@mmstack/di 19.3.2 → 20.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,49 +12,12 @@ class ScopeRegistry {
12
12
  this.registry.set(factory, val);
13
13
  return val;
14
14
  }
15
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScopeRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
16
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScopeRegistry });
15
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ScopeRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
16
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ScopeRegistry });
17
17
  }
18
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScopeRegistry, decorators: [{
18
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ScopeRegistry, decorators: [{
19
19
  type: Injectable
20
20
  }] });
21
- /**
22
- * Creates a specialized dependency injection scope.
23
- *
24
- * This utility allows you to create a localized dependency injection scope where you can
25
- * register and provide shared state, services, or primitives that are bound to a specific
26
- * component tree instead of the global root injector.
27
- *
28
- * @param name Optional name for the scope, primarily used for debugging and error messages.
29
- * @returns A tuple containing `[registerFn, provideFn]`:
30
- * - `registerFn`: A function to register a factory within the scope. Returns an injection function to retrieve the value.
31
- * - `provideFn`: An Angular provider function that must be added to the `providers` array where the scope begins.
32
- *
33
- * @example
34
- * ```ts
35
- * const [registerInUserScope, provideUserScope] = createScope('UserScope');
36
- *
37
- * // Define a state/service bound to this scope
38
- * const injectUserState = registerInUserScope(() => signal({ name: 'John Doe' }));
39
- * const injectLogger = registerInUserScope(() => {
40
- * const globalLogger = inject(GlobalLogger);
41
- * const user = injectUserState();
42
- * return {
43
- * log: (msg: string) => globalLogger.log(`[USER MODULE (${user().name})]: ${msg}`),
44
- * }
45
- * })
46
- * @Component({
47
- * providers: [provideUserScope()] // provides a new instance of every dependency registered to the scope
48
- * })
49
- * class ParentComponent {}
50
- *
51
- * @Component({})
52
- * class ChildComponent {
53
- * readonly userState = injectUserState();
54
- * readonly logger = injectLogger();
55
- * }
56
- * ```
57
- */
58
21
  function createScope(name) {
59
22
  const token = new InjectionToken(name ?? '@mmstack/di/scope');
60
23
  const provideFn = () => ({
@@ -1 +1 @@
1
- {"version":3,"file":"mmstack-di.mjs","sources":["../../../../packages/di/src/lib/create-scope.ts","../../../../packages/di/src/lib/injectable.ts","../../../../packages/di/src/lib/root-injectable.ts","../../../../packages/di/src/mmstack-di.ts"],"sourcesContent":["import {\n inject,\n Injectable,\n InjectionToken,\n Injector,\n runInInjectionContext,\n type Provider,\n} from '@angular/core';\n\n@Injectable()\nexport class ScopeRegistry {\n private readonly injector = inject(Injector);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n private readonly registry = new Map<Function, any>();\n\n getOrCreate<T>(factory: () => T): T {\n if (this.registry.has(factory)) return this.registry.get(factory);\n\n const val = runInInjectionContext(this.injector, factory);\n this.registry.set(factory, val);\n return val;\n }\n}\n\n/**\n * Creates a specialized dependency injection scope.\n *\n * This utility allows you to create a localized dependency injection scope where you can\n * register and provide shared state, services, or primitives that are bound to a specific\n * component tree instead of the global root injector.\n *\n * @param name Optional name for the scope, primarily used for debugging and error messages.\n * @returns A tuple containing `[registerFn, provideFn]`:\n * - `registerFn`: A function to register a factory within the scope. Returns an injection function to retrieve the value.\n * - `provideFn`: An Angular provider function that must be added to the `providers` array where the scope begins.\n *\n * @example\n * ```ts\n * const [registerInUserScope, provideUserScope] = createScope('UserScope');\n *\n * // Define a state/service bound to this scope\n * const injectUserState = registerInUserScope(() => signal({ name: 'John Doe' }));\n * const injectLogger = registerInUserScope(() => {\n * const globalLogger = inject(GlobalLogger);\n * const user = injectUserState();\n * return {\n * log: (msg: string) => globalLogger.log(`[USER MODULE (${user().name})]: ${msg}`),\n * }\n * })\n * @Component({\n * providers: [provideUserScope()] // provides a new instance of every dependency registered to the scope\n * })\n * class ParentComponent {}\n *\n * @Component({})\n * class ChildComponent {\n * readonly userState = injectUserState();\n * readonly logger = injectLogger();\n * }\n * ```\n */\nexport function createScope(name?: string) {\n const token = new InjectionToken<ScopeRegistry>(name ?? '@mmstack/di/scope');\n\n const provideFn = (): Provider => ({\n provide: token,\n useClass: ScopeRegistry,\n });\n\n const registerFn = <T>(factory: () => T) => {\n return () => {\n const registry = inject(token, { optional: true });\n if (!registry)\n throw new Error(\n `[mmstack/di]: Scope ${name ?? 'unknown'} not found. Please make sure you provide it`,\n );\n\n return registry.getOrCreate(factory);\n };\n };\n\n return [registerFn, provideFn] as const;\n}\n","import {\n inject,\n InjectionToken,\n type AbstractType,\n type InjectOptions,\n type Provider,\n type Type,\n} from '@angular/core';\n\ntype ServiceType<T> =\n T extends Type<infer U>\n ? U\n : T extends AbstractType<infer U>\n ? U\n : T extends InjectionToken<infer U>\n ? U\n : never;\n\ntype MapDeps<T extends readonly any[]> = {\n [K in keyof T]: ServiceType<T[K]>;\n};\n\ntype ProviderFn<T> = {\n (value: T): Provider;\n <const TDeps extends any[]>(\n fn: (...deps: MapDeps<TDeps>) => T,\n deps: TDeps,\n ): Provider;\n};\n\ntype InjectFns<T> = [\n (opt?: Omit<InjectOptions, 'optional'>) => T,\n ProviderFn<T>,\n];\n\ntype FallbackInjectableOptions<T> = {\n /** Default value returned when the injectable is not provided */\n fallback: T;\n};\n\ntype LazyFallbackInjectableOptions<T> = {\n /** Function that returns a default value when the injectable is not provided. Useful for expensive defaults. */\n lazyFallback: () => T;\n};\n\ntype ErrorMessageInjectableOptions = {\n /** Error message thrown when the injectable is not provided */\n errorMessage: string;\n};\n\ntype InjectableOptions<T> =\n | FallbackInjectableOptions<T>\n | LazyFallbackInjectableOptions<T>\n | ErrorMessageInjectableOptions;\n\n/**\n * Creates a typed InjectionToken with inject and provide helper functions.\n *\n * @param token - Unique token identifier\n * @param opt - Optional configuration for fallback value or error message\n * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection\n */\nexport function injectable<T>(token: string): InjectFns<T | null>;\n\n/**\n * Creates a typed InjectionToken with inject and provide helper functions.\n * Returns a fallback value when the injectable is not provided.\n *\n * @param token - Unique token identifier\n * @param opt - Configuration with fallback value\n * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection\n */\nexport function injectable<T>(\n token: string,\n opt: FallbackInjectableOptions<T>,\n): InjectFns<T>;\n\n/**\n *\n * Creates a typed InjectionToken with inject and provide helper functions.\n * Returns a lazily evaluated fallback value when the injectable is not provided.\n *\n * @param token\n * @param opt\n */\nexport function injectable<T>(\n token: string,\n opt: LazyFallbackInjectableOptions<T>,\n): InjectFns<T>;\n\n/**\n * Creates a typed InjectionToken with inject and provide helper functions.\n * Throws an error with a custom message when the injectable is not provided.\n *\n * @param token - Unique token identifier\n * @param opt - Configuration with error message\n * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection\n */\nexport function injectable<T>(\n token: string,\n opt: ErrorMessageInjectableOptions,\n): InjectFns<T>;\n\nexport function injectable<T>(\n token: string,\n opt?: InjectableOptions<T>,\n): InjectFns<T> {\n const injectionToken = new InjectionToken<T>(token);\n\n const options = opt as\n | Partial<\n FallbackInjectableOptions<T> &\n LazyFallbackInjectableOptions<T> &\n ErrorMessageInjectableOptions\n >\n | undefined;\n\n let fallback: T | undefined | null = options?.fallback;\n\n const initFallback =\n options?.lazyFallback ?? (() => options?.fallback ?? null);\n\n const fallbackFn = () => {\n if (fallback === undefined) fallback = initFallback();\n return fallback;\n };\n\n const injectFn = (iOpt?: Omit<InjectOptions, 'optional'>) => {\n const injected =\n inject(injectionToken, {\n ...iOpt,\n optional: true,\n }) ?? fallbackFn();\n\n if (injected === null && options?.errorMessage)\n throw new Error(options.errorMessage);\n\n return injected as T;\n };\n\n const provideFn = (\n fnOrValue: T | ((...deps: any[]) => T),\n deps?: any[],\n ): Provider => {\n if (deps !== undefined)\n return {\n provide: injectionToken,\n useFactory: fnOrValue as (...args: any[]) => T,\n deps,\n };\n\n return {\n provide: injectionToken,\n useValue: fnOrValue,\n };\n };\n\n return [injectFn, provideFn];\n}\n","import { inject, InjectionToken, Injector } from '@angular/core';\n\n/**\n * Creates a tree-shakable root singleton without a class.\n * @example const injectUser = rootInjectable(() => ({ name: signal('John') }));\n */\nexport function rootInjectable<T>(\n factory: (injector: Injector) => T, // Keeping the injector just in case\n name?: string,\n): () => T {\n const token = new InjectionToken<T>(name ?? '@mmstack/di/root-injectable', {\n providedIn: 'root',\n factory: () => factory(inject(Injector)),\n });\n\n return () => inject(token);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mmstack-di.mjs","sources":["../../../../packages/di/src/lib/create-scope.ts","../../../../packages/di/src/lib/injectable.ts","../../../../packages/di/src/lib/root-injectable.ts","../../../../packages/di/src/mmstack-di.ts"],"sourcesContent":["import {\n inject,\n Injectable,\n InjectionToken,\n Injector,\n runInInjectionContext,\n type Provider,\n} from '@angular/core';\n\n@Injectable()\nexport class ScopeRegistry {\n private readonly injector = inject(Injector);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n private readonly registry = new Map<Function, any>();\n\n getOrCreate<T>(factory: () => T): T {\n if (this.registry.has(factory)) return this.registry.get(factory);\n\n const val = runInInjectionContext(this.injector, factory);\n this.registry.set(factory, val);\n return val;\n }\n}\n\nexport function createScope(name?: string) {\n const token = new InjectionToken<ScopeRegistry>(name ?? '@mmstack/di/scope');\n\n const provideFn = (): Provider => ({\n provide: token,\n useClass: ScopeRegistry,\n });\n\n const registerFn = <T>(factory: () => T) => {\n return () => {\n const registry = inject(token, { optional: true });\n if (!registry)\n throw new Error(\n `[mmstack/di]: Scope ${name ?? 'unknown'} not found. Please make sure you provide it`,\n );\n\n return registry.getOrCreate(factory);\n };\n };\n\n return [registerFn, provideFn] as const;\n}\n","import {\n inject,\n InjectionToken,\n type AbstractType,\n type InjectOptions,\n type Provider,\n type Type,\n} from '@angular/core';\n\ntype ServiceType<T> =\n T extends Type<infer U>\n ? U\n : T extends AbstractType<infer U>\n ? U\n : T extends InjectionToken<infer U>\n ? U\n : never;\n\ntype MapDeps<T extends readonly any[]> = {\n [K in keyof T]: ServiceType<T[K]>;\n};\n\ntype ProviderFn<T> = {\n (value: T): Provider;\n <const TDeps extends any[]>(\n fn: (...deps: MapDeps<TDeps>) => T,\n deps: TDeps,\n ): Provider;\n};\n\ntype InjectFns<T> = [\n (opt?: Omit<InjectOptions, 'optional'>) => T,\n ProviderFn<T>,\n];\n\ntype FallbackInjectableOptions<T> = {\n /** Default value returned when the injectable is not provided */\n fallback: T;\n};\n\ntype LazyFallbackInjectableOptions<T> = {\n /** Function that returns a default value when the injectable is not provided. Useful for expensive defaults. */\n lazyFallback: () => T;\n};\n\ntype ErrorMessageInjectableOptions = {\n /** Error message thrown when the injectable is not provided */\n errorMessage: string;\n};\n\ntype InjectableOptions<T> =\n | FallbackInjectableOptions<T>\n | LazyFallbackInjectableOptions<T>\n | ErrorMessageInjectableOptions;\n\n/**\n * Creates a typed InjectionToken with inject and provide helper functions.\n *\n * @param token - Unique token identifier\n * @param opt - Optional configuration for fallback value or error message\n * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection\n */\nexport function injectable<T>(token: string): InjectFns<T | null>;\n\n/**\n * Creates a typed InjectionToken with inject and provide helper functions.\n * Returns a fallback value when the injectable is not provided.\n *\n * @param token - Unique token identifier\n * @param opt - Configuration with fallback value\n * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection\n */\nexport function injectable<T>(\n token: string,\n opt: FallbackInjectableOptions<T>,\n): InjectFns<T>;\n\n/**\n *\n * Creates a typed InjectionToken with inject and provide helper functions.\n * Returns a lazily evaluated fallback value when the injectable is not provided.\n *\n * @param token\n * @param opt\n */\nexport function injectable<T>(\n token: string,\n opt: LazyFallbackInjectableOptions<T>,\n): InjectFns<T>;\n\n/**\n * Creates a typed InjectionToken with inject and provide helper functions.\n * Throws an error with a custom message when the injectable is not provided.\n *\n * @param token - Unique token identifier\n * @param opt - Configuration with error message\n * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection\n */\nexport function injectable<T>(\n token: string,\n opt: ErrorMessageInjectableOptions,\n): InjectFns<T>;\n\nexport function injectable<T>(\n token: string,\n opt?: InjectableOptions<T>,\n): InjectFns<T> {\n const injectionToken = new InjectionToken<T>(token);\n\n const options = opt as\n | Partial<\n FallbackInjectableOptions<T> &\n LazyFallbackInjectableOptions<T> &\n ErrorMessageInjectableOptions\n >\n | undefined;\n\n let fallback: T | undefined | null = options?.fallback;\n\n const initFallback =\n options?.lazyFallback ?? (() => options?.fallback ?? null);\n\n const fallbackFn = () => {\n if (fallback === undefined) fallback = initFallback();\n return fallback;\n };\n\n const injectFn = (iOpt?: Omit<InjectOptions, 'optional'>) => {\n const injected =\n inject(injectionToken, {\n ...iOpt,\n optional: true,\n }) ?? fallbackFn();\n\n if (injected === null && options?.errorMessage)\n throw new Error(options.errorMessage);\n\n return injected as T;\n };\n\n const provideFn = (\n fnOrValue: T | ((...deps: any[]) => T),\n deps?: any[],\n ): Provider => {\n if (deps !== undefined)\n return {\n provide: injectionToken,\n useFactory: fnOrValue as (...args: any[]) => T,\n deps,\n };\n\n return {\n provide: injectionToken,\n useValue: fnOrValue,\n };\n };\n\n return [injectFn, provideFn];\n}\n","import { inject, InjectionToken, Injector } from '@angular/core';\n\n/**\n * Creates a tree-shakable root singleton without a class.\n * @example const injectUser = rootInjectable(() => ({ name: signal('John') }));\n */\nexport function rootInjectable<T>(\n factory: (injector: Injector) => T, // Keeping the injector just in case\n name?: string,\n): () => T {\n const token = new InjectionToken<T>(name ?? '@mmstack/di/root-injectable', {\n providedIn: 'root',\n factory: () => factory(inject(Injector)),\n });\n\n return () => inject(token);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/index.d.ts CHANGED
@@ -1,3 +1,72 @@
1
- export { createScope } from './lib/create-scope';
2
- export * from './lib/injectable';
3
- export { rootInjectable } from './lib/root-injectable';
1
+ import { Provider, InjectOptions, Type, AbstractType, InjectionToken, Injector } from '@angular/core';
2
+
3
+ declare function createScope(name?: string): readonly [<T>(factory: () => T) => () => T, () => Provider];
4
+
5
+ type ServiceType<T> = T extends Type<infer U> ? U : T extends AbstractType<infer U> ? U : T extends InjectionToken<infer U> ? U : never;
6
+ type MapDeps<T extends readonly any[]> = {
7
+ [K in keyof T]: ServiceType<T[K]>;
8
+ };
9
+ type ProviderFn<T> = {
10
+ (value: T): Provider;
11
+ <const TDeps extends any[]>(fn: (...deps: MapDeps<TDeps>) => T, deps: TDeps): Provider;
12
+ };
13
+ type InjectFns<T> = [
14
+ (opt?: Omit<InjectOptions, 'optional'>) => T,
15
+ ProviderFn<T>
16
+ ];
17
+ type FallbackInjectableOptions<T> = {
18
+ /** Default value returned when the injectable is not provided */
19
+ fallback: T;
20
+ };
21
+ type LazyFallbackInjectableOptions<T> = {
22
+ /** Function that returns a default value when the injectable is not provided. Useful for expensive defaults. */
23
+ lazyFallback: () => T;
24
+ };
25
+ type ErrorMessageInjectableOptions = {
26
+ /** Error message thrown when the injectable is not provided */
27
+ errorMessage: string;
28
+ };
29
+ /**
30
+ * Creates a typed InjectionToken with inject and provide helper functions.
31
+ *
32
+ * @param token - Unique token identifier
33
+ * @param opt - Optional configuration for fallback value or error message
34
+ * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection
35
+ */
36
+ declare function injectable<T>(token: string): InjectFns<T | null>;
37
+ /**
38
+ * Creates a typed InjectionToken with inject and provide helper functions.
39
+ * Returns a fallback value when the injectable is not provided.
40
+ *
41
+ * @param token - Unique token identifier
42
+ * @param opt - Configuration with fallback value
43
+ * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection
44
+ */
45
+ declare function injectable<T>(token: string, opt: FallbackInjectableOptions<T>): InjectFns<T>;
46
+ /**
47
+ *
48
+ * Creates a typed InjectionToken with inject and provide helper functions.
49
+ * Returns a lazily evaluated fallback value when the injectable is not provided.
50
+ *
51
+ * @param token
52
+ * @param opt
53
+ */
54
+ declare function injectable<T>(token: string, opt: LazyFallbackInjectableOptions<T>): InjectFns<T>;
55
+ /**
56
+ * Creates a typed InjectionToken with inject and provide helper functions.
57
+ * Throws an error with a custom message when the injectable is not provided.
58
+ *
59
+ * @param token - Unique token identifier
60
+ * @param opt - Configuration with error message
61
+ * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection
62
+ */
63
+ declare function injectable<T>(token: string, opt: ErrorMessageInjectableOptions): InjectFns<T>;
64
+
65
+ /**
66
+ * Creates a tree-shakable root singleton without a class.
67
+ * @example const injectUser = rootInjectable(() => ({ name: signal('John') }));
68
+ */
69
+ declare function rootInjectable<T>(factory: (injector: Injector) => T, // Keeping the injector just in case
70
+ name?: string): () => T;
71
+
72
+ export { createScope, injectable, rootInjectable };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmstack/di",
3
- "version": "19.3.2",
3
+ "version": "20.5.1",
4
4
  "keywords": [
5
5
  "angular",
6
6
  "dependency injection",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "homepage": "https://github.com/mihajm/mmstack/blob/master/packages/di",
18
18
  "peerDependencies": {
19
- "@angular/core": ">=19 <20"
19
+ "@angular/core": ">=20 <21"
20
20
  },
21
21
  "sideEffects": false,
22
22
  "module": "fesm2022/mmstack-di.mjs",
@@ -1,47 +0,0 @@
1
- import { type Provider } from '@angular/core';
2
- import * as i0 from "@angular/core";
3
- export declare class ScopeRegistry {
4
- private readonly injector;
5
- private readonly registry;
6
- getOrCreate<T>(factory: () => T): T;
7
- static ɵfac: i0.ɵɵFactoryDeclaration<ScopeRegistry, never>;
8
- static ɵprov: i0.ɵɵInjectableDeclaration<ScopeRegistry>;
9
- }
10
- /**
11
- * Creates a specialized dependency injection scope.
12
- *
13
- * This utility allows you to create a localized dependency injection scope where you can
14
- * register and provide shared state, services, or primitives that are bound to a specific
15
- * component tree instead of the global root injector.
16
- *
17
- * @param name Optional name for the scope, primarily used for debugging and error messages.
18
- * @returns A tuple containing `[registerFn, provideFn]`:
19
- * - `registerFn`: A function to register a factory within the scope. Returns an injection function to retrieve the value.
20
- * - `provideFn`: An Angular provider function that must be added to the `providers` array where the scope begins.
21
- *
22
- * @example
23
- * ```ts
24
- * const [registerInUserScope, provideUserScope] = createScope('UserScope');
25
- *
26
- * // Define a state/service bound to this scope
27
- * const injectUserState = registerInUserScope(() => signal({ name: 'John Doe' }));
28
- * const injectLogger = registerInUserScope(() => {
29
- * const globalLogger = inject(GlobalLogger);
30
- * const user = injectUserState();
31
- * return {
32
- * log: (msg: string) => globalLogger.log(`[USER MODULE (${user().name})]: ${msg}`),
33
- * }
34
- * })
35
- * @Component({
36
- * providers: [provideUserScope()] // provides a new instance of every dependency registered to the scope
37
- * })
38
- * class ParentComponent {}
39
- *
40
- * @Component({})
41
- * class ChildComponent {
42
- * readonly userState = injectUserState();
43
- * readonly logger = injectLogger();
44
- * }
45
- * ```
46
- */
47
- export declare function createScope(name?: string): readonly [<T>(factory: () => T) => () => T, () => Provider];
@@ -1,61 +0,0 @@
1
- import { InjectionToken, type AbstractType, type InjectOptions, type Provider, type Type } from '@angular/core';
2
- type ServiceType<T> = T extends Type<infer U> ? U : T extends AbstractType<infer U> ? U : T extends InjectionToken<infer U> ? U : never;
3
- type MapDeps<T extends readonly any[]> = {
4
- [K in keyof T]: ServiceType<T[K]>;
5
- };
6
- type ProviderFn<T> = {
7
- (value: T): Provider;
8
- <const TDeps extends any[]>(fn: (...deps: MapDeps<TDeps>) => T, deps: TDeps): Provider;
9
- };
10
- type InjectFns<T> = [
11
- (opt?: Omit<InjectOptions, 'optional'>) => T,
12
- ProviderFn<T>
13
- ];
14
- type FallbackInjectableOptions<T> = {
15
- /** Default value returned when the injectable is not provided */
16
- fallback: T;
17
- };
18
- type LazyFallbackInjectableOptions<T> = {
19
- /** Function that returns a default value when the injectable is not provided. Useful for expensive defaults. */
20
- lazyFallback: () => T;
21
- };
22
- type ErrorMessageInjectableOptions = {
23
- /** Error message thrown when the injectable is not provided */
24
- errorMessage: string;
25
- };
26
- /**
27
- * Creates a typed InjectionToken with inject and provide helper functions.
28
- *
29
- * @param token - Unique token identifier
30
- * @param opt - Optional configuration for fallback value or error message
31
- * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection
32
- */
33
- export declare function injectable<T>(token: string): InjectFns<T | null>;
34
- /**
35
- * Creates a typed InjectionToken with inject and provide helper functions.
36
- * Returns a fallback value when the injectable is not provided.
37
- *
38
- * @param token - Unique token identifier
39
- * @param opt - Configuration with fallback value
40
- * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection
41
- */
42
- export declare function injectable<T>(token: string, opt: FallbackInjectableOptions<T>): InjectFns<T>;
43
- /**
44
- *
45
- * Creates a typed InjectionToken with inject and provide helper functions.
46
- * Returns a lazily evaluated fallback value when the injectable is not provided.
47
- *
48
- * @param token
49
- * @param opt
50
- */
51
- export declare function injectable<T>(token: string, opt: LazyFallbackInjectableOptions<T>): InjectFns<T>;
52
- /**
53
- * Creates a typed InjectionToken with inject and provide helper functions.
54
- * Throws an error with a custom message when the injectable is not provided.
55
- *
56
- * @param token - Unique token identifier
57
- * @param opt - Configuration with error message
58
- * @returns A tuple of [injectFn, provideFn] for type-safe dependency injection
59
- */
60
- export declare function injectable<T>(token: string, opt: ErrorMessageInjectableOptions): InjectFns<T>;
61
- export {};
@@ -1,7 +0,0 @@
1
- import { Injector } from '@angular/core';
2
- /**
3
- * Creates a tree-shakable root singleton without a class.
4
- * @example const injectUser = rootInjectable(() => ({ name: signal('John') }));
5
- */
6
- export declare function rootInjectable<T>(factory: (injector: Injector) => T, // Keeping the injector just in case
7
- name?: string): () => T;