diff --git a/devisfuture-electron-modular-1.2.16.tgz b/devisfuture-electron-modular-1.2.16.tgz new file mode 100644 index 0000000..6d88f28 Binary files /dev/null and b/devisfuture-electron-modular-1.2.16.tgz differ diff --git a/package.json b/package.json index 5bf5bda..af97b22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@devisfuture/electron-modular", - "version": "1.2.16", + "version": "1.2.17", "description": "Core module system, DI container, IPC handlers, and window utilities for Electron main process.", "type": "module", "main": "./dist/index.js", @@ -35,14 +35,13 @@ "peerDependencies": { "electron": ">=36" }, - "dependencies": { - "reflect-metadata": "^0.2.2" - }, + "dependencies": {}, "devDependencies": { "@types/node": "^20.11.0", "@vitest/coverage-v8": "^2.1.9", "@vitest/ui": "^2.1.9", "electron": "^36.4.0", + "reflect-metadata": "^0.2.2", "typescript": "^5.7.2", "vitest": "^2.1.8" }, diff --git a/src/@core/decorators/inject.ts b/src/@core/decorators/inject.ts index 7f0b144..a1bd33d 100644 --- a/src/@core/decorators/inject.ts +++ b/src/@core/decorators/inject.ts @@ -10,7 +10,7 @@ * @module @core/decorators/inject */ -import "reflect-metadata/lite"; +import "../../reflect-metadata.js"; import type { TProviderToken } from "../types/provider.js"; /** Maps parameter index to provider token */ @@ -43,8 +43,10 @@ export const Inject = (token: TProviderToken): ParameterDecorator => { return; } - const existingTokens: TInjectTokensMetadata = - Reflect.getMetadata(INJECT_TOKENS_METADATA_KEY, target) ?? {}; + const existingTokens = + (Reflect.getMetadata(INJECT_TOKENS_METADATA_KEY, target) as + | TInjectTokensMetadata + | undefined) ?? ({} as TInjectTokensMetadata); existingTokens[parameterIndex] = token; @@ -61,5 +63,9 @@ export const Inject = (token: TProviderToken): ParameterDecorator => { * @returns Map of parameter index to provider token */ export const getInjectedTokens = (target: Function): TInjectTokensMetadata => { - return Reflect.getMetadata(INJECT_TOKENS_METADATA_KEY, target) ?? {}; + return ( + (Reflect.getMetadata(INJECT_TOKENS_METADATA_KEY, target) as + | TInjectTokensMetadata + | undefined) ?? ({} as TInjectTokensMetadata) + ); }; diff --git a/src/@core/decorators/injectable.ts b/src/@core/decorators/injectable.ts index 2bf7e92..59a20a5 100644 --- a/src/@core/decorators/injectable.ts +++ b/src/@core/decorators/injectable.ts @@ -9,7 +9,7 @@ * @module @core/decorators/injectable */ -import "reflect-metadata/lite"; +import "../../reflect-metadata.js"; /** * Decorator that marks a class as injectable into the DI container. diff --git a/src/@core/decorators/ipc-handler.ts b/src/@core/decorators/ipc-handler.ts index 19bd632..0fb25f8 100644 --- a/src/@core/decorators/ipc-handler.ts +++ b/src/@core/decorators/ipc-handler.ts @@ -9,7 +9,7 @@ * @module @core/decorators/ipc-handler */ -import "reflect-metadata/lite"; +import "../../reflect-metadata.js"; /** * Decorator that marks a class as an IPC handler. diff --git a/src/@core/decorators/rg-module.ts b/src/@core/decorators/rg-module.ts index 6e0218f..4256e1d 100644 --- a/src/@core/decorators/rg-module.ts +++ b/src/@core/decorators/rg-module.ts @@ -11,7 +11,7 @@ * @module @core/decorators/rg-module */ -import "reflect-metadata/lite"; +import "../../reflect-metadata.js"; import type { RgModuleMetadata } from "../types/module-metadata.js"; /** diff --git a/src/@core/decorators/window-manager.ts b/src/@core/decorators/window-manager.ts index 3b08f3e..7b7994a 100644 --- a/src/@core/decorators/window-manager.ts +++ b/src/@core/decorators/window-manager.ts @@ -9,7 +9,7 @@ * @module @core/decorators/window-manager */ -import "reflect-metadata/lite"; +import "../../reflect-metadata.js"; import type { TParamsCreateWindow } from "../control-window/types.js"; /** diff --git a/src/@core/utils/dependency-tokens.ts b/src/@core/utils/dependency-tokens.ts index 5da002d..6823619 100644 --- a/src/@core/utils/dependency-tokens.ts +++ b/src/@core/utils/dependency-tokens.ts @@ -7,7 +7,7 @@ * @module @core/utils/dependency-tokens */ -import "reflect-metadata/lite"; +import "../../reflect-metadata.js"; import type { Constructor } from "../types/constructor.js"; import type { TProviderToken } from "../types/provider.js"; import { getInjectedTokens } from "../decorators/inject.js"; diff --git a/src/index.ts b/src/index.ts index 1e397d4..fbbe469 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,5 @@ +import "./reflect-metadata.js"; + // Container export * from "./@core/container.js"; diff --git a/src/reflect-metadata.ts b/src/reflect-metadata.ts new file mode 100644 index 0000000..f127f96 --- /dev/null +++ b/src/reflect-metadata.ts @@ -0,0 +1,160 @@ +type TMetadataStore = Map>; + +const targetMetadataStore = new WeakMap(); + +const getOrCreatePropertyMetadata = ( + target: object, + propertyKey?: PropertyKey, +): Map => { + let propertiesMetadata = targetMetadataStore.get(target); + + if (propertiesMetadata === undefined) { + propertiesMetadata = new Map< + PropertyKey | undefined, + Map + >(); + targetMetadataStore.set(target, propertiesMetadata); + } + + let propertyMetadata = propertiesMetadata.get(propertyKey); + + if (propertyMetadata === undefined) { + propertyMetadata = new Map(); + propertiesMetadata.set(propertyKey, propertyMetadata); + } + + return propertyMetadata; +}; + +const getPropertyMetadata = ( + target: object, + propertyKey?: PropertyKey, +): Map | undefined => { + return targetMetadataStore.get(target)?.get(propertyKey); +}; + +if (Reflect.defineMetadata === undefined) { + Reflect.defineMetadata = ( + metadataKey: unknown, + metadataValue: unknown, + target: object, + propertyKey?: PropertyKey, + ): void => { + const propertyMetadata = getOrCreatePropertyMetadata(target, propertyKey); + propertyMetadata.set(metadataKey, metadataValue); + }; +} + +if (Reflect.getOwnMetadata === undefined) { + Reflect.getOwnMetadata = ( + metadataKey: unknown, + target: object, + propertyKey?: PropertyKey, + ): unknown => { + return getPropertyMetadata(target, propertyKey)?.get(metadataKey); + }; +} + +if (Reflect.getMetadata === undefined) { + Reflect.getMetadata = ( + metadataKey: unknown, + target: object, + propertyKey?: PropertyKey, + ): unknown => { + let currentTarget: object | null = target; + + while (currentTarget !== null) { + const metadataValue = Reflect.getOwnMetadata( + metadataKey, + currentTarget, + propertyKey, + ); + + if (metadataValue !== undefined) { + return metadataValue; + } + + currentTarget = Object.getPrototypeOf(currentTarget); + } + + return undefined; + }; +} + +if (Reflect.hasOwnMetadata === undefined) { + Reflect.hasOwnMetadata = ( + metadataKey: unknown, + target: object, + propertyKey?: PropertyKey, + ): boolean => { + return getPropertyMetadata(target, propertyKey)?.has(metadataKey) ?? false; + }; +} + +if (Reflect.hasMetadata === undefined) { + Reflect.hasMetadata = ( + metadataKey: unknown, + target: object, + propertyKey?: PropertyKey, + ): boolean => { + let currentTarget: object | null = target; + + while (currentTarget !== null) { + if (Reflect.hasOwnMetadata(metadataKey, currentTarget, propertyKey)) { + return true; + } + + currentTarget = Object.getPrototypeOf(currentTarget); + } + + return false; + }; +} + +if (Reflect.metadata === undefined) { + Reflect.metadata = ( + metadataKey: unknown, + metadataValue: unknown, + ): ClassDecorator & PropertyDecorator => { + return (target: object, propertyKey?: string | symbol): void => { + Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey); + }; + }; +} + +declare global { + namespace Reflect { + function defineMetadata( + metadataKey: unknown, + metadataValue: unknown, + target: object, + propertyKey?: PropertyKey, + ): void; + function getOwnMetadata( + metadataKey: unknown, + target: object, + propertyKey?: PropertyKey, + ): unknown; + function getMetadata( + metadataKey: unknown, + target: object, + propertyKey?: PropertyKey, + ): unknown; + function hasOwnMetadata( + metadataKey: unknown, + target: object, + propertyKey?: PropertyKey, + ): boolean; + function hasMetadata( + metadataKey: unknown, + target: object, + propertyKey?: PropertyKey, + ): boolean; + function metadata( + metadataKey: unknown, + metadataValue: unknown, + ): ClassDecorator & PropertyDecorator; + } +} + +export {};