di-bag 0.1.0

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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +280 -0
  3. package/dist/acquisition-context.d.ts +42 -0
  4. package/dist/acquisition-context.js +19 -0
  5. package/dist/acquisition-family.d.ts +32 -0
  6. package/dist/acquisition-family.js +135 -0
  7. package/dist/acquisition-mode.d.ts +34 -0
  8. package/dist/acquisition-mode.js +35 -0
  9. package/dist/acquisition.d.ts +44 -0
  10. package/dist/acquisition.js +395 -0
  11. package/dist/alias-types.d.ts +22 -0
  12. package/dist/alias-types.js +2 -0
  13. package/dist/aliases.d.ts +4 -0
  14. package/dist/aliases.js +24 -0
  15. package/dist/composition.d.ts +41 -0
  16. package/dist/composition.js +45 -0
  17. package/dist/contribution-types.d.ts +57 -0
  18. package/dist/contribution-types.js +2 -0
  19. package/dist/contributions.d.ts +3 -0
  20. package/dist/contributions.js +11 -0
  21. package/dist/dependency-references.d.ts +52 -0
  22. package/dist/dependency-references.js +53 -0
  23. package/dist/di-bag.d.ts +247 -0
  24. package/dist/di-bag.js +211 -0
  25. package/dist/errors.d.ts +66 -0
  26. package/dist/errors.js +89 -0
  27. package/dist/index.d.ts +25 -0
  28. package/dist/index.js +10 -0
  29. package/dist/inspection.d.ts +36 -0
  30. package/dist/inspection.js +2 -0
  31. package/dist/lifetime-types.d.ts +214 -0
  32. package/dist/lifetime-types.js +2 -0
  33. package/dist/lifetime.d.ts +42 -0
  34. package/dist/lifetime.js +31 -0
  35. package/dist/module-types.d.ts +182 -0
  36. package/dist/module-types.js +2 -0
  37. package/dist/module.d.ts +45 -0
  38. package/dist/module.js +118 -0
  39. package/dist/node.d.ts +4 -0
  40. package/dist/node.js +22 -0
  41. package/dist/observers.d.ts +71 -0
  42. package/dist/observers.js +58 -0
  43. package/dist/persistent-map.d.ts +29 -0
  44. package/dist/persistent-map.js +146 -0
  45. package/dist/persistent-sequence.d.ts +9 -0
  46. package/dist/persistent-sequence.js +20 -0
  47. package/dist/plugins.d.ts +32 -0
  48. package/dist/plugins.js +82 -0
  49. package/dist/provider-execution.d.ts +59 -0
  50. package/dist/provider-execution.js +271 -0
  51. package/dist/provider-operations.d.ts +59 -0
  52. package/dist/provider-operations.js +38 -0
  53. package/dist/provider.d.ts +199 -0
  54. package/dist/provider.js +158 -0
  55. package/dist/registration.d.ts +32 -0
  56. package/dist/registration.js +45 -0
  57. package/dist/replacement-types.d.ts +30 -0
  58. package/dist/replacement-types.js +2 -0
  59. package/dist/runtime.d.ts +90 -0
  60. package/dist/runtime.js +428 -0
  61. package/dist/scope-selection.d.ts +6 -0
  62. package/dist/scope-selection.js +62 -0
  63. package/dist/scope-types.d.ts +58 -0
  64. package/dist/scope-types.js +2 -0
  65. package/dist/startup.d.ts +14 -0
  66. package/dist/startup.js +141 -0
  67. package/dist/token-types.d.ts +67 -0
  68. package/dist/token-types.js +2 -0
  69. package/dist/tokens.d.ts +47 -0
  70. package/dist/tokens.js +69 -0
  71. package/dist/types.d.ts +174 -0
  72. package/dist/types.js +2 -0
  73. package/package.json +64 -0
@@ -0,0 +1,59 @@
1
+ import type { ArgumentReference } from './dependency-references';
2
+ import type { Factory } from './registration';
3
+ import type { AcquisitionMode } from './acquisition-mode';
4
+ import type { LifetimePolicy } from './lifetime';
5
+ interface SourceOperation {
6
+ readonly kind: 'source';
7
+ readonly create: Factory;
8
+ readonly acquisitionMode: AcquisitionMode;
9
+ readonly tokenKeys: readonly symbol[];
10
+ readonly references: readonly ArgumentReference[];
11
+ readonly contextual: boolean;
12
+ readonly dispose?: (value: never) => void | Promise<void>;
13
+ }
14
+ interface MetadataOperation {
15
+ readonly kind: 'metadata';
16
+ readonly metadata: Readonly<object>;
17
+ }
18
+ export interface OwnedOperation {
19
+ readonly kind: 'owned';
20
+ readonly dispose: (value: never) => void | Promise<void>;
21
+ }
22
+ interface MapOperation {
23
+ readonly kind: 'map-sync' | 'map-async';
24
+ readonly acquisitionMode: AcquisitionMode;
25
+ readonly project: (this: void, value: never) => unknown;
26
+ }
27
+ interface FrameOperation {
28
+ readonly kind: 'frame-sync' | 'frame-async';
29
+ readonly acquisitionMode: AcquisitionMode;
30
+ readonly project: (this: void, value: never) => {
31
+ readonly value: unknown;
32
+ readonly frame: unknown;
33
+ };
34
+ }
35
+ export type ProviderOperation = MetadataOperation | OwnedOperation | MapOperation | FrameOperation;
36
+ export interface ProviderDescription {
37
+ readonly lifetime: LifetimePolicy;
38
+ readonly alias?: string | symbol;
39
+ readonly source: SourceOperation;
40
+ readonly operations: readonly ProviderOperation[];
41
+ readonly metadata: Readonly<object>;
42
+ }
43
+ export declare function sourceDescription(create: Factory, dispose?: (value: never) => void | Promise<void>, tokenKeys?: readonly symbol[], acquisitionMode?: AcquisitionMode, contextual?: boolean, references?: readonly ArgumentReference[]): ProviderDescription;
44
+ /** One registry authenticates both ownership handles and transformed providers. */
45
+ export declare function retainDescription(handle: object, description: ProviderDescription): void;
46
+ export declare function describe(registration: unknown): ProviderDescription;
47
+ export declare function normalize(registration: unknown): {
48
+ lifetime: LifetimePolicy;
49
+ alias?: string | symbol;
50
+ create: Factory;
51
+ acquisitionMode: AcquisitionMode;
52
+ tokenKeys: readonly symbol[];
53
+ references: readonly ArgumentReference[];
54
+ contextual: boolean;
55
+ dispose?: (value: never) => void | Promise<void>;
56
+ metadata: Readonly<object>;
57
+ operations: readonly ProviderOperation[];
58
+ };
59
+ export {};
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sourceDescription = sourceDescription;
4
+ exports.retainDescription = retainDescription;
5
+ exports.describe = describe;
6
+ exports.normalize = normalize;
7
+ const errors_1 = require("./errors");
8
+ const emptyMetadata = Object.freeze({});
9
+ const scopedLifetime = Object.freeze({ kind: 'scoped', allowScopedDependencies: false });
10
+ const descriptions = new WeakMap();
11
+ function sourceDescription(create, dispose, tokenKeys = [], acquisitionMode = 'auto', contextual = false, references = []) {
12
+ const selected = Object.freeze([...tokenKeys]);
13
+ const argumentsSnapshot = Object.freeze(references.map(reference => Object.freeze({ ...reference })));
14
+ const source = Object.freeze(dispose ? { kind: 'source', create, dispose, tokenKeys: selected, references: argumentsSnapshot, acquisitionMode, contextual } : { kind: 'source', create, tokenKeys: selected, references: argumentsSnapshot, acquisitionMode, contextual });
15
+ return Object.freeze({ source, operations: Object.freeze([]), metadata: emptyMetadata, lifetime: scopedLifetime });
16
+ }
17
+ /** One registry authenticates both ownership handles and transformed providers. */
18
+ function retainDescription(handle, description) {
19
+ descriptions.set(handle, description);
20
+ Object.freeze(handle);
21
+ }
22
+ function describe(registration) {
23
+ if (typeof registration === 'function')
24
+ return sourceDescription(registration);
25
+ if (typeof registration === 'object' && registration !== null) {
26
+ const description = descriptions.get(registration);
27
+ if (description)
28
+ return description;
29
+ }
30
+ throw (0, errors_1.libraryError)('DI_BAG_INVALID_REGISTRATION', 'invalid factory registration', { operation: 'register' });
31
+ }
32
+ function normalize(registration) {
33
+ const description = describe(registration);
34
+ const { create, dispose, tokenKeys, references, acquisitionMode, contextual } = description.source;
35
+ const { metadata, operations, lifetime } = description;
36
+ const alias = description.alias === undefined ? {} : { alias: description.alias };
37
+ return dispose ? { ...alias, create, dispose, tokenKeys, references, acquisitionMode, metadata, operations, lifetime, contextual } : { ...alias, create, tokenKeys, references, acquisitionMode, metadata, operations, lifetime, contextual };
38
+ }
@@ -0,0 +1,199 @@
1
+ import type { FactoryWithDisposal, Factory, Registration } from './registration';
2
+ import type { Unsatisfied } from './types';
3
+ import type { ProviderOperation } from './provider-operations';
4
+ import type { TokenBase, TokenKey, TokenService } from './tokens';
5
+ import type { GraphContract, TokenDependencyContract, OpaqueGraph, TokenTupleAdmission, ReboundGraph } from './token-types';
6
+ import type { Acquired, AcquisitionMode, ModeOptions } from './acquisition-mode';
7
+ declare const providerInvariant: unique symbol;
8
+ /** A type-only common contract for immutable provider descriptions. */
9
+ declare class ProviderBase {
10
+ private readonly nominal;
11
+ }
12
+ /**
13
+ * An immutable provider description retaining factory, metadata, inspection-frame,
14
+ * dependency-graph, and acquired-value contracts.
15
+ *
16
+ * Create providers through {@link DiBagApi.fromFactory}, composition adapters, or provider
17
+ * decorators. This type-only class has no public constructor.
18
+ * @typeParam F - The exact exposed factory signature, including named dependencies.
19
+ * @typeParam M - Static registration metadata available before resolution.
20
+ * @typeParam A - The ordered tuple of acquisition metadata frame payloads.
21
+ * @typeParam G - The retained token, lifetime, and graph compatibility contract.
22
+ * @typeParam V - The raw or fulfilled value supplied to an outer disposal stage.
23
+ */
24
+ declare class Provider<F extends Factory, M extends object = Readonly<{}>, A extends readonly unknown[] = readonly [], G extends GraphContract = TokenDependencyContract, V = Awaited<ReturnType<F>>> extends ProviderBase {
25
+ /** @internal */
26
+ readonly [providerInvariant]: (value: [F, M, A, G, V]) => [F, M, A, G, V];
27
+ }
28
+ /** Internal construction bridge; authentication remains in retainDescription. */
29
+ export declare function createProvider<F extends Factory, M extends object, A extends readonly unknown[], G extends GraphContract, V>(): Provider<F, M, A, G, V>;
30
+ export type ProviderContext<F extends Factory, G extends GraphContract = GraphContract> = ProviderBase & {
31
+ readonly [providerInvariant]: (...args: never[]) => [F, object, readonly unknown[], G, unknown];
32
+ };
33
+ /** Extract the callable factory contract retained by a registration. */
34
+ export type ProviderFactory<R extends Registration> = R extends infer T & {} ? FactoryOf<T> : never;
35
+ type FactoryOf<R> = R extends Factory ? R : R extends {
36
+ create: infer F extends Factory;
37
+ } ? F : R extends ProviderContext<infer F> ? F : R extends ProviderBase ? (this: void, deps: unknown) => unknown : never;
38
+ /** Extract the exact service value exposed by a registration, including Promise identity. */
39
+ export type ProviderOutput<R extends Registration> = ProviderBase extends R ? unknown : ReturnType<ProviderFactory<R>>;
40
+ /** Extract the fulfilled or raw value passed to the registration's outer disposer. */
41
+ export type ProviderAcquiredValue<R extends Registration> = ProviderBase extends R ? unknown : R extends infer T & {} ? AcquiredOf<T> : unknown;
42
+ type AcquiredOf<R> = R extends {
43
+ readonly [providerInvariant]: (...args: never[]) => [Factory, object, readonly unknown[], GraphContract, infer V];
44
+ } ? V : R extends Factory ? Awaited<ReturnType<R>> : R extends FactoryWithDisposal<infer F> ? Awaited<ReturnType<F>> : unknown;
45
+ /** Extract the registration's named dependency object. */
46
+ export type ProviderNamedDependencies<R extends Registration> = ProviderBase extends R ? unknown : Parameters<ProviderFactory<R>> extends [] ? Record<never, never> : Exclude<Parameters<ProviderFactory<R>>[0], undefined>;
47
+ /** Extract static metadata attached to a registration. */
48
+ export type ProviderRegistrationMetadata<R> = R extends infer T & {} ? MetadataOf<T> : unknown;
49
+ type MetadataOf<R> = R extends Provider<infer _F, infer M, infer _A, infer _G, infer _V> ? M : R extends Factory | FactoryWithDisposal<Factory> ? Readonly<{}> : unknown;
50
+ /** Extract the ordered acquisition-frame metadata tuple exposed by inspection. */
51
+ export type ProviderAcquisitionMetadata<R> = ProviderBase extends R ? readonly unknown[] : R extends infer T & {} ? AcquisitionMetadataOf<T> : readonly unknown[];
52
+ type AcquisitionMetadataOf<R> = R extends Provider<infer _F, infer _M, infer A, infer _G, infer _V> ? A : R extends Factory | FactoryWithDisposal<Factory> ? readonly [] : readonly unknown[];
53
+ /** Extract the retained typed-token and lifetime graph contract. */
54
+ export type ProviderGraphContract<R> = ProviderBase extends R ? OpaqueGraph : R extends infer T & {} ? GraphOf<T> : OpaqueGraph;
55
+ type GraphOf<R> = R extends Provider<infer _F, infer _M, infer _A, infer G, infer _V> ? G : R extends Factory | FactoryWithDisposal<Factory> ? TokenDependencyContract : R extends ProviderContext<Factory, infer G> ? G : OpaqueGraph;
56
+ type RequiredTokens<G> = G extends TokenDependencyContract<infer T, TokenBase, readonly TokenBase[]> ? T[number] : TokenBase;
57
+ type Bound<G> = G extends TokenDependencyContract<readonly TokenBase[], infer B, readonly TokenBase[]> ? B : TokenBase;
58
+ type OptionalTokens<G> = G extends TokenDependencyContract<readonly TokenBase[], TokenBase, infer O> ? O[number] : TokenBase;
59
+ /** Extract token collection requirements from a registration. */
60
+ export type ProviderCollectionTokens<R> = ProviderGraphContract<R> extends infer G ? G extends {
61
+ readonly all: infer T extends readonly TokenBase[];
62
+ } ? T[number] : never : never;
63
+ /** Extract optional typed-token requirements from a registration. */
64
+ export type ProviderOptionalTokens<R> = OptionalTokens<ProviderGraphContract<R>>;
65
+ /** Extract required typed-token dependencies from a registration. */
66
+ export type ProviderRequiredTokens<R> = RequiredTokens<ProviderGraphContract<R>>;
67
+ export type BoundToken<R> = Bound<ProviderGraphContract<R>>;
68
+ /** Bind a checked output without changing the reusable source's retained needs. */
69
+ export declare function withTokenBinding<T extends TokenBase, R extends Registration>(token: T & TokenTupleAdmission<readonly [T]>, registration: R & Registration & ([ProviderOutput<NoInfer<R>>] extends [TokenService<NoInfer<T>>] ? unknown : Unsatisfied<'token binding output is not assignable to its service', {
70
+ token: TokenKey<T>;
71
+ expected: TokenService<T>;
72
+ provided: ProviderOutput<R>;
73
+ }>)): Provider<ProviderFactory<R>, RetainedMetadata<R>, ProviderAcquisitionMetadata<R>, ReboundGraph<ProviderGraphContract<R>, T>, ProviderAcquiredValue<R>>;
74
+ type MappedFactory<R extends Registration, O> = (this: void, deps: ProviderNamedDependencies<R>) => O;
75
+ export type RetainedMetadata<R> = ProviderRegistrationMetadata<R> extends object ? ProviderRegistrationMetadata<R> : object;
76
+ /** Extend an authenticated description without exposing its operations. */
77
+ export declare function transform<R extends Registration, F extends Factory, A extends readonly unknown[] = ProviderAcquisitionMetadata<R>, V = Awaited<ReturnType<F>>>(registration: R, operation: ProviderOperation): Provider<F, RetainedMetadata<R>, A, ProviderGraphContract<R>, V>;
78
+ /**
79
+ * Transform the exact exposed service without awaiting the input or callback result.
80
+ * Retains dependencies, lifetime, metadata, and earlier cleanup; the result adds no ownership.
81
+ * @param registration - The source registration whose exact output is transformed.
82
+ * @param options - Direct mode, a transform callback, and optional output acquisitionMode (auto by default).
83
+ * @returns A provider exposing the callback's exact result, with the selected output acquisition policy.
84
+ * @typeParam R - The source registration and its retained contracts.
85
+ * @typeParam P - The exact transform callback signature and output.
86
+ * @typeParam M - The result's auto, raw, or nativePromise acquisition policy.
87
+ */
88
+ export declare function transformService<R extends Registration, P extends (this: void, value: ProviderOutput<NoInfer<R>>) => ('nativePromise' extends M ? Promise<unknown> : unknown), M extends AcquisitionMode = 'auto'>(registration: R & Registration, options: {
89
+ readonly mode: 'direct';
90
+ readonly transform: P;
91
+ } & ModeOptions<M>): Provider<MappedFactory<R, ReturnType<P>>, RetainedMetadata<R>, ProviderAcquisitionMetadata<R>, ProviderGraphContract<R>, Acquired<ReturnType<P>, M>>;
92
+ /**
93
+ * Await the input and adopt the transformed result into a native Promise stage.
94
+ * Retains dependencies, lifetime, metadata, and existing cleanup; adds no result ownership.
95
+ * @param registration - The source registration whose fulfilled value is transformed.
96
+ * @param options - Awaited mode and a transform callback; acquisitionMode cannot be overridden.
97
+ * @returns A provider exposing a Promise of the awaited transform result.
98
+ * @typeParam R - The source registration and retained contracts.
99
+ * @typeParam P - The callback signature; its result may itself be a Promise.
100
+ */
101
+ export declare function transformService<R extends Registration, P extends (this: void, value: Awaited<ProviderOutput<NoInfer<R>>>) => unknown>(registration: R & Registration, options: {
102
+ readonly mode: 'awaited';
103
+ readonly transform: P;
104
+ readonly acquisitionMode?: never;
105
+ }): Provider<MappedFactory<R, Promise<Awaited<ReturnType<P>>>>, RetainedMetadata<R>, ProviderAcquisitionMetadata<R>, ProviderGraphContract<R>>;
106
+ type InvalidAcquisitionMetadata<M> = M extends unknown ? M extends readonly unknown[] | ((...args: never[]) => unknown) ? true : 'then' extends keyof M ? unknown extends M['then'] ? true : Extract<M['then'], (...args: never[]) => unknown> extends never ? never : true : never : never;
107
+ type AcquisitionMetadataAdmission<M> = [InvalidAcquisitionMetadata<M>] extends [never] ? unknown : Unsatisfied<'acquisition metadata must be a synchronous object record', {}>;
108
+ type AcquisitionFrames<R, M> = readonly [...ProviderAcquisitionMetadata<R>, Readonly<M>];
109
+ export type MetadataKeyUnion<M> = M extends unknown ? keyof M : never;
110
+ type NonFiniteKeys<M> = M extends unknown ? {
111
+ [K in keyof M]-?: Record<never, never> extends Record<K, never> ? K : never;
112
+ }[keyof M] : never;
113
+ type MetadataKeys<R, M> = [NonFiniteKeys<M> | Extract<MetadataKeyUnion<M>, number>] extends [never] ? [MetadataKeyUnion<M> & MetadataKeyUnion<ProviderRegistrationMetadata<R>>] extends [never] ? unknown : Unsatisfied<'duplicate metadata keys', {
114
+ duplicates: MetadataKeyUnion<M> & MetadataKeyUnion<ProviderRegistrationMetadata<R>>;
115
+ }> : Unsatisfied<'metadata keys must be finite string or unique-symbol keys', {}>;
116
+ export type { Provider, ProviderBase };
117
+ /**
118
+ * Attach registration metadata without evaluating the source or changing ownership.
119
+ * Own keys are copied and frozen; static key collisions reject before getters run.
120
+ * @param registration - The source registration to describe.
121
+ * @param options - A static record with finite noncolliding string or unique-symbol keys.
122
+ * @returns A provider preserving exact output, acquisition policy, and ordered dynamic frames.
123
+ * @typeParam R - The source registration and retained contracts.
124
+ * @typeParam M - The additional static registration metadata record.
125
+ */
126
+ export declare function withMetadata<R extends Registration, M extends object>(registration: R & Registration, options: {
127
+ readonly static: M & MetadataKeys<NoInfer<R>, M>;
128
+ readonly dynamic?: never;
129
+ }): Provider<ProviderFactory<R>, Readonly<RetainedMetadata<R> & M>, ProviderAcquisitionMetadata<R>, ProviderGraphContract<R>, ProviderAcquiredValue<R>>;
130
+ /**
131
+ * Describe the exact exposed service with a synchronous plain metadata record.
132
+ * Direct mode preserves Promise identity and source acquisition policy, adding no ownership.
133
+ * @param registration - The source registration whose exact output is described.
134
+ * @param options - Required static metadata and mandatory direct dynamic mode with a synchronous describe callback.
135
+ * @returns A provider with merged registration metadata and one appended acquisition metadata frame.
136
+ * @typeParam R - The source registration and retained contracts.
137
+ * @typeParam P - The synchronous describe callback and its record result.
138
+ * @typeParam M - The required static metadata record.
139
+ */
140
+ export declare function withMetadata<R extends Registration, P extends (this: void, value: ProviderOutput<NoInfer<R>>) => object, M extends object = {}>(registration: R & Registration, options: {
141
+ readonly static: M & MetadataKeys<NoInfer<R>, M>;
142
+ readonly dynamic: {
143
+ readonly mode: 'direct';
144
+ readonly describe: P & AcquisitionMetadataAdmission<ReturnType<P>>;
145
+ };
146
+ }): Provider<ProviderFactory<R>, Readonly<RetainedMetadata<R> & M>, AcquisitionFrames<R, ReturnType<P>>, ProviderGraphContract<R>, ProviderAcquiredValue<R>>;
147
+ /**
148
+ * Describe the exact exposed service with a synchronous plain metadata record.
149
+ * Direct mode preserves Promise identity and source acquisition policy, adding no ownership.
150
+ * @param registration - The source registration whose exact output is described.
151
+ * @param options - Optional static metadata and mandatory direct dynamic mode with a synchronous describe callback.
152
+ * If the static level may be absent, its added keys remain optional in inspection.
153
+ * @returns A provider with merged registration metadata and one appended acquisition metadata frame.
154
+ * @typeParam R - The source registration and retained contracts.
155
+ * @typeParam P - The synchronous describe callback and its record result.
156
+ * @typeParam M - The optional static metadata record.
157
+ */
158
+ export declare function withMetadata<R extends Registration, P extends (this: void, value: ProviderOutput<NoInfer<R>>) => object, M extends object = {}>(registration: R & Registration, options: {
159
+ readonly static?: M & MetadataKeys<NoInfer<R>, M>;
160
+ readonly dynamic: {
161
+ readonly mode: 'direct';
162
+ readonly describe: P & AcquisitionMetadataAdmission<ReturnType<P>>;
163
+ };
164
+ }): Provider<ProviderFactory<R>, Readonly<RetainedMetadata<R> & Partial<M>>, AcquisitionFrames<R, ReturnType<P>>, ProviderGraphContract<R>, ProviderAcquiredValue<R>>;
165
+ /**
166
+ * Await the source and append a synchronous metadata record through a native Promise stage.
167
+ * Existing ownership and metadata frames remain ordered; annotation adds no ownership.
168
+ * @param registration - The source registration whose fulfilled value is described.
169
+ * @param options - Required static metadata and mandatory awaited mode with a synchronous describe callback.
170
+ * @returns A provider exposing a Promise of the source value with one appended metadata frame.
171
+ * @typeParam R - The source registration and retained contracts.
172
+ * @typeParam P - The synchronous describe callback and its record result.
173
+ * @typeParam M - The required static metadata record.
174
+ */
175
+ export declare function withMetadata<R extends Registration, P extends (this: void, value: Awaited<ProviderOutput<NoInfer<R>>>) => object, M extends object = {}>(registration: R & Registration, options: {
176
+ readonly static: M & MetadataKeys<NoInfer<R>, M>;
177
+ readonly dynamic: {
178
+ readonly mode: 'awaited';
179
+ readonly describe: P & AcquisitionMetadataAdmission<ReturnType<P>>;
180
+ };
181
+ }): Provider<MappedFactory<R, Promise<Awaited<ProviderOutput<R>>>>, Readonly<RetainedMetadata<R> & M>, AcquisitionFrames<R, ReturnType<P>>, ProviderGraphContract<R>, Awaited<ProviderOutput<R>>>;
182
+ /**
183
+ * Await the source and append a synchronous metadata record through a native Promise stage.
184
+ * Existing ownership and metadata frames remain ordered; annotation adds no ownership.
185
+ * @param registration - The source registration whose fulfilled value is described.
186
+ * @param options - Optional static metadata and mandatory awaited mode with a synchronous describe callback.
187
+ * If the static level may be absent, its added keys remain optional in inspection.
188
+ * @returns A provider exposing a Promise of the source value with one appended metadata frame.
189
+ * @typeParam R - The source registration and retained contracts.
190
+ * @typeParam P - The synchronous describe callback and its record result.
191
+ * @typeParam M - The optional static metadata record.
192
+ */
193
+ export declare function withMetadata<R extends Registration, P extends (this: void, value: Awaited<ProviderOutput<NoInfer<R>>>) => object, M extends object = {}>(registration: R & Registration, options: {
194
+ readonly static?: M & MetadataKeys<NoInfer<R>, M>;
195
+ readonly dynamic: {
196
+ readonly mode: 'awaited';
197
+ readonly describe: P & AcquisitionMetadataAdmission<ReturnType<P>>;
198
+ };
199
+ }): Provider<MappedFactory<R, Promise<Awaited<ProviderOutput<R>>>>, Readonly<RetainedMetadata<R> & Partial<M>>, AcquisitionFrames<R, ReturnType<P>>, ProviderGraphContract<R>, Awaited<ProviderOutput<R>>>;
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createProvider = createProvider;
4
+ exports.withTokenBinding = withTokenBinding;
5
+ exports.transform = transform;
6
+ exports.transformService = transformService;
7
+ exports.withMetadata = withMetadata;
8
+ const errors_1 = require("./errors");
9
+ const provider_operations_1 = require("./provider-operations");
10
+ const tokens_1 = require("./tokens");
11
+ const acquisition_mode_1 = require("./acquisition-mode");
12
+ // Non-generic admission preserves invariant concrete contracts at graph boundaries.
13
+ /** A type-only common contract for immutable provider descriptions. */
14
+ class ProviderBase {
15
+ }
16
+ /**
17
+ * An immutable provider description retaining factory, metadata, inspection-frame,
18
+ * dependency-graph, and acquired-value contracts.
19
+ *
20
+ * Create providers through {@link DiBagApi.fromFactory}, composition adapters, or provider
21
+ * decorators. This type-only class has no public constructor.
22
+ * @typeParam F - The exact exposed factory signature, including named dependencies.
23
+ * @typeParam M - Static registration metadata available before resolution.
24
+ * @typeParam A - The ordered tuple of acquisition metadata frame payloads.
25
+ * @typeParam G - The retained token, lifetime, and graph compatibility contract.
26
+ * @typeParam V - The raw or fulfilled value supplied to an outer disposal stage.
27
+ */
28
+ class Provider extends ProviderBase {
29
+ }
30
+ /** Internal construction bridge; authentication remains in retainDescription. */
31
+ function createProvider() {
32
+ return new Provider();
33
+ }
34
+ /** Bind a checked output without changing the reusable source's retained needs. */
35
+ function withTokenBinding(token, registration) {
36
+ (0, tokens_1.readTokenKey)(token);
37
+ const handle = new Provider();
38
+ (0, provider_operations_1.retainDescription)(handle, (0, provider_operations_1.describe)(registration));
39
+ return handle;
40
+ }
41
+ /** Extend an authenticated description without exposing its operations. */
42
+ function transform(registration, operation) {
43
+ const description = (0, provider_operations_1.describe)(registration);
44
+ const handle = new Provider();
45
+ (0, provider_operations_1.retainDescription)(handle, Object.freeze({ ...description, operations: Object.freeze([...description.operations, Object.freeze(operation)]) }));
46
+ return handle;
47
+ }
48
+ function transformService(registration, options) {
49
+ if (typeof options !== 'object' || options === null || (options.mode !== 'direct' && options.mode !== 'awaited'))
50
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_TRANSFORM', 'transformService mode must be direct or awaited', { operation: 'transformService' });
51
+ if (typeof options.transform !== 'function')
52
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_TRANSFORM', 'transformService requires a transform callback', { operation: 'transformService' });
53
+ if (options.mode === 'awaited' && 'acquisitionMode' in options)
54
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_TRANSFORM', 'transformService awaited mode does not accept acquisitionMode', { operation: 'transformService' });
55
+ return transform(registration, { kind: options.mode === 'direct' ? 'map-sync' : 'map-async', project: options.transform, acquisitionMode: options.mode === 'direct' ? (0, acquisition_mode_1.acquisitionMode)(options) : 'nativePromise' });
56
+ }
57
+ function annotate(registration, callback, async) {
58
+ if (typeof callback !== 'function')
59
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_METADATA', 'acquisition metadata requires a function', { operation: 'withMetadata' });
60
+ const description = (0, provider_operations_1.describe)(registration);
61
+ // Decoration retains the current output stage's mode even across metadata and ownership.
62
+ let acquisitionMode = description.source.acquisitionMode;
63
+ for (const operation of description.operations) {
64
+ if ('acquisitionMode' in operation)
65
+ acquisitionMode = operation.acquisitionMode;
66
+ }
67
+ return transform(registration, {
68
+ kind: async ? 'frame-async' : 'frame-sync',
69
+ acquisitionMode: async ? 'nativePromise' : acquisitionMode,
70
+ project(value) {
71
+ const metadata = callback(value);
72
+ if (typeof metadata !== 'object' || metadata === null || Array.isArray(metadata)) {
73
+ return invalidAcquisitionMetadata(metadata);
74
+ }
75
+ const prototype = Object.getPrototypeOf(metadata);
76
+ if (prototype !== null && prototype !== Object.prototype)
77
+ return invalidAcquisitionMetadata(metadata);
78
+ const frame = Object.create(null);
79
+ for (const key of Reflect.ownKeys(metadata))
80
+ frame[key] = Reflect.get(metadata, key);
81
+ const then = Object.hasOwn(frame, 'then') ? frame.then : Reflect.get(metadata, 'then');
82
+ if (typeof then === 'function')
83
+ return invalidAcquisitionMetadata(metadata);
84
+ return { value, frame: Object.freeze(frame) };
85
+ },
86
+ });
87
+ }
88
+ function invalidAcquisitionMetadata(value) {
89
+ // A widened callback can return a rejected Promise. Observe that invalid result
90
+ // before throwing, without reading its `then` or assimilating service values.
91
+ // The intrinsic rejects non-Promise receivers without invoking user code.
92
+ try {
93
+ Promise.prototype.then.call(value, () => { }, () => { });
94
+ }
95
+ catch { /* Not an observable native Promise. */ }
96
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_METADATA', 'acquisition metadata must be a synchronous plain object record', { operation: 'withMetadata' });
97
+ }
98
+ /**
99
+ * Attach static metadata without evaluating the registration or transferring ownership.
100
+ * Own string and symbol keys are copied and frozen; payload objects keep their identity.
101
+ * @param registration - The source registration to describe.
102
+ * @param metadata - A finite, noncolliding metadata record.
103
+ * @returns A provider retaining the source output, dependencies, frames, and ownership stages.
104
+ * @throws If metadata is not an object or an own key duplicates existing metadata.
105
+ */
106
+ function attachStaticMetadata(registration, metadata) {
107
+ const description = (0, provider_operations_1.describe)(registration);
108
+ if (typeof metadata !== 'object' || metadata === null || Array.isArray(metadata)) {
109
+ throw (0, errors_1.libraryError)('DI_BAG_INVALID_METADATA', 'metadata must be a string or symbol-keyed object', { operation: 'withMetadata' });
110
+ }
111
+ const keys = Reflect.ownKeys(metadata);
112
+ for (const key of keys) {
113
+ if (Object.hasOwn(description.metadata, key))
114
+ throw (0, errors_1.libraryError)('DI_BAG_DUPLICATE_METADATA', `duplicate metadata: ${String(key)}`, { operation: 'withMetadata', key });
115
+ }
116
+ // Preflight all keys before evaluating a getter; copy hidden entries as data too.
117
+ const added = Object.create(null);
118
+ for (const key of keys)
119
+ added[key] = Reflect.get(metadata, key);
120
+ Object.freeze(added);
121
+ const combined = Object.freeze(Object.assign(Object.create(null), description.metadata, added));
122
+ const handle = new Provider();
123
+ (0, provider_operations_1.retainDescription)(handle, Object.freeze({
124
+ ...description,
125
+ operations: Object.freeze([...description.operations, Object.freeze({ kind: 'metadata', metadata: added })]),
126
+ metadata: combined,
127
+ }));
128
+ return handle;
129
+ }
130
+ function withMetadata(registration, options) {
131
+ if (typeof options !== 'object' || options === null || Array.isArray(options))
132
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_METADATA', 'withMetadata requires static or dynamic metadata', { operation: 'withMetadata' });
133
+ const hasStatic = Object.hasOwn(options, 'static');
134
+ const hasDynamic = Object.hasOwn(options, 'dynamic');
135
+ if (!hasStatic && !hasDynamic)
136
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_METADATA', 'withMetadata requires static or dynamic metadata', { operation: 'withMetadata' });
137
+ if ((!hasStatic && 'static' in options) || (!hasDynamic && 'dynamic' in options))
138
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_METADATA', 'withMetadata static and dynamic options must be own properties', { operation: 'withMetadata' });
139
+ // Snapshot every executed dynamic field once, before static metadata getters can
140
+ // change it. A checked mode must be the same mode used to build the operation.
141
+ let frame;
142
+ if (hasDynamic) {
143
+ const dynamic = options.dynamic;
144
+ if (typeof dynamic !== 'object' || dynamic === null)
145
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_METADATA', 'withMetadata dynamic mode must be direct or awaited', { operation: 'withMetadata' });
146
+ const mode = dynamic.mode;
147
+ if (mode !== 'direct' && mode !== 'awaited')
148
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_METADATA', 'withMetadata dynamic mode must be direct or awaited', { operation: 'withMetadata' });
149
+ const callback = dynamic.describe;
150
+ if (typeof callback !== 'function')
151
+ throw (0, errors_1.libraryTypeError)('DI_BAG_INVALID_METADATA', 'acquisition metadata requires a function', { operation: 'withMetadata' });
152
+ frame = { mode, describe: callback };
153
+ }
154
+ let result = hasStatic ? attachStaticMetadata(registration, options.static) : registration;
155
+ if (frame !== undefined)
156
+ result = annotate(result, frame.describe, frame.mode === 'awaited');
157
+ return result;
158
+ }
@@ -0,0 +1,32 @@
1
+ import type { ProviderBase, Provider, ProviderFactory, ProviderAcquiredValue, RetainedMetadata, ProviderAcquisitionMetadata, ProviderGraphContract } from './provider';
2
+ export { normalize } from './provider-operations';
3
+ export type Factory = (this: void, deps: never) => unknown;
4
+ /** A nominal registration pairing a factory with fulfilled-value cleanup. */
5
+ declare class FactoryWithDisposal<F extends Factory> {
6
+ readonly create: F;
7
+ private readonly nominal;
8
+ constructor(create: F);
9
+ }
10
+ /** A nominal registration pairing a factory with fulfilled-value cleanup. */
11
+ export type { FactoryWithDisposal };
12
+ /** A factory, disposable factory, or immutable provider accepted by builders and decorators. */
13
+ export type Registration = Factory | FactoryWithDisposal<Factory> | ProviderBase;
14
+ export type Registrations = Record<string, Registration>;
15
+ /**
16
+ * Declare that each acquiring bag owns a factory's fulfilled value.
17
+ * Neither callback runs until acquisition; cleanup runs once after dependent resources.
18
+ * @param create - The receiver-free service factory.
19
+ * @param dispose - Cleanup for its fulfilled value; it may complete synchronously or asynchronously.
20
+ * @returns A nominal disposable registration preserving the factory's exact output.
21
+ */
22
+ export declare function withDisposal<F extends Factory>(create: F, dispose: (this: void, value: Awaited<ReturnType<NoInfer<F>>>) => void | Promise<void>): FactoryWithDisposal<F>;
23
+ /**
24
+ * Add an ownership stage to an existing registration.
25
+ * Earlier disposal stages remain attached and run after this stage in reverse order.
26
+ * @param provider - The registration whose acquired value becomes owned at this stage.
27
+ * @param dispose - Cleanup for the registration's acquired value.
28
+ * @returns A provider retaining output, dependencies, metadata, frames, and earlier ownership.
29
+ */
30
+ export declare function withDisposal<R extends Registration>(provider: R & Registration, dispose: (this: void, value: ProviderAcquiredValue<NoInfer<R>>) => void | Promise<void>): Provider<ProviderFactory<R>, RetainedMetadata<R>, ProviderAcquisitionMetadata<R>, ProviderGraphContract<R>, ProviderAcquiredValue<R>>;
31
+ /** Preflight every own key before reading getters; retain hidden own entries. */
32
+ export declare function snapshotAdd(more: unknown, hasKey: (key: string) => boolean): Registrations;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalize = void 0;
4
+ exports.withDisposal = withDisposal;
5
+ exports.snapshotAdd = snapshotAdd;
6
+ const errors_1 = require("./errors");
7
+ const provider_1 = require("./provider");
8
+ const provider_operations_1 = require("./provider-operations");
9
+ var provider_operations_2 = require("./provider-operations");
10
+ Object.defineProperty(exports, "normalize", { enumerable: true, get: function () { return provider_operations_2.normalize; } });
11
+ // A private member is lost on spread; structural copies cannot be registrations.
12
+ /** A nominal registration pairing a factory with fulfilled-value cleanup. */
13
+ class FactoryWithDisposal {
14
+ create;
15
+ constructor(create) {
16
+ this.create = create;
17
+ }
18
+ }
19
+ function withDisposal(registration, dispose) {
20
+ if (typeof registration !== 'function')
21
+ return (0, provider_1.transform)(registration, { kind: 'owned', dispose });
22
+ const handle = new FactoryWithDisposal(registration);
23
+ (0, provider_operations_1.retainDescription)(handle, (0, provider_operations_1.sourceDescription)(registration, dispose));
24
+ return handle;
25
+ }
26
+ /** Preflight every own key before reading getters; retain hidden own entries. */
27
+ function snapshotAdd(more, hasKey) {
28
+ if (typeof more !== 'object' || more === null || Array.isArray(more)) {
29
+ throw (0, errors_1.libraryError)('DI_BAG_INVALID_REGISTRATION', 'registrations must be a string-keyed object', { operation: 'register' });
30
+ }
31
+ const keys = Reflect.ownKeys(more);
32
+ for (const key of keys) {
33
+ if (typeof key !== 'string')
34
+ throw (0, errors_1.libraryError)('DI_BAG_INVALID_REGISTRATION', 'registration keys must be strings', { operation: 'register' });
35
+ if (hasKey(key))
36
+ throw (0, errors_1.libraryError)('DI_BAG_DUPLICATE_REGISTRATION', `duplicate registration: ${key}`, { operation: 'register', key });
37
+ }
38
+ const snapshot = Object.create(null);
39
+ for (const key of keys) {
40
+ const registration = Reflect.get(more, key);
41
+ (0, provider_operations_1.normalize)(registration);
42
+ snapshot[key] = registration;
43
+ }
44
+ return snapshot;
45
+ }
@@ -0,0 +1,30 @@
1
+ import type { NeedConstraint, CheckedConstraints } from './module-types';
2
+ import type { ProviderFactory } from './provider';
3
+ import type { Registration, Registrations } from './registration';
4
+ import type { TokenBinding, BindingOutput, TokenMember } from './token-types';
5
+ import type { TokenBase, TokenKey } from './tokens';
6
+ import type { Entry, RegistrationsFromEntries, IncrementalChecked, OverrideRegistrations, ReplacementKey } from './types';
7
+ type DependencyBearingRegistration<R extends Registration> = R extends unknown ? Parameters<ProviderFactory<R>> extends [] ? never : R : never;
8
+ export type ZeroDependencyAdmission<R extends Registration> = [
9
+ DependencyBearingRegistration<R>
10
+ ] extends [never] ? unknown : never;
11
+ export type ReplacementAdmission<R extends Registrations, K extends string | TokenBase> = [
12
+ K
13
+ ] extends [string] ? ReplacementKey<R, K> : TokenMember<R, K>;
14
+ export type BuilderReplacementRegistration<E extends Entry, C extends NeedConstraint, K extends string | TokenBase, V extends Registration> = [K] extends [string] ? IncrementalChecked<E, Record<K, NoInfer<V>>> & CheckedConstraints<C, OverrideRegistrations<RegistrationsFromEntries<E>, Record<K, NoInfer<V>>>> : [K] extends [TokenBase] ? BindingOutput<NoInfer<K>, NoInfer<V>> & IncrementalChecked<E, Record<TokenKey<K>, TokenBinding<NoInfer<K>, NoInfer<V>>>> & CheckedConstraints<C, OverrideRegistrations<RegistrationsFromEntries<E>, Record<TokenKey<K>, TokenBinding<NoInfer<K>, NoInfer<V>>>>> : never;
15
+ type ReflectedEntry = {
16
+ key: never;
17
+ registration: TokenBinding<TokenBase, Registration>;
18
+ };
19
+ export type ReplacedEntries<E extends Entry, K extends string | TokenBase, V extends Registration> = [K] extends [string] ? Exclude<E, {
20
+ key: K;
21
+ }> | {
22
+ key: K;
23
+ registration: V;
24
+ } : [K] extends [TokenBase] ? Exclude<E, {
25
+ key: TokenKey<K>;
26
+ }> | {
27
+ key: TokenKey<K>;
28
+ registration: TokenBinding<K, V>;
29
+ } : E | ReflectedEntry;
30
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });