{"version":3,"file":"ngxtension-create-injection-token.mjs","sources":["../../../../libs/ngxtension/create-injection-token/src/create-injection-token.ts","../../../../libs/ngxtension/create-injection-token/src/ngxtension-create-injection-token.ts"],"sourcesContent":["import {\n\tENVIRONMENT_INITIALIZER,\n\tInjectionToken,\n\tinject,\n\trunInInjectionContext,\n\ttype EnvironmentProviders,\n\ttype FactoryProvider,\n\ttype Host,\n\ttype InjectOptions,\n\ttype Injector,\n\ttype Optional,\n\ttype Provider,\n\ttype Self,\n\ttype SkipSelf,\n\ttype Type,\n} from '@angular/core';\nimport { assertInjector } from 'ngxtension/assert-injector';\n\ntype CreateInjectionTokenDep<TTokenType> =\n\t| Type<TTokenType>\n\t// NOTE: we don't have an AbstractType\n\t| (abstract new (...args: any[]) => TTokenType)\n\t| InjectionToken<TTokenType>;\n\ntype CreateInjectionTokenDeps<\n\tTFactory extends (...args: any[]) => any,\n\tTFactoryDeps extends Parameters<TFactory> = Parameters<TFactory>,\n> = {\n\t[Index in keyof TFactoryDeps]:\n\t\t| CreateInjectionTokenDep<TFactoryDeps[Index]>\n\t\t| [\n\t\t\t\t...modifiers: Array<Optional | Self | SkipSelf | Host>,\n\t\t\t\ttoken: CreateInjectionTokenDep<TFactoryDeps[Index]>,\n\t\t  ];\n} & { length: TFactoryDeps['length'] };\n\nexport type CreateInjectionTokenOptions<\n\tTFactory extends (...args: any[]) => any,\n\tTFactoryDeps extends Parameters<TFactory> = Parameters<TFactory>,\n> =\n\t// this means TFunction has no parameters\n\t(TFactoryDeps[0] extends undefined\n\t\t? { deps?: never }\n\t\t: { deps: CreateInjectionTokenDeps<TFactory, TFactoryDeps> }) & {\n\t\tisRoot?: boolean;\n\t\tisFunctionValue?: boolean;\n\t\tmulti?: boolean;\n\t\ttoken?: InjectionToken<ReturnType<TFactory>>;\n\t\textraProviders?: Provider | EnvironmentProviders;\n\t};\n\ntype CreateProvideFnOptions<\n\tTFactory extends (...args: any[]) => any,\n\tTFactoryDeps extends Parameters<TFactory> = Parameters<TFactory>,\n> = Pick<\n\tCreateInjectionTokenOptions<TFactory, TFactoryDeps>,\n\t'deps' | 'extraProviders' | 'multi' | 'isFunctionValue'\n>;\n\ntype InjectFn<TFactoryReturn> = {\n\t(): TFactoryReturn;\n\t(\n\t\tinjectOptions: InjectOptions & { optional?: false } & {\n\t\t\tinjector?: Injector;\n\t\t},\n\t): TFactoryReturn;\n\t(\n\t\tinjectOptions: InjectOptions & { injector?: Injector },\n\t): TFactoryReturn | null;\n};\n\ntype ProvideFn<\n\tTNoop extends boolean,\n\tTFactoryReturn,\n\tTReturn = TFactoryReturn extends Array<infer Item> ? Item : TFactoryReturn,\n> = (TNoop extends true\n\t? (value: TReturn | (() => TReturn)) => Provider\n\t: () => Provider) &\n\t(TReturn extends Function\n\t\t? (value: TReturn | (() => TReturn), isFunctionValue: boolean) => Provider\n\t\t: (value: TReturn | (() => TReturn)) => Provider);\n\nexport type CreateInjectionTokenReturn<\n\tTFactoryReturn,\n\tTNoop extends boolean = false,\n> = [\n\tInjectFn<TFactoryReturn>,\n\tProvideFn<TNoop, TFactoryReturn>,\n\tInjectionToken<TFactoryReturn>,\n\t() => Provider,\n];\n\nfunction createInjectFn<TValue>(token: InjectionToken<TValue>) {\n\treturn function (\n\t\tthis: Function,\n\t\t{\n\t\t\tinjector,\n\t\t\t...injectOptions\n\t\t}: InjectOptions & { injector?: Injector } = {},\n\t) {\n\t\tinjector = assertInjector(this, injector);\n\t\treturn runInInjectionContext(injector, () =>\n\t\t\tinject(token, injectOptions as InjectOptions),\n\t\t);\n\t};\n}\n\nfunction createProvideFn<\n\tTValue,\n\tTFactory extends (...args: any[]) => any = (...args: any[]) => TValue,\n\tTFactoryDeps extends Parameters<TFactory> = Parameters<TFactory>,\n>(\n\ttoken: InjectionToken<TValue>,\n\tfactory: (...args: any[]) => TValue,\n\topts: CreateProvideFnOptions<TFactory, TFactoryDeps> = {},\n) {\n\tconst {\n\t\tdeps = [],\n\t\tmulti = false,\n\t\textraProviders = [],\n\t\tisFunctionValue: isFunctionValueFromOpts = false,\n\t} = opts;\n\treturn (\n\t\tvalue?: TValue | (() => TValue),\n\t\tisFunctionValue = isFunctionValueFromOpts,\n\t) => {\n\t\tlet provider: Provider;\n\t\tif (typeof value !== 'undefined') {\n\t\t\t// TODO: (chau) maybe this can be made better\n\t\t\tconst factory =\n\t\t\t\ttypeof value === 'function'\n\t\t\t\t\t? isFunctionValue\n\t\t\t\t\t\t? () => value\n\t\t\t\t\t\t: value\n\t\t\t\t\t: () => value;\n\n\t\t\tprovider = {\n\t\t\t\tprovide: token,\n\t\t\t\tuseFactory: factory,\n\t\t\t\tmulti,\n\t\t\t};\n\t\t} else {\n\t\t\tprovider = {\n\t\t\t\tprovide: token,\n\t\t\t\tuseFactory: factory,\n\t\t\t\tdeps: deps as FactoryProvider['deps'],\n\t\t\t\tmulti,\n\t\t\t};\n\t\t}\n\n\t\treturn [extraProviders, provider];\n\t};\n}\n\n/**\n * `createInjectionToken` accepts a factory function and returns a tuple of `injectFn`, `provideFn`, and the `InjectionToken`\n * that the factory function is for.\n *\n * @param {Function} factory - Factory Function that returns the value for the `InjectionToken`\n * @param {CreateInjectionTokenOptions} options - object to control how the `InjectionToken` behaves\n * @returns {CreateInjectionTokenReturn}\n *\n * @example\n * ```ts\n * const [injectCounter, provideCounter, COUNTER] = createInjectionToken(() => signal(0));\n *\n * export class Counter {\n *  counter = injectCounter(); // WritableSignal<number>\n * }\n * ```\n */\nexport function createInjectionToken<\n\tTFactory extends (...args: any[]) => any,\n\tTFactoryDeps extends Parameters<TFactory> = Parameters<TFactory>,\n\tTOptions extends CreateInjectionTokenOptions<\n\t\tTFactory,\n\t\tTFactoryDeps\n\t> = CreateInjectionTokenOptions<TFactory, TFactoryDeps>,\n\tTFactoryReturn = TOptions['multi'] extends true\n\t\t? Array<ReturnType<TFactory>>\n\t\t: ReturnType<TFactory>,\n>(\n\tfactory: TFactory,\n\toptions?: TOptions,\n): CreateInjectionTokenReturn<TFactoryReturn> {\n\tconst tokenName = factory.name || factory.toString();\n\tconst opts =\n\t\toptions ??\n\t\t({ isRoot: true } as CreateInjectionTokenOptions<TFactory, TFactoryDeps>);\n\n\topts.isRoot ??= true;\n\n\t// NOTE: multi tokens cannot be a root token. It has to be provided (provideFn needs to be invoked)\n\t// for the 'multi' flag to work properly\n\tif (opts.multi) {\n\t\topts.isRoot = false;\n\t}\n\n\tif (opts.isRoot) {\n\t\tif (opts.token) {\n\t\t\tthrow new Error(`\\\ncreateInjectionToken is creating a root InjectionToken but an external token is passed in.\n`);\n\t\t}\n\n\t\tconst token = new InjectionToken<TFactoryReturn>(`Token for ${tokenName}`, {\n\t\t\tfactory: () => {\n\t\t\t\tif (opts.deps && Array.isArray(opts.deps)) {\n\t\t\t\t\treturn factory(\n\t\t\t\t\t\t...opts.deps.map((dep) => {\n\t\t\t\t\t\t\tdep = (\n\t\t\t\t\t\t\t\tArray.isArray(dep) ? dep.at(-1) : dep\n\t\t\t\t\t\t\t) as CreateInjectionTokenDep<any>;\n\t\t\t\t\t\t\treturn inject(dep);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn factory();\n\t\t\t},\n\t\t});\n\n\t\tconst injectFn = createInjectFn(\n\t\t\ttoken,\n\t\t) as CreateInjectionTokenReturn<TFactoryReturn>[0];\n\n\t\treturn [\n\t\t\tinjectFn,\n\t\t\tcreateProvideFn(\n\t\t\t\ttoken,\n\t\t\t\tfactory,\n\t\t\t\topts as CreateProvideFnOptions<TFactory, TFactoryDeps>,\n\t\t\t) as CreateInjectionTokenReturn<TFactoryReturn>[1],\n\t\t\ttoken,\n\t\t\t() => ({\n\t\t\t\tprovide: ENVIRONMENT_INITIALIZER,\n\t\t\t\tuseValue: () => injectFn(),\n\t\t\t\tmulti: true,\n\t\t\t}),\n\t\t];\n\t}\n\n\tconst token =\n\t\topts.token || new InjectionToken<TFactoryReturn>(`Token for ${tokenName}`);\n\treturn [\n\t\tcreateInjectFn(token) as CreateInjectionTokenReturn<TFactoryReturn>[0],\n\t\tcreateProvideFn(\n\t\t\ttoken,\n\t\t\tfactory,\n\t\t\topts as CreateProvideFnOptions<TFactory, TFactoryDeps>,\n\t\t) as CreateInjectionTokenReturn<TFactoryReturn>[1],\n\t\ttoken,\n\t\t() => [],\n\t];\n}\n\nexport function createNoopInjectionToken<\n\tTValue,\n\tTMulti extends boolean = false,\n\tTOptions = Pick<\n\t\tCreateInjectionTokenOptions<() => void, []>,\n\t\t'extraProviders'\n\t> &\n\t\t(TValue extends (...args: any[]) => any\n\t\t\t? { isFunctionValue: true }\n\t\t\t: { isFunctionValue?: never }) &\n\t\t(TMulti extends true ? { multi: true } : { multi?: never }),\n>(description: string, options?: TOptions) {\n\ttype TReturn = TMulti extends true ? Array<TValue> : TValue;\n\n\tconst token =\n\t\t(options as CreateInjectionTokenOptions<() => void, []>)?.token ||\n\t\tnew InjectionToken<TReturn>(description);\n\treturn [\n\t\tcreateInjectFn(token) as CreateInjectionTokenReturn<TReturn, true>[0],\n\t\tcreateProvideFn(\n\t\t\ttoken,\n\t\t\t() => null!,\n\t\t\t(options || {}) as CreateProvideFnOptions<() => void, []>,\n\t\t) as CreateInjectionTokenReturn<TReturn, true>[1],\n\t\ttoken,\n\t\t() => [],\n\t] as CreateInjectionTokenReturn<TReturn, true>;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}