@teqfw/di 2.0.3 → 2.0.5
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.
- package/CHANGELOG.md +13 -0
- package/README.md +220 -149
- package/ai/AGENTS.md +8 -7
- package/ai/package-api.ts +440 -0
- package/dist/esm.js +1 -1
- package/dist/umd.js +1 -1
- package/package.json +1 -2
- package/src/AGENTS.md +5 -5
- package/src/Container.mjs +9 -6
- package/src/Def/Parser.mjs +7 -7
- package/src/Dto/DepId.mjs +8 -13
- package/src/Dto/Resolver/Config/Namespace.mjs +13 -18
- package/src/Dto/Resolver/Config.mjs +14 -20
- package/src/Enum/Composition.mjs +1 -1
- package/src/Enum/Life.mjs +1 -1
- package/src/Enum/Platform.mjs +1 -1
- package/types.d.ts +8 -5
- package/jsconfig.json +0 -13
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
export type ApiExposure =
|
|
2
|
+
| 'public-runtime'
|
|
3
|
+
| 'public-structural'
|
|
4
|
+
| 'internal';
|
|
5
|
+
|
|
6
|
+
export interface ImportBinding {
|
|
7
|
+
readonly specifier: string;
|
|
8
|
+
readonly exportName: 'default' | string;
|
|
9
|
+
readonly canonical: boolean;
|
|
10
|
+
readonly note?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface MethodContract {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly signature: string;
|
|
16
|
+
readonly stage?: 'builder' | 'runtime' | 'composition';
|
|
17
|
+
readonly summary: string;
|
|
18
|
+
readonly constraints?: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface RuntimeComponentContract {
|
|
22
|
+
readonly alias: string;
|
|
23
|
+
readonly kind: 'class';
|
|
24
|
+
readonly role: string;
|
|
25
|
+
readonly imports: readonly ImportBinding[];
|
|
26
|
+
readonly methods: readonly MethodContract[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface StructuralContract {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly kind: 'dto' | 'enum' | 'protocol' | 'module-contract';
|
|
32
|
+
readonly summary: string;
|
|
33
|
+
readonly aliases?: readonly string[];
|
|
34
|
+
readonly fields?: Readonly<Record<string, string>>;
|
|
35
|
+
readonly values?: Readonly<Record<string, string>>;
|
|
36
|
+
readonly notes?: readonly string[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface TypeAliasClassification {
|
|
40
|
+
readonly alias: string;
|
|
41
|
+
readonly source: string;
|
|
42
|
+
readonly exposure: ApiExposure;
|
|
43
|
+
readonly reason: string;
|
|
44
|
+
readonly canonicalUse?: string;
|
|
45
|
+
readonly sameAs?: readonly string[];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface PackageApiContract {
|
|
49
|
+
readonly packageName: '@teqfw/di';
|
|
50
|
+
readonly packageRole: string;
|
|
51
|
+
readonly canonicalEntrypoints: readonly string[];
|
|
52
|
+
readonly publicRuntime: readonly RuntimeComponentContract[];
|
|
53
|
+
readonly structuralContracts: readonly StructuralContract[];
|
|
54
|
+
readonly typeMapClassification: readonly TypeAliasClassification[];
|
|
55
|
+
readonly operationalNotes: readonly string[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Public package contract intended for agents that consume `@teqfw/di`
|
|
60
|
+
* as an npm dependency.
|
|
61
|
+
*
|
|
62
|
+
* This file distinguishes between:
|
|
63
|
+
* - importable runtime API supported by `package.json#exports`
|
|
64
|
+
* - structural contracts that external code may rely on indirectly
|
|
65
|
+
* - internal implementation aliases present in `types.d.ts`
|
|
66
|
+
*/
|
|
67
|
+
export const PACKAGE_API: PackageApiContract = {
|
|
68
|
+
packageName: '@teqfw/di',
|
|
69
|
+
packageRole: 'Deterministic runtime DI container for native ES modules with explicit CDC contracts.',
|
|
70
|
+
canonicalEntrypoints: [
|
|
71
|
+
'@teqfw/di',
|
|
72
|
+
'@teqfw/di/src/Config/NamespaceRegistry.mjs',
|
|
73
|
+
],
|
|
74
|
+
publicRuntime: [
|
|
75
|
+
{
|
|
76
|
+
alias: 'TeqFw_Di_Container',
|
|
77
|
+
kind: 'class',
|
|
78
|
+
role: 'Primary runtime composition root. Resolves CDC identifiers into frozen linked values.',
|
|
79
|
+
imports: [
|
|
80
|
+
{
|
|
81
|
+
specifier: '@teqfw/di',
|
|
82
|
+
exportName: 'default',
|
|
83
|
+
canonical: true,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
specifier: '@teqfw/di/src/Container.mjs',
|
|
87
|
+
exportName: 'default',
|
|
88
|
+
canonical: false,
|
|
89
|
+
note: 'Explicit source subpath export. Prefer the package root import.',
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
methods: [
|
|
93
|
+
{
|
|
94
|
+
name: 'constructor',
|
|
95
|
+
signature: 'new Container()',
|
|
96
|
+
stage: 'builder',
|
|
97
|
+
summary: 'Creates a container in builder stage. The constructor accepts no arguments.',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'setParser',
|
|
101
|
+
signature: 'setParser(parser: { parse(cdc: string): TeqFw_Di_DepId$DTO }): void',
|
|
102
|
+
stage: 'builder',
|
|
103
|
+
summary: 'Replaces the default CDC parser before the first resolution.',
|
|
104
|
+
constraints: [
|
|
105
|
+
'Allowed only before the first get().',
|
|
106
|
+
'The parser contract is structural. The package does not export the default parser runtime class.',
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: 'addNamespaceRoot',
|
|
111
|
+
signature: 'addNamespaceRoot(prefix: string, target: string, defaultExt: string): void',
|
|
112
|
+
stage: 'builder',
|
|
113
|
+
summary: 'Registers one namespace-to-filesystem mapping rule.',
|
|
114
|
+
constraints: [
|
|
115
|
+
'Allowed only before the first get().',
|
|
116
|
+
'Namespace rules are snapshotted and locked on the first get().',
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'addPreprocess',
|
|
121
|
+
signature: 'addPreprocess(fn: (depId: TeqFw_Di_DepId$DTO) => TeqFw_Di_DepId$DTO): void',
|
|
122
|
+
stage: 'builder',
|
|
123
|
+
summary: 'Adds an ordered CDC preprocessing hook.',
|
|
124
|
+
constraints: [
|
|
125
|
+
'Allowed only before the first get().',
|
|
126
|
+
'Each hook must return another DepId DTO.',
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'addPostprocess',
|
|
131
|
+
signature: 'addPostprocess(fn: (value: unknown) => unknown): void',
|
|
132
|
+
stage: 'builder',
|
|
133
|
+
summary: 'Adds an ordered post-instantiation value transform applied to every resolved value.',
|
|
134
|
+
constraints: [
|
|
135
|
+
'Allowed only before the first get().',
|
|
136
|
+
'Runs before wrapper exports and before freeze.',
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'enableLogging',
|
|
141
|
+
signature: 'enableLogging(): void',
|
|
142
|
+
stage: 'builder',
|
|
143
|
+
summary: 'Turns on diagnostic console logging without changing linking semantics.',
|
|
144
|
+
constraints: [
|
|
145
|
+
'Allowed only before the first get().',
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'enableTestMode',
|
|
150
|
+
signature: 'enableTestMode(): void',
|
|
151
|
+
stage: 'builder',
|
|
152
|
+
summary: 'Enables structural mock registration for tests.',
|
|
153
|
+
constraints: [
|
|
154
|
+
'Allowed only before the first get().',
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'register',
|
|
159
|
+
signature: 'register(cdc: string, mock: unknown): void',
|
|
160
|
+
stage: 'builder',
|
|
161
|
+
summary: 'Registers a mock by canonical DepId identity after parsing the provided CDC.',
|
|
162
|
+
constraints: [
|
|
163
|
+
'Allowed only before the first get().',
|
|
164
|
+
'Requires enableTestMode() first.',
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'get',
|
|
169
|
+
signature: 'get(cdc: string): Promise<any>',
|
|
170
|
+
stage: 'runtime',
|
|
171
|
+
summary: 'Parses, resolves, instantiates, postprocesses, wraps, applies lifecycle, freezes, and returns a linked value.',
|
|
172
|
+
constraints: [
|
|
173
|
+
'The first get() locks configuration and creates internal infrastructure.',
|
|
174
|
+
'Any fatal pipeline error moves the container into failed state.',
|
|
175
|
+
'All subsequent get() calls reject once the container is failed.',
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
alias: 'TeqFw_Di_Config_NamespaceRegistry',
|
|
182
|
+
kind: 'class',
|
|
183
|
+
role: 'Composition-stage helper that discovers namespace roots from the root package and installed npm dependencies.',
|
|
184
|
+
imports: [
|
|
185
|
+
{
|
|
186
|
+
specifier: '@teqfw/di/src/Config/NamespaceRegistry.mjs',
|
|
187
|
+
exportName: 'default',
|
|
188
|
+
canonical: true,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
methods: [
|
|
192
|
+
{
|
|
193
|
+
name: 'constructor',
|
|
194
|
+
signature: 'new NamespaceRegistry({ fs, path, appRoot })',
|
|
195
|
+
stage: 'composition',
|
|
196
|
+
summary: 'Creates a registry builder over filesystem and path adapters.',
|
|
197
|
+
constraints: [
|
|
198
|
+
'Intended for composition root code, not for DI-managed runtime modules.',
|
|
199
|
+
'Consumes static package.json metadata only.',
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: 'build',
|
|
204
|
+
signature: 'build(): Promise<ReadonlyArray<{ prefix: string; dirAbs: string; ext: string }>>',
|
|
205
|
+
stage: 'composition',
|
|
206
|
+
summary: 'Builds an immutable namespace registry sorted by descending prefix length.',
|
|
207
|
+
constraints: [
|
|
208
|
+
'Fails fast on invalid namespace metadata or duplicate canonical prefixes.',
|
|
209
|
+
],
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
structuralContracts: [
|
|
215
|
+
{
|
|
216
|
+
name: 'DepId DTO',
|
|
217
|
+
kind: 'dto',
|
|
218
|
+
aliases: ['TeqFw_Di_DepId$DTO', 'TeqFw_Di_Dto_DepId$DTO'],
|
|
219
|
+
summary: 'Canonical structural dependency identity passed to preprocess hooks and expected from custom parsers.',
|
|
220
|
+
fields: {
|
|
221
|
+
moduleName: 'Logical module identifier without platform prefix.',
|
|
222
|
+
platform: '"teq" | "node" | "npm".',
|
|
223
|
+
exportName: 'Named export or "default"; null means whole-module/as-is resolution.',
|
|
224
|
+
composition: '"A" | "F" in the current implementation.',
|
|
225
|
+
life: '"S" | "T" | null in the current implementation.',
|
|
226
|
+
wrappers: 'Ordered wrapper export names.',
|
|
227
|
+
origin: 'Original CDC string for diagnostics.',
|
|
228
|
+
},
|
|
229
|
+
notes: [
|
|
230
|
+
'Identity excludes origin.',
|
|
231
|
+
'Consumers should treat it as a structural protocol, not as a factory import surface.',
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: 'Parser Protocol',
|
|
236
|
+
kind: 'protocol',
|
|
237
|
+
aliases: ['TeqFw_Di_Def_Parser'],
|
|
238
|
+
summary: 'Structural contract accepted by Container.setParser().',
|
|
239
|
+
fields: {
|
|
240
|
+
parse: '(cdc: string) => TeqFw_Di_DepId$DTO',
|
|
241
|
+
},
|
|
242
|
+
notes: [
|
|
243
|
+
'The package does not export the default parser runtime class through package exports.',
|
|
244
|
+
'External code may provide any object that satisfies the parse() contract.',
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: 'DepId Enums',
|
|
249
|
+
kind: 'enum',
|
|
250
|
+
aliases: [
|
|
251
|
+
'TeqFw_Di_Enum_Composition',
|
|
252
|
+
'TeqFw_Di_Enum_Life',
|
|
253
|
+
'TeqFw_Di_Enum_Platform',
|
|
254
|
+
],
|
|
255
|
+
summary: 'Current implementation literals used inside DepId DTO values.',
|
|
256
|
+
values: {
|
|
257
|
+
composition: 'AS_IS -> "A", FACTORY -> "F"',
|
|
258
|
+
life: 'SINGLETON -> "S", TRANSIENT -> "T"',
|
|
259
|
+
platform: 'TEQ -> "teq", NODE -> "node", NPM -> "npm"',
|
|
260
|
+
},
|
|
261
|
+
notes: [
|
|
262
|
+
'These aliases are useful for tooling and JSDoc, not for runtime imports from the package.',
|
|
263
|
+
],
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: 'Module Contract',
|
|
267
|
+
kind: 'module-contract',
|
|
268
|
+
summary: 'Shape expected from application modules resolved by the container.',
|
|
269
|
+
fields: {
|
|
270
|
+
__deps__: 'Optional top-level Record<string, string> mapping constructor keys to CDC strings.',
|
|
271
|
+
moduleNamespace: 'Whole ES module namespace object returned for as-is CDC without selected export.',
|
|
272
|
+
defaultExport: 'Used when the parsed DepId selects exportName="default" for factory composition.',
|
|
273
|
+
namedExports: 'May be selected via __ExportName for factory composition and may also provide wrapper functions.',
|
|
274
|
+
wrapperExport: 'Named export whose identifier appears in depId.wrappers; it must be synchronous and unary.',
|
|
275
|
+
},
|
|
276
|
+
notes: [
|
|
277
|
+
'The current runtime reads namespace.__deps__ directly; it does not use export-scoped dependency maps.',
|
|
278
|
+
'Wrapper functions are exported by the same resolved module namespace, not registered globally in the container.',
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
typeMapClassification: [
|
|
283
|
+
{
|
|
284
|
+
alias: 'TeqFw_Di_Config_NamespaceRegistry',
|
|
285
|
+
source: './src/Config/NamespaceRegistry.mjs',
|
|
286
|
+
exposure: 'public-runtime',
|
|
287
|
+
reason: 'Exported through package.json exports as a supported subpath entrypoint.',
|
|
288
|
+
canonicalUse: 'Composition-stage helper imported from @teqfw/di/src/Config/NamespaceRegistry.mjs.',
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
alias: 'TeqFw_Di_Container',
|
|
292
|
+
source: './src/Container.mjs',
|
|
293
|
+
exposure: 'public-runtime',
|
|
294
|
+
reason: 'Default export of the package root and of the explicit source subpath.',
|
|
295
|
+
canonicalUse: 'Primary container API imported from @teqfw/di.',
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
alias: 'TeqFw_Di_Container_Instantiate_ExportSelector',
|
|
299
|
+
source: './src/Container/Instantiate/ExportSelector.mjs',
|
|
300
|
+
exposure: 'internal',
|
|
301
|
+
reason: 'Internal immutable-core helper. Not exported via package.json.',
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
alias: 'TeqFw_Di_Container_Instantiate_Instantiator',
|
|
305
|
+
source: './src/Container/Instantiate/Instantiator.mjs',
|
|
306
|
+
exposure: 'internal',
|
|
307
|
+
reason: 'Internal immutable-core helper. Not exported via package.json.',
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
alias: 'TeqFw_Di_Container_Lifecycle_Registry',
|
|
311
|
+
source: './src/Container/Lifecycle/Registry.mjs',
|
|
312
|
+
exposure: 'internal',
|
|
313
|
+
reason: 'Internal lifecycle cache component. Not exported via package.json.',
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
alias: 'TeqFw_Di_Container_Resolve_GraphResolver',
|
|
317
|
+
source: './src/Container/Resolve/GraphResolver.mjs',
|
|
318
|
+
exposure: 'internal',
|
|
319
|
+
reason: 'Internal graph builder used by Container.get(). Not exported via package.json.',
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
alias: 'TeqFw_Di_Container_Wrapper_Executor',
|
|
323
|
+
source: './src/Container/Wrapper/Executor.mjs',
|
|
324
|
+
exposure: 'internal',
|
|
325
|
+
reason: 'Internal wrapper-stage executor. Not exported via package.json.',
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
alias: 'TeqFw_Di_Def_Parser',
|
|
329
|
+
source: './src/Def/Parser.mjs',
|
|
330
|
+
exposure: 'public-structural',
|
|
331
|
+
reason: 'Container.setParser() accepts this structural contract, but the runtime class is not importable from the package.',
|
|
332
|
+
canonicalUse: 'Typing/protocol alias for custom parser implementations.',
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
alias: 'TeqFw_Di_DepId',
|
|
336
|
+
source: './src/Dto/DepId.mjs',
|
|
337
|
+
exposure: 'internal',
|
|
338
|
+
reason: 'Factory class behind the DepId DTO module. Not needed for the supported package runtime API.',
|
|
339
|
+
sameAs: ['TeqFw_Di_Dto_DepId'],
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
alias: 'TeqFw_Di_DepId$DTO',
|
|
343
|
+
source: './src/Dto/DepId.mjs#DTO',
|
|
344
|
+
exposure: 'public-structural',
|
|
345
|
+
reason: 'Public structural protocol used by preprocess hooks and parser replacement.',
|
|
346
|
+
canonicalUse: 'Primary type alias for canonical dependency identity.',
|
|
347
|
+
sameAs: ['TeqFw_Di_Dto_DepId$DTO'],
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
alias: 'TeqFw_Di_Dto_DepId',
|
|
351
|
+
source: './src/Dto/DepId.mjs',
|
|
352
|
+
exposure: 'internal',
|
|
353
|
+
reason: 'Legacy-namespaced alias of the DepId factory class; not part of the supported runtime import surface.',
|
|
354
|
+
sameAs: ['TeqFw_Di_DepId'],
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
alias: 'TeqFw_Di_Dto_DepId$DTO',
|
|
358
|
+
source: './src/Dto/DepId.mjs#DTO',
|
|
359
|
+
exposure: 'public-structural',
|
|
360
|
+
reason: 'Synonym of TeqFw_Di_DepId$DTO kept in the type map.',
|
|
361
|
+
sameAs: ['TeqFw_Di_DepId$DTO'],
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
alias: 'TeqFw_Di_Dto_Resolver_Config',
|
|
365
|
+
source: './src/Dto/Resolver/Config.mjs',
|
|
366
|
+
exposure: 'internal',
|
|
367
|
+
reason: 'Internal DTO factory used inside Container when bootstrapping Resolver.',
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
alias: 'TeqFw_Di_Dto_Resolver_Config$DTO',
|
|
371
|
+
source: './src/Dto/Resolver/Config.mjs#DTO',
|
|
372
|
+
exposure: 'internal',
|
|
373
|
+
reason: 'Internal resolver configuration DTO. External code configures the container through addNamespaceRoot() instead.',
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
alias: 'TeqFw_Di_Dto_Resolver_Config_Namespace',
|
|
377
|
+
source: './src/Dto/Resolver/Config/Namespace.mjs',
|
|
378
|
+
exposure: 'internal',
|
|
379
|
+
reason: 'Internal DTO factory for resolver namespace rules.',
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
alias: 'TeqFw_Di_Dto_Resolver_Config_Namespace$DTO',
|
|
383
|
+
source: './src/Dto/Resolver/Config/Namespace.mjs#DTO',
|
|
384
|
+
exposure: 'internal',
|
|
385
|
+
reason: 'Internal resolver namespace DTO alias retained for type-map completeness.',
|
|
386
|
+
sameAs: ['TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$'],
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
alias: 'TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$',
|
|
390
|
+
source: './src/Dto/Resolver/Config/Namespace.mjs#DTO',
|
|
391
|
+
exposure: 'internal',
|
|
392
|
+
reason: 'Duplicate DTO alias retained for compatibility inside implementation typings.',
|
|
393
|
+
sameAs: ['TeqFw_Di_Dto_Resolver_Config_Namespace$DTO'],
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
alias: 'TeqFw_Di_Enum_Composition',
|
|
397
|
+
source: './src/Enum/Composition.mjs',
|
|
398
|
+
exposure: 'public-structural',
|
|
399
|
+
reason: 'Useful static vocabulary for interpreting DepId.composition values.',
|
|
400
|
+
canonicalUse: 'Type/JSDoc vocabulary only; no package export for runtime import.',
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
alias: 'TeqFw_Di_Enum_Life',
|
|
404
|
+
source: './src/Enum/Life.mjs',
|
|
405
|
+
exposure: 'public-structural',
|
|
406
|
+
reason: 'Useful static vocabulary for interpreting DepId.life values.',
|
|
407
|
+
canonicalUse: 'Type/JSDoc vocabulary only; no package export for runtime import.',
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
alias: 'TeqFw_Di_Enum_Platform',
|
|
411
|
+
source: './src/Enum/Platform.mjs',
|
|
412
|
+
exposure: 'public-structural',
|
|
413
|
+
reason: 'Useful static vocabulary for interpreting DepId.platform values.',
|
|
414
|
+
canonicalUse: 'Type/JSDoc vocabulary only; no package export for runtime import.',
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
alias: 'TeqFw_Di_Internal_Logger',
|
|
418
|
+
source: './src/Internal/Logger.mjs',
|
|
419
|
+
exposure: 'internal',
|
|
420
|
+
reason: 'Diagnostic helper used only inside the container implementation.',
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
alias: 'TeqFw_Di_Resolver',
|
|
424
|
+
source: './src/Container/Resolver.mjs',
|
|
425
|
+
exposure: 'internal',
|
|
426
|
+
reason: 'Internal module resolver infrastructure. Consumers should configure the Container, not instantiate Resolver directly.',
|
|
427
|
+
},
|
|
428
|
+
],
|
|
429
|
+
operationalNotes: [
|
|
430
|
+
'Only two runtime entrypoints are supported by package.json exports: @teqfw/di and @teqfw/di/src/Config/NamespaceRegistry.mjs.',
|
|
431
|
+
'Resolved values are frozen before being returned.',
|
|
432
|
+
'The current runtime reads __deps__ as a flat top-level map exported by the module namespace.',
|
|
433
|
+
'With the default parser, CDC without lifecycle returns the whole module namespace as-is; named export selection implies factory composition.',
|
|
434
|
+
'Named wrapper exports are executed after addPostprocess() hooks and before freeze.',
|
|
435
|
+
'In the current implementation, CDC markers $$ and $$$ both end up as transient/no-cache behavior.',
|
|
436
|
+
'types.d.ts is broader than the runtime import surface. Presence of an alias there does not by itself make the underlying module a supported runtime entrypoint.',
|
|
437
|
+
],
|
|
438
|
+
} as const;
|
|
439
|
+
|
|
440
|
+
export default PACKAGE_API;
|
package/dist/esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e={AS_IS:"A",FACTORY:"F"},t={SINGLETON:"S",TRANSIENT:"T"},o={TEQ:"teq",NODE:"node",NPM:"npm"},r=o.TEQ,n=e.AS_IS,i=new Set(Object.values(o)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let l=class{moduleName;platform;exportName;composition;life;wrappers;origin},c=class{create(e,t){const o=e&&"object"==typeof e?e:{},c=new l;c.moduleName="string"==typeof o.moduleName?o.moduleName:"";const p="string"==typeof o.platform?o.platform:void 0;c.platform=p&&i.has(p)?p:r;let f=null;null===o.exportName?f=null:"string"==typeof o.exportName&&(f=o.exportName),c.exportName=f;const u="string"==typeof o.composition?o.composition:void 0;c.composition=u&&s.has(u)?u:n;const m="string"==typeof o.life?o.life:void 0;return c.life=m&&a.has(m)?m:null,c.wrappers=Array.isArray(o.wrappers)?o.wrappers.filter(e=>"string"==typeof e):[],c.origin="string"==typeof o.origin?o.origin:"",!0===t?.immutable&&(Object.freeze(c.wrappers),Object.freeze(c)),c}};class p{constructor(){const r=new c;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("CDC must be a string.");if(0===i.length)throw new Error("CDC must be non-empty.");if(!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(i))throw new Error("CDC must satisfy AsciiCdcIdentifier.");const s=i;let a=i,l=o.TEQ;if(a.startsWith("node_"))l=o.NODE,a=a.slice(5);else if(a.startsWith("npm_"))l=o.NPM,a=a.slice(4);else if(a.startsWith("teq_"))throw new Error("Explicit teq_ prefix is forbidden.");if(0===a.length)throw new Error("moduleName must be non-empty.");const c=a.match(/(\${1,3})(?:_([A-Za-z0-9]+(?:_[A-Za-z0-9]+)*))?$/);let p=null,f=[],u=a;if(c){const e=c[1],o=c[2];if("$"===e)p=t.SINGLETON;else{if("$$"!==e&&"$$$"!==e)throw new Error("Lifecycle marker overflow.");p=t.TRANSIENT}if(u=a.slice(0,c.index),o){f=o.split("_");for(const e of f){if(!e)throw new Error("Wrapper must be non-empty.");if(e.includes("$"))throw new Error("Wrapper must not contain $.");if(e.includes("_"))throw new Error("Wrapper must not contain _.")}}}else{if(a.includes("$"))throw new Error("Invalid lifecycle marker.");if(a.match(/(?:^|[^_])_([a-z][A-Za-z0-9]*)$/))throw new Error("Wrapper without lifecycle is forbidden.")}if(u.includes("$$$$"))throw new Error("Lifecycle marker overflow.");const m=u.indexOf("__"),d=u.lastIndexOf("__");if(-1!==m&&m!==d)throw new Error("Export delimiter must appear at most once.");if(u.startsWith("__")||u.endsWith("__"))throw new Error("Malformed export segment.");let g=u,w=null;if(-1!==m){if(g=u.slice(0,m),w=u.slice(m+2),!w)throw new Error("Export must be non-empty.");if(w.includes("_"))throw new Error("Export must not contain _.");if(w.includes("$"))throw new Error("Export must not contain $.")}if(!g)throw new Error("moduleName must be non-empty.");if(g.startsWith("_")||g.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(g.includes("__"))throw new Error("moduleName must not contain __.");if(g.includes("$"))throw new Error("moduleName must not contain $.");let h=e.AS_IS;null!==w?h=e.FACTORY:p===t.SINGLETON?(w="default",h=e.FACTORY):p===t.TRANSIENT&&(h=e.FACTORY,null===w&&(w="default"));const $=r.create({moduleName:g,platform:l,exportName:w,composition:h,life:p,wrappers:f,origin:s},{immutable:!0});return n&&n.log(`Parser.parse: produced='${$.platform}::${$.moduleName}'.`),$},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e,t){const o=e&&"object"==typeof e?e:{},r=t&&"object"==typeof t?t:{},n=new f;return n.prefix="string"==typeof o.prefix?o.prefix:void 0,n.target="string"==typeof o.target?o.target:void 0,n.defaultExt="string"==typeof o.defaultExt?o.defaultExt:void 0,!0===r.immutable&&Object.freeze(n),n}};class m{namespaces;nodeModulesRoot}class d{constructor(){const e=new u;this.create=function(t,o){const r=t&&"object"==typeof t?t:{},n=o&&"object"==typeof o?o:{},i=new m,s=Array.isArray(r.namespaces)?r.namespaces:[];return i.namespaces=s.map(t=>e.create(t,n)),i.nodeModulesRoot="string"==typeof r.nodeModulesRoot?r.nodeModulesRoot:void 0,!0===n.immutable&&(Object.freeze(i.namespaces),Object.freeze(i)),i}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:o=null}){const r=new Map,n=e;let i;const s=t,a=o,l=function(e,t){if("node"===e){const e=`node:${t}`;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("teq"!==e)throw new Error(`Unsupported platform: ${e}`);const o=function(e){let t=null,o=-1;const r=i.namespaces;for(const n of r){const r=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(r)} module='${e}'.`),r&&n.prefix.length>o&&(t=n,o=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),r=t.slice(o.prefix.length).split("_").join("/"),n=(s=r,(l=o.defaultExt)?s.endsWith(l)?s:`${s}${l}`:s);var s,l;const c=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(o.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${c}'.`),c};this.resolve=async function(e){var t;await Promise.resolve(),i||(i={nodeModulesRoot:(t=n).nodeModulesRoot,namespaces:t.namespaces.map(e=>({prefix:e.prefix,target:e.target,defaultExt:e.defaultExt}))});const o=e.platform,c=e.moduleName,p=`${o}::${c}`;if(r.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),r.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=l(o,c);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();r.set(p,f);try{return await f}catch(e){throw r.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}class w{constructor({parser:e,resolver:t,logger:o=null}){const r=o,n=async function(o,i,s,a){const l=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(s.has(l)){const e=[...a,l].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const c=function(e){return`${e.platform}::${e.moduleName}`}(o);if(!i.has(c)){s.add(l),a.push(l);try{const l=await t.resolve(o);r&&r.log(`GraphResolver.walk: resolved '${c}'.`),i.set(c,{depId:o,namespace:l});const p=Reflect.get(l,"__deps__");if(void 0===p)return;const f=p;for(const[,t]of Object.entries(f)){const o=t,l=e.parse(o);r&&r.log(`GraphResolver.walk: edge '${c}' -> '${l.platform}::${l.moduleName}'.`),await n(l,i,s,a)}}finally{a.pop(),s.delete(l)}}};this.resolve=async function(e){const t=new Map,o=new Set;return await n(e,t,o,[]),t}}}class h{constructor(){this.instantiate=function(t,o,r){const n=function(e,t){if(null===e.exportName)return t;if(!(e.exportName in t))throw new Error(`Export '${e.exportName}' is not found in module namespace.`);return t[e.exportName]}(t,o);if(t.composition===e.AS_IS)return n;if(t.composition===e.FACTORY){if("function"!=typeof n)throw new Error("Factory composition requires a callable export.");const e=n;let t;if(function(e){try{return Reflect.construct(String,[],e),!0}catch{return!1}}(e)){t=new e(r)}else{t=e(r)}if(function(e){if(null==e)return!1;const t=typeof e;return("object"===t||"function"===t)&&"function"==typeof e.then}(t))throw new Error("Factory composition must return synchronously (non-thenable).");return t}throw new Error(`Unsupported composition mode: ${String(t.composition)}.`)}}}class ${constructor(o=null){const r=new Map,n=o;this.apply=function(o,i){if(o.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${o.composition}' cache=skip.`),i();if(o.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),i();if(o.life===t.SINGLETON){const e=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(r.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),r.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=i();return r.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),i()}}}class y{constructor(){const e=function(e){if(null==e)return!1;const t=typeof e;if("object"!==t&&"function"!==t)return!1;return"function"==typeof e.then},t=function(e){return"function"==typeof e};this.execute=function(o,r,n){let i=r;const s=o.wrappers;for(const o of s){if(!(o in n))throw new Error(`Wrapper '${o}' is not found in module namespace.`);const r=n[o];if(!t(r))throw new Error(`Wrapper '${o}' must be callable.`);if(i=r(i),e(i))throw new Error(`Wrapper '${o}' must return synchronously (non-thenable).`)}return i}}}class N{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,o){console.error(`${t} ${e}`),o instanceof Error?console.error(o.stack??o.message):void 0!==o&&console.error(o)}}}const E=Object.freeze({log(){},error(){}});class x{constructor(){let e="notConfigured";const t=[],o=[],r=[],n=new Map;let i=!1,s=!1,a=new p;const l=new d;let c,f,u,m=E;const x=new h,C=new y,b=function(e){return`${e.platform}::${e.moduleName}`},_=function(e){const t=null===e.exportName?"":e.exportName,o=null===e.life?"":e.life,r=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,o,r].join("::")},v=function(e){if(null==e)return e;const t=typeof e;return"object"!==t&&"function"!==t||"[object Module]"===Object.prototype.toString.call(e)||Object.isFrozen(e)||Object.freeze(e),e},I=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},j=function(e){s&&m.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){I(),j("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){I(),j("addPostprocess()."),o.push(e)},this.setParser=function(e){I(),a=e,"function"==typeof a.setLogger&&a.setLogger(s?m:null),j("setParser().")},this.addNamespaceRoot=function(e,t,o){I(),j(`addNamespaceRoot('${e}').`),r.push({prefix:e,target:t,defaultExt:o})},this.enableTestMode=function(){I(),j("enableTestMode()."),i=!0},this.enableLogging=function(){I(),s||(s=!0,m=new N,"function"==typeof a.setLogger&&a.setLogger(m),m.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(I(),j(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const o=a.parse(e);n.set(_(o),t)},this.get=async function(s){if("failed"===e)throw m.error(`Container.get: rejected in failed state cdc='${s}'.`),new Error("Container is in failed state.");let p="start";try{m.log(`Container.get: cdc='${s}'.`),function(){if("notConfigured"!==e)return;m.log("Container.transition: notConfigured -> operational."),e="operational";const t=l.create({namespaces:r},{immutable:!0});"function"==typeof a.setLogger&&a.setLogger(m),c=new g({config:t,logger:m}),f=new w({parser:a,resolver:c,logger:m}),u=new $(m)}(),m.log(`Container.state: '${e}'.`),p="parse",m.log("Container.pipeline: parse:entry.");const d=a.parse(s);m.log(`Container.pipeline: parse:exit '${d.platform}::${d.moduleName}'.`),p="preprocess",m.log("Container.pipeline: preprocess:entry.");const h=function(e){let o=e;for(const e of t)o=e(o);return o}(d);if(m.log(`Container.pipeline: preprocess:exit '${h.platform}::${h.moduleName}'.`),!0===i){p="mock",m.log("Container.pipeline: mock-lookup:entry.");const e=_(h);if(n.has(e)){m.log(`Container.pipeline: mock-lookup:hit '${e}'.`),p="freeze",m.log("Container.pipeline: freeze:entry.");const t=v(n.get(e));return m.log("Container.pipeline: freeze:exit."),m.log("Container.pipeline: return:success."),t}m.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else m.log("Container.pipeline: mock-lookup:disabled.");p="resolve",m.log("Container.pipeline: resolve:entry.");const y=await f.resolve(h);m.log(`Container.pipeline: resolve:exit nodes=${y.size}.`);const N=new Map,E=function(e){if(N.has(e))return N.get(e);if(!y.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=y.get(e);p="lifecycle",m.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=u.apply(t.depId,function(){p="instantiate",m.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},r=function(e){const t=Reflect.get(e,"__deps__");return void 0===t?{}:t}(t.namespace);for(const[t,o]of Object.entries(r)){const r=o,n=a.parse(r);e[t]=E(b(n))}const n=x.instantiate(t.depId,t.namespace,e);m.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),p="postprocess",m.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=function(e){let t=e;for(const e of o)t=e(t);return t}(n);m.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const s=C.execute(t.depId,i,t.namespace);p="freeze",m.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const l=v(s);return m.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),l});return m.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),N.set(e,r),r},I=E(b(h));return m.log("Container.pipeline: return:success."),I}catch(t){throw m.error(`Container.pipeline: failed at stage='${p}'.`,t),m.log("Container.transition: operational -> failed."),e="failed",t}}}}export{x as default};
|
|
1
|
+
var e=Object.freeze({AS_IS:"A",FACTORY:"F"});var t=Object.freeze({SINGLETON:"S",TRANSIENT:"T"});var o=Object.freeze({TEQ:"teq",NODE:"node",NPM:"npm"});const r=o.TEQ,n=e.AS_IS,i=new Set(Object.values(o)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let l=class{moduleName;platform;exportName;composition;life;wrappers;origin},c=class{create(e){const t=e&&"object"==typeof e?e:{},o=new l;o.moduleName="string"==typeof t.moduleName?t.moduleName:"";const c="string"==typeof t.platform?t.platform:void 0;o.platform=c&&i.has(c)?c:r;let p=null;null===t.exportName?p=null:"string"==typeof t.exportName&&(p=t.exportName),o.exportName=p;const f="string"==typeof t.composition?t.composition:void 0;o.composition=f&&s.has(f)?f:n;const u="string"==typeof t.life?t.life:void 0;return o.life=u&&a.has(u)?u:null,o.wrappers=Array.isArray(t.wrappers)?t.wrappers.filter(e=>"string"==typeof e):[],o.origin="string"==typeof t.origin?t.origin:"",Object.freeze(o.wrappers),Object.freeze(o)}};class p{constructor(){const r=new c;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("CDC must be a string.");if(0===i.length)throw new Error("CDC must be non-empty.");if(!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(i))throw new Error("CDC must satisfy AsciiCdcIdentifier.");const s=i;let a=i,l=o.TEQ;if(a.startsWith("node_"))l=o.NODE,a=a.slice(5);else if(a.startsWith("npm_"))l=o.NPM,a=a.slice(4);else if(a.startsWith("teq_"))throw new Error("Explicit teq_ prefix is forbidden.");if(0===a.length)throw new Error("moduleName must be non-empty.");const c=a.match(/(\${1,3})(?:_([A-Za-z0-9]+(?:_[A-Za-z0-9]+)*))?$/);let p=null,f=[],u=a;if(c){const e=c[1],o=c[2];if("$"===e)p=t.SINGLETON;else{if("$$"!==e&&"$$$"!==e)throw new Error("Lifecycle marker overflow.");p=t.TRANSIENT}if(u=a.slice(0,c.index),o){f=o.split("_");for(const e of f){if(!e)throw new Error("Wrapper must be non-empty.");if(e.includes("$"))throw new Error("Wrapper must not contain $.");if(e.includes("_"))throw new Error("Wrapper must not contain _.")}}}else{if(a.includes("$"))throw new Error("Invalid lifecycle marker.");if(a.match(/(?:^|[^_])_([a-z][A-Za-z0-9]*)$/))throw new Error("Wrapper without lifecycle is forbidden.")}if(u.includes("$$$$"))throw new Error("Lifecycle marker overflow.");const d=u.indexOf("__"),m=u.lastIndexOf("__");if(-1!==d&&d!==m)throw new Error("Export delimiter must appear at most once.");if(u.startsWith("__")||u.endsWith("__"))throw new Error("Malformed export segment.");let g=u,w=null;if(-1!==d){if(g=u.slice(0,d),w=u.slice(d+2),!w)throw new Error("Export must be non-empty.");if(w.includes("_"))throw new Error("Export must not contain _.");if(w.includes("$"))throw new Error("Export must not contain $.")}if(!g)throw new Error("moduleName must be non-empty.");if(g.startsWith("_")||g.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(g.includes("__"))throw new Error("moduleName must not contain __.");if(g.includes("$"))throw new Error("moduleName must not contain $.");let h=e.AS_IS;null!==w?h=e.FACTORY:p===t.SINGLETON?(w="default",h=e.FACTORY):p===t.TRANSIENT&&(h=e.FACTORY,null===w&&(w="default"));const $=r.create({moduleName:g,platform:l,exportName:w,composition:h,life:p,wrappers:f,origin:s});return n&&n.log(`Parser.parse: produced='${$.platform}::${$.moduleName}'.`),$},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e){const t=e&&"object"==typeof e?e:{},o=new f;return o.prefix="string"==typeof t.prefix?t.prefix:void 0,o.target="string"==typeof t.target?t.target:void 0,o.defaultExt="string"==typeof t.defaultExt?t.defaultExt:void 0,Object.freeze(o)}};class d{namespaces;nodeModulesRoot}class m{constructor(){const e=new u;this.create=function(t){const o=t&&"object"==typeof t?t:{},r=new d,n=Array.isArray(o.namespaces)?o.namespaces:[];return r.namespaces=n.map(t=>e.create(t)),r.nodeModulesRoot="string"==typeof o.nodeModulesRoot?o.nodeModulesRoot:void 0,Object.freeze(r.namespaces),Object.freeze(r)}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:o=null}){const r=new Map,n=e;let i;const s=t,a=o,l=function(e,t){if("node"===e){const e=`node:${t}`;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("teq"!==e)throw new Error(`Unsupported platform: ${e}`);const o=function(e){let t=null,o=-1;const r=i.namespaces;for(const n of r){const r=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(r)} module='${e}'.`),r&&n.prefix.length>o&&(t=n,o=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),r=t.slice(o.prefix.length).split("_").join("/"),n=(s=r,(l=o.defaultExt)?s.endsWith(l)?s:`${s}${l}`:s);var s,l;const c=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(o.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${c}'.`),c};this.resolve=async function(e){var t;await Promise.resolve(),i||(i={nodeModulesRoot:(t=n).nodeModulesRoot,namespaces:t.namespaces.map(e=>({prefix:e.prefix,target:e.target,defaultExt:e.defaultExt}))});const o=e.platform,c=e.moduleName,p=`${o}::${c}`;if(r.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),r.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=l(o,c);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();r.set(p,f);try{return await f}catch(e){throw r.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}class w{constructor({parser:e,resolver:t,logger:o=null}){const r=o,n=async function(o,i,s,a){const l=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(s.has(l)){const e=[...a,l].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const c=function(e){return`${e.platform}::${e.moduleName}`}(o);if(!i.has(c)){s.add(l),a.push(l);try{const l=await t.resolve(o);r&&r.log(`GraphResolver.walk: resolved '${c}'.`),i.set(c,{depId:o,namespace:l});const p=Reflect.get(l,"__deps__");if(void 0===p)return;const f=p;for(const[,t]of Object.entries(f)){const o=t,l=e.parse(o);r&&r.log(`GraphResolver.walk: edge '${c}' -> '${l.platform}::${l.moduleName}'.`),await n(l,i,s,a)}}finally{a.pop(),s.delete(l)}}};this.resolve=async function(e){const t=new Map,o=new Set;return await n(e,t,o,[]),t}}}class h{constructor(){this.instantiate=function(t,o,r){const n=function(e,t){if(null===e.exportName)return t;if(!(e.exportName in t))throw new Error(`Export '${e.exportName}' is not found in module namespace.`);return t[e.exportName]}(t,o);if(t.composition===e.AS_IS)return n;if(t.composition===e.FACTORY){if("function"!=typeof n)throw new Error("Factory composition requires a callable export.");const e=n;let t;if(function(e){try{return Reflect.construct(String,[],e),!0}catch{return!1}}(e)){t=new e(r)}else{t=e(r)}if(function(e){if(null==e)return!1;const t=typeof e;return("object"===t||"function"===t)&&"function"==typeof e.then}(t))throw new Error("Factory composition must return synchronously (non-thenable).");return t}throw new Error(`Unsupported composition mode: ${String(t.composition)}.`)}}}class ${constructor(o=null){const r=new Map,n=o;this.apply=function(o,i){if(o.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${o.composition}' cache=skip.`),i();if(o.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),i();if(o.life===t.SINGLETON){const e=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(r.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),r.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=i();return r.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),i()}}}class y{constructor(){const e=function(e){if(null==e)return!1;const t=typeof e;if("object"!==t&&"function"!==t)return!1;return"function"==typeof e.then},t=function(e){return"function"==typeof e};this.execute=function(o,r,n){let i=r;const s=o.wrappers;for(const o of s){if(!(o in n))throw new Error(`Wrapper '${o}' is not found in module namespace.`);const r=n[o];if(!t(r))throw new Error(`Wrapper '${o}' must be callable.`);if(i=r(i),e(i))throw new Error(`Wrapper '${o}' must return synchronously (non-thenable).`)}return i}}}class N{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,o){console.error(`${t} ${e}`),o instanceof Error?console.error(o.stack??o.message):void 0!==o&&console.error(o)}}}const E=Object.freeze({log(){},error(){}});class x{constructor(){let e="notConfigured";const t=[],o=[],r=[],n=new Map;let i=!1,s=!1,a=new p;const l=new m;let c,f,u,d=E;const x=new h,C=new y,b=function(e){return`${e.platform}::${e.moduleName}`},v=function(e){const t=null===e.exportName?"":e.exportName,o=null===e.life?"":e.life,r=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,o,r].join("::")},_=function(e){if(null==e)return e;const t=typeof e;return"object"!==t&&"function"!==t||"[object Module]"===Object.prototype.toString.call(e)||Object.isFrozen(e)||Object.freeze(e),e},I=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},j=function(e){s&&d.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){I(),j("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){I(),j("addPostprocess()."),o.push(e)},this.setParser=function(e){I(),a=e,"function"==typeof a.setLogger&&a.setLogger(s?d:null),j("setParser().")},this.addNamespaceRoot=function(e,t,o){I(),j(`addNamespaceRoot('${e}').`),r.push({prefix:e,target:t,defaultExt:o})},this.enableTestMode=function(){I(),j("enableTestMode()."),i=!0},this.enableLogging=function(){I(),s||(s=!0,d=new N,"function"==typeof a.setLogger&&a.setLogger(d),d.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(I(),j(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const o=a.parse(e);n.set(v(o),t)},this.get=async function(s){if("failed"===e)throw d.error(`Container.get: rejected in failed state cdc='${s}'.`),new Error("Container is in failed state.");let p="start";try{d.log(`Container.get: cdc='${s}'.`),function(){if("notConfigured"!==e)return;d.log("Container.transition: notConfigured -> operational."),e="operational";const t=l.create({namespaces:r});"function"==typeof a.setLogger&&a.setLogger(d),c=new g({config:t,logger:d}),f=new w({parser:a,resolver:c,logger:d}),u=new $(d)}(),d.log(`Container.state: '${e}'.`),p="parse",d.log("Container.pipeline: parse:entry.");const m=a.parse(s);d.log(`Container.pipeline: parse:exit '${m.platform}::${m.moduleName}'.`),p="preprocess",d.log("Container.pipeline: preprocess:entry.");const h=function(e){let o=e;for(const e of t)o=e(o);return o}(m);if(d.log(`Container.pipeline: preprocess:exit '${h.platform}::${h.moduleName}'.`),!0===i){p="mock",d.log("Container.pipeline: mock-lookup:entry.");const e=v(h);if(n.has(e)){d.log(`Container.pipeline: mock-lookup:hit '${e}'.`),p="freeze",d.log("Container.pipeline: freeze:entry.");const t=_(n.get(e));return d.log("Container.pipeline: freeze:exit."),d.log("Container.pipeline: return:success."),t}d.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else d.log("Container.pipeline: mock-lookup:disabled.");p="resolve",d.log("Container.pipeline: resolve:entry.");const y=await f.resolve(h);d.log(`Container.pipeline: resolve:exit nodes=${y.size}.`);const N=new Map,E=function(e){if(N.has(e))return N.get(e);if(!y.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=y.get(e);p="lifecycle",d.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=u.apply(t.depId,function(){p="instantiate",d.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},r=function(e){const t=Reflect.get(e,"__deps__");return void 0===t?{}:t}(t.namespace);for(const[t,o]of Object.entries(r)){const r=o,n=a.parse(r);e[t]=E(b(n))}const n=x.instantiate(t.depId,t.namespace,e);d.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),p="postprocess",d.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=function(e){let t=e;for(const e of o)t=e(t);return t}(n);d.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const s=C.execute(t.depId,i,t.namespace);p="freeze",d.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const l=_(s);return d.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),l});return d.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),N.set(e,r),r},I=E(b(h));return d.log("Container.pipeline: return:success."),I}catch(t){throw d.error(`Container.pipeline: failed at stage='${p}'.`,t),d.log("Container.transition: operational -> failed."),e="failed",t}}}}export{x as default};
|
package/dist/umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).TeqFw_Di_Container=t()}(this,function(){"use strict";const e={AS_IS:"A",FACTORY:"F"},t={SINGLETON:"S",TRANSIENT:"T"},o={TEQ:"teq",NODE:"node",NPM:"npm"},r=o.TEQ,n=e.AS_IS,i=new Set(Object.values(o)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let l=class{moduleName;platform;exportName;composition;life;wrappers;origin},c=class{create(e,t){const o=e&&"object"==typeof e?e:{},c=new l;c.moduleName="string"==typeof o.moduleName?o.moduleName:"";const p="string"==typeof o.platform?o.platform:void 0;c.platform=p&&i.has(p)?p:r;let f=null;null===o.exportName?f=null:"string"==typeof o.exportName&&(f=o.exportName),c.exportName=f;const u="string"==typeof o.composition?o.composition:void 0;c.composition=u&&s.has(u)?u:n;const m="string"==typeof o.life?o.life:void 0;return c.life=m&&a.has(m)?m:null,c.wrappers=Array.isArray(o.wrappers)?o.wrappers.filter(e=>"string"==typeof e):[],c.origin="string"==typeof o.origin?o.origin:"",!0===t?.immutable&&(Object.freeze(c.wrappers),Object.freeze(c)),c}};class p{constructor(){const r=new c;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("CDC must be a string.");if(0===i.length)throw new Error("CDC must be non-empty.");if(!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(i))throw new Error("CDC must satisfy AsciiCdcIdentifier.");const s=i;let a=i,l=o.TEQ;if(a.startsWith("node_"))l=o.NODE,a=a.slice(5);else if(a.startsWith("npm_"))l=o.NPM,a=a.slice(4);else if(a.startsWith("teq_"))throw new Error("Explicit teq_ prefix is forbidden.");if(0===a.length)throw new Error("moduleName must be non-empty.");const c=a.match(/(\${1,3})(?:_([A-Za-z0-9]+(?:_[A-Za-z0-9]+)*))?$/);let p=null,f=[],u=a;if(c){const e=c[1],o=c[2];if("$"===e)p=t.SINGLETON;else{if("$$"!==e&&"$$$"!==e)throw new Error("Lifecycle marker overflow.");p=t.TRANSIENT}if(u=a.slice(0,c.index),o){f=o.split("_");for(const e of f){if(!e)throw new Error("Wrapper must be non-empty.");if(e.includes("$"))throw new Error("Wrapper must not contain $.");if(e.includes("_"))throw new Error("Wrapper must not contain _.")}}}else{if(a.includes("$"))throw new Error("Invalid lifecycle marker.");if(a.match(/(?:^|[^_])_([a-z][A-Za-z0-9]*)$/))throw new Error("Wrapper without lifecycle is forbidden.")}if(u.includes("$$$$"))throw new Error("Lifecycle marker overflow.");const m=u.indexOf("__"),d=u.lastIndexOf("__");if(-1!==m&&m!==d)throw new Error("Export delimiter must appear at most once.");if(u.startsWith("__")||u.endsWith("__"))throw new Error("Malformed export segment.");let g=u,w=null;if(-1!==m){if(g=u.slice(0,m),w=u.slice(m+2),!w)throw new Error("Export must be non-empty.");if(w.includes("_"))throw new Error("Export must not contain _.");if(w.includes("$"))throw new Error("Export must not contain $.")}if(!g)throw new Error("moduleName must be non-empty.");if(g.startsWith("_")||g.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(g.includes("__"))throw new Error("moduleName must not contain __.");if(g.includes("$"))throw new Error("moduleName must not contain $.");let h=e.AS_IS;null!==w?h=e.FACTORY:p===t.SINGLETON?(w="default",h=e.FACTORY):p===t.TRANSIENT&&(h=e.FACTORY,null===w&&(w="default"));const $=r.create({moduleName:g,platform:l,exportName:w,composition:h,life:p,wrappers:f,origin:s},{immutable:!0});return n&&n.log(`Parser.parse: produced='${$.platform}::${$.moduleName}'.`),$},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e,t){const o=e&&"object"==typeof e?e:{},r=t&&"object"==typeof t?t:{},n=new f;return n.prefix="string"==typeof o.prefix?o.prefix:void 0,n.target="string"==typeof o.target?o.target:void 0,n.defaultExt="string"==typeof o.defaultExt?o.defaultExt:void 0,!0===r.immutable&&Object.freeze(n),n}};class m{namespaces;nodeModulesRoot}class d{constructor(){const e=new u;this.create=function(t,o){const r=t&&"object"==typeof t?t:{},n=o&&"object"==typeof o?o:{},i=new m,s=Array.isArray(r.namespaces)?r.namespaces:[];return i.namespaces=s.map(t=>e.create(t,n)),i.nodeModulesRoot="string"==typeof r.nodeModulesRoot?r.nodeModulesRoot:void 0,!0===n.immutable&&(Object.freeze(i.namespaces),Object.freeze(i)),i}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:o=null}){const r=new Map,n=e;let i;const s=t,a=o,l=function(e,t){if("node"===e){const e=`node:${t}`;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("teq"!==e)throw new Error(`Unsupported platform: ${e}`);const o=function(e){let t=null,o=-1;const r=i.namespaces;for(const n of r){const r=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(r)} module='${e}'.`),r&&n.prefix.length>o&&(t=n,o=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),r=t.slice(o.prefix.length).split("_").join("/"),n=(s=r,(l=o.defaultExt)?s.endsWith(l)?s:`${s}${l}`:s);var s,l;const c=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(o.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${c}'.`),c};this.resolve=async function(e){var t;await Promise.resolve(),i||(i={nodeModulesRoot:(t=n).nodeModulesRoot,namespaces:t.namespaces.map(e=>({prefix:e.prefix,target:e.target,defaultExt:e.defaultExt}))});const o=e.platform,c=e.moduleName,p=`${o}::${c}`;if(r.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),r.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=l(o,c);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();r.set(p,f);try{return await f}catch(e){throw r.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}class w{constructor({parser:e,resolver:t,logger:o=null}){const r=o,n=async function(o,i,s,a){const l=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(s.has(l)){const e=[...a,l].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const c=function(e){return`${e.platform}::${e.moduleName}`}(o);if(!i.has(c)){s.add(l),a.push(l);try{const l=await t.resolve(o);r&&r.log(`GraphResolver.walk: resolved '${c}'.`),i.set(c,{depId:o,namespace:l});const p=Reflect.get(l,"__deps__");if(void 0===p)return;const f=p;for(const[,t]of Object.entries(f)){const o=t,l=e.parse(o);r&&r.log(`GraphResolver.walk: edge '${c}' -> '${l.platform}::${l.moduleName}'.`),await n(l,i,s,a)}}finally{a.pop(),s.delete(l)}}};this.resolve=async function(e){const t=new Map,o=new Set;return await n(e,t,o,[]),t}}}class h{constructor(){this.instantiate=function(t,o,r){const n=function(e,t){if(null===e.exportName)return t;if(!(e.exportName in t))throw new Error(`Export '${e.exportName}' is not found in module namespace.`);return t[e.exportName]}(t,o);if(t.composition===e.AS_IS)return n;if(t.composition===e.FACTORY){if("function"!=typeof n)throw new Error("Factory composition requires a callable export.");const e=n;let t;if(function(e){try{return Reflect.construct(String,[],e),!0}catch{return!1}}(e)){t=new e(r)}else{t=e(r)}if(function(e){if(null==e)return!1;const t=typeof e;return("object"===t||"function"===t)&&"function"==typeof e.then}(t))throw new Error("Factory composition must return synchronously (non-thenable).");return t}throw new Error(`Unsupported composition mode: ${String(t.composition)}.`)}}}class ${constructor(o=null){const r=new Map,n=o;this.apply=function(o,i){if(o.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${o.composition}' cache=skip.`),i();if(o.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),i();if(o.life===t.SINGLETON){const e=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(r.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),r.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=i();return r.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),i()}}}class y{constructor(){const e=function(e){if(null==e)return!1;const t=typeof e;if("object"!==t&&"function"!==t)return!1;return"function"==typeof e.then},t=function(e){return"function"==typeof e};this.execute=function(o,r,n){let i=r;const s=o.wrappers;for(const o of s){if(!(o in n))throw new Error(`Wrapper '${o}' is not found in module namespace.`);const r=n[o];if(!t(r))throw new Error(`Wrapper '${o}' must be callable.`);if(i=r(i),e(i))throw new Error(`Wrapper '${o}' must return synchronously (non-thenable).`)}return i}}}class N{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,o){console.error(`${t} ${e}`),o instanceof Error?console.error(o.stack??o.message):void 0!==o&&console.error(o)}}}const E=Object.freeze({log(){},error(){}});return class{constructor(){let e="notConfigured";const t=[],o=[],r=[],n=new Map;let i=!1,s=!1,a=new p;const l=new d;let c,f,u,m=E;const x=new h,b=new y,C=function(e){return`${e.platform}::${e.moduleName}`},_=function(e){const t=null===e.exportName?"":e.exportName,o=null===e.life?"":e.life,r=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,o,r].join("::")},v=function(e){if(null==e)return e;const t=typeof e;return"object"!==t&&"function"!==t||"[object Module]"===Object.prototype.toString.call(e)||Object.isFrozen(e)||Object.freeze(e),e},I=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},j=function(e){s&&m.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){I(),j("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){I(),j("addPostprocess()."),o.push(e)},this.setParser=function(e){I(),a=e,"function"==typeof a.setLogger&&a.setLogger(s?m:null),j("setParser().")},this.addNamespaceRoot=function(e,t,o){I(),j(`addNamespaceRoot('${e}').`),r.push({prefix:e,target:t,defaultExt:o})},this.enableTestMode=function(){I(),j("enableTestMode()."),i=!0},this.enableLogging=function(){I(),s||(s=!0,m=new N,"function"==typeof a.setLogger&&a.setLogger(m),m.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(I(),j(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const o=a.parse(e);n.set(_(o),t)},this.get=async function(s){if("failed"===e)throw m.error(`Container.get: rejected in failed state cdc='${s}'.`),new Error("Container is in failed state.");let p="start";try{m.log(`Container.get: cdc='${s}'.`),function(){if("notConfigured"!==e)return;m.log("Container.transition: notConfigured -> operational."),e="operational";const t=l.create({namespaces:r},{immutable:!0});"function"==typeof a.setLogger&&a.setLogger(m),c=new g({config:t,logger:m}),f=new w({parser:a,resolver:c,logger:m}),u=new $(m)}(),m.log(`Container.state: '${e}'.`),p="parse",m.log("Container.pipeline: parse:entry.");const d=a.parse(s);m.log(`Container.pipeline: parse:exit '${d.platform}::${d.moduleName}'.`),p="preprocess",m.log("Container.pipeline: preprocess:entry.");const h=function(e){let o=e;for(const e of t)o=e(o);return o}(d);if(m.log(`Container.pipeline: preprocess:exit '${h.platform}::${h.moduleName}'.`),!0===i){p="mock",m.log("Container.pipeline: mock-lookup:entry.");const e=_(h);if(n.has(e)){m.log(`Container.pipeline: mock-lookup:hit '${e}'.`),p="freeze",m.log("Container.pipeline: freeze:entry.");const t=v(n.get(e));return m.log("Container.pipeline: freeze:exit."),m.log("Container.pipeline: return:success."),t}m.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else m.log("Container.pipeline: mock-lookup:disabled.");p="resolve",m.log("Container.pipeline: resolve:entry.");const y=await f.resolve(h);m.log(`Container.pipeline: resolve:exit nodes=${y.size}.`);const N=new Map,E=function(e){if(N.has(e))return N.get(e);if(!y.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=y.get(e);p="lifecycle",m.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=u.apply(t.depId,function(){p="instantiate",m.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},r=function(e){const t=Reflect.get(e,"__deps__");return void 0===t?{}:t}(t.namespace);for(const[t,o]of Object.entries(r)){const r=o,n=a.parse(r);e[t]=E(C(n))}const n=x.instantiate(t.depId,t.namespace,e);m.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),p="postprocess",m.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=function(e){let t=e;for(const e of o)t=e(t);return t}(n);m.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const s=b.execute(t.depId,i,t.namespace);p="freeze",m.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const l=v(s);return m.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),l});return m.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),N.set(e,r),r},I=E(C(h));return m.log("Container.pipeline: return:success."),I}catch(t){throw m.error(`Container.pipeline: failed at stage='${p}'.`,t),m.log("Container.transition: operational -> failed."),e="failed",t}}}}});
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).TeqFw_Di_Container=t()}(this,function(){"use strict";var e=Object.freeze({AS_IS:"A",FACTORY:"F"});var t=Object.freeze({SINGLETON:"S",TRANSIENT:"T"});var o=Object.freeze({TEQ:"teq",NODE:"node",NPM:"npm"});const r=o.TEQ,n=e.AS_IS,i=new Set(Object.values(o)),s=new Set(Object.values(e)),a=new Set(Object.values(t));let l=class{moduleName;platform;exportName;composition;life;wrappers;origin},c=class{create(e){const t=e&&"object"==typeof e?e:{},o=new l;o.moduleName="string"==typeof t.moduleName?t.moduleName:"";const c="string"==typeof t.platform?t.platform:void 0;o.platform=c&&i.has(c)?c:r;let p=null;null===t.exportName?p=null:"string"==typeof t.exportName&&(p=t.exportName),o.exportName=p;const f="string"==typeof t.composition?t.composition:void 0;o.composition=f&&s.has(f)?f:n;const u="string"==typeof t.life?t.life:void 0;return o.life=u&&a.has(u)?u:null,o.wrappers=Array.isArray(t.wrappers)?t.wrappers.filter(e=>"string"==typeof e):[],o.origin="string"==typeof t.origin?t.origin:"",Object.freeze(o.wrappers),Object.freeze(o)}};class p{constructor(){const r=new c;let n=null;this.parse=function(i){if(n&&n.log(`Parser.parse: input='${i}'.`),"string"!=typeof i)throw new Error("CDC must be a string.");if(0===i.length)throw new Error("CDC must be non-empty.");if(!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(i))throw new Error("CDC must satisfy AsciiCdcIdentifier.");const s=i;let a=i,l=o.TEQ;if(a.startsWith("node_"))l=o.NODE,a=a.slice(5);else if(a.startsWith("npm_"))l=o.NPM,a=a.slice(4);else if(a.startsWith("teq_"))throw new Error("Explicit teq_ prefix is forbidden.");if(0===a.length)throw new Error("moduleName must be non-empty.");const c=a.match(/(\${1,3})(?:_([A-Za-z0-9]+(?:_[A-Za-z0-9]+)*))?$/);let p=null,f=[],u=a;if(c){const e=c[1],o=c[2];if("$"===e)p=t.SINGLETON;else{if("$$"!==e&&"$$$"!==e)throw new Error("Lifecycle marker overflow.");p=t.TRANSIENT}if(u=a.slice(0,c.index),o){f=o.split("_");for(const e of f){if(!e)throw new Error("Wrapper must be non-empty.");if(e.includes("$"))throw new Error("Wrapper must not contain $.");if(e.includes("_"))throw new Error("Wrapper must not contain _.")}}}else{if(a.includes("$"))throw new Error("Invalid lifecycle marker.");if(a.match(/(?:^|[^_])_([a-z][A-Za-z0-9]*)$/))throw new Error("Wrapper without lifecycle is forbidden.")}if(u.includes("$$$$"))throw new Error("Lifecycle marker overflow.");const d=u.indexOf("__"),m=u.lastIndexOf("__");if(-1!==d&&d!==m)throw new Error("Export delimiter must appear at most once.");if(u.startsWith("__")||u.endsWith("__"))throw new Error("Malformed export segment.");let g=u,w=null;if(-1!==d){if(g=u.slice(0,d),w=u.slice(d+2),!w)throw new Error("Export must be non-empty.");if(w.includes("_"))throw new Error("Export must not contain _.");if(w.includes("$"))throw new Error("Export must not contain $.")}if(!g)throw new Error("moduleName must be non-empty.");if(g.startsWith("_")||g.startsWith("$"))throw new Error("moduleName must not start with _ or $.");if(g.includes("__"))throw new Error("moduleName must not contain __.");if(g.includes("$"))throw new Error("moduleName must not contain $.");let h=e.AS_IS;null!==w?h=e.FACTORY:p===t.SINGLETON?(w="default",h=e.FACTORY):p===t.TRANSIENT&&(h=e.FACTORY,null===w&&(w="default"));const $=r.create({moduleName:g,platform:l,exportName:w,composition:h,life:p,wrappers:f,origin:s});return n&&n.log(`Parser.parse: produced='${$.platform}::${$.moduleName}'.`),$},this.setLogger=function(e){n=e}}}let f=class{prefix;target;defaultExt},u=class{create(e){const t=e&&"object"==typeof e?e:{},o=new f;return o.prefix="string"==typeof t.prefix?t.prefix:void 0,o.target="string"==typeof t.target?t.target:void 0,o.defaultExt="string"==typeof t.defaultExt?t.defaultExt:void 0,Object.freeze(o)}};class d{namespaces;nodeModulesRoot}class m{constructor(){const e=new u;this.create=function(t){const o=t&&"object"==typeof t?t:{},r=new d,n=Array.isArray(o.namespaces)?o.namespaces:[];return r.namespaces=n.map(t=>e.create(t)),r.nodeModulesRoot="string"==typeof o.nodeModulesRoot?o.nodeModulesRoot:void 0,Object.freeze(r.namespaces),Object.freeze(r)}}}class g{constructor({config:e,importFn:t=e=>import(e),logger:o=null}){const r=new Map,n=e;let i;const s=t,a=o,l=function(e,t){if("node"===e){const e=`node:${t}`;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("npm"===e){const e=t;return a&&a.log(`Resolver.specifier: module='${t}' -> '${e}'.`),e}if("teq"!==e)throw new Error(`Unsupported platform: ${e}`);const o=function(e){let t=null,o=-1;const r=i.namespaces;for(const n of r){const r=e.startsWith(n.prefix);a&&a.log(`Resolver.namespace: prefix='${n.prefix}' match=${String(r)} module='${e}'.`),r&&n.prefix.length>o&&(t=n,o=n.prefix.length)}if(!t)throw new Error(`Namespace rule is not found for '${e}'.`);return t}(t),r=t.slice(o.prefix.length).split("_").join("/"),n=(s=r,(l=o.defaultExt)?s.endsWith(l)?s:`${s}${l}`:s);var s,l;const c=function(e,t){return e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}(o.target,n);return a&&a.log(`Resolver.specifier: module='${t}' -> '${c}'.`),c};this.resolve=async function(e){var t;await Promise.resolve(),i||(i={nodeModulesRoot:(t=n).nodeModulesRoot,namespaces:t.namespaces.map(e=>({prefix:e.prefix,target:e.target,defaultExt:e.defaultExt}))});const o=e.platform,c=e.moduleName,p=`${o}::${c}`;if(r.has(p))return a&&a.log(`Resolver.cache: hit key='${p}'.`),r.get(p);a&&a.log(`Resolver.cache: miss key='${p}'.`);const f=(async()=>{const e=l(o,c);return a&&a.log(`Resolver.import: '${e}'.`),s(e)})();r.set(p,f);try{return await f}catch(e){throw r.delete(p),a&&a.error(`Resolver.cache: evict key='${p}' after failure.`,e),e}}}}class w{constructor({parser:e,resolver:t,logger:o=null}){const r=o,n=async function(o,i,s,a){const l=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(s.has(l)){const e=[...a,l].join(" -> ");throw new Error(`Cyclic dependency detected: ${e}`)}const c=function(e){return`${e.platform}::${e.moduleName}`}(o);if(!i.has(c)){s.add(l),a.push(l);try{const l=await t.resolve(o);r&&r.log(`GraphResolver.walk: resolved '${c}'.`),i.set(c,{depId:o,namespace:l});const p=Reflect.get(l,"__deps__");if(void 0===p)return;const f=p;for(const[,t]of Object.entries(f)){const o=t,l=e.parse(o);r&&r.log(`GraphResolver.walk: edge '${c}' -> '${l.platform}::${l.moduleName}'.`),await n(l,i,s,a)}}finally{a.pop(),s.delete(l)}}};this.resolve=async function(e){const t=new Map,o=new Set;return await n(e,t,o,[]),t}}}class h{constructor(){this.instantiate=function(t,o,r){const n=function(e,t){if(null===e.exportName)return t;if(!(e.exportName in t))throw new Error(`Export '${e.exportName}' is not found in module namespace.`);return t[e.exportName]}(t,o);if(t.composition===e.AS_IS)return n;if(t.composition===e.FACTORY){if("function"!=typeof n)throw new Error("Factory composition requires a callable export.");const e=n;let t;if(function(e){try{return Reflect.construct(String,[],e),!0}catch{return!1}}(e)){t=new e(r)}else{t=e(r)}if(function(e){if(null==e)return!1;const t=typeof e;return("object"===t||"function"===t)&&"function"==typeof e.then}(t))throw new Error("Factory composition must return synchronously (non-thenable).");return t}throw new Error(`Unsupported composition mode: ${String(t.composition)}.`)}}}class ${constructor(o=null){const r=new Map,n=o;this.apply=function(o,i){if(o.composition!==e.FACTORY)return n&&n.log(`Lifecycle.apply: composition='${o.composition}' cache=skip.`),i();if(o.life===t.TRANSIENT)return n&&n.log("Lifecycle.apply: transient cache=skip."),i();if(o.life===t.SINGLETON){const e=function(e){const t=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,null===e.exportName?"":e.exportName,e.composition,null===e.life?"":e.life,t].join("::")}(o);if(r.has(e))return n&&n.log(`Lifecycle.cache: hit key='${e}'.`),r.get(e);n&&n.log(`Lifecycle.cache: miss key='${e}', create.`);const t=i();return r.set(e,t),n&&n.log(`Lifecycle.cache: stored key='${e}'.`),t}return n&&n.log("Lifecycle.apply: no lifecycle marker cache=skip."),i()}}}class y{constructor(){const e=function(e){if(null==e)return!1;const t=typeof e;if("object"!==t&&"function"!==t)return!1;return"function"==typeof e.then},t=function(e){return"function"==typeof e};this.execute=function(o,r,n){let i=r;const s=o.wrappers;for(const o of s){if(!(o in n))throw new Error(`Wrapper '${o}' is not found in module namespace.`);const r=n[o];if(!t(r))throw new Error(`Wrapper '${o}' must be callable.`);if(i=r(i),e(i))throw new Error(`Wrapper '${o}' must return synchronously (non-thenable).`)}return i}}}class N{constructor(e="teqfw/di"){const t=`[${e}]`;this.log=function(e){console.debug(`${t} ${e}`)},this.error=function(e,o){console.error(`${t} ${e}`),o instanceof Error?console.error(o.stack??o.message):void 0!==o&&console.error(o)}}}const E=Object.freeze({log(){},error(){}});return class{constructor(){let e="notConfigured";const t=[],o=[],r=[],n=new Map;let i=!1,s=!1,a=new p;const l=new m;let c,f,u,d=E;const x=new h,C=new y,b=function(e){return`${e.platform}::${e.moduleName}`},v=function(e){const t=null===e.exportName?"":e.exportName,o=null===e.life?"":e.life,r=Array.isArray(e.wrappers)?e.wrappers.join("|"):"";return[e.platform,e.moduleName,t,e.composition,o,r].join("::")},_=function(e){if(null==e)return e;const t=typeof e;return"object"!==t&&"function"!==t||"[object Module]"===Object.prototype.toString.call(e)||Object.isFrozen(e)||Object.freeze(e),e},I=function(){if("notConfigured"!==e)throw new Error("Container configuration is locked.")},j=function(e){s&&d.log(`Container.builder: ${e}`)};this.addPreprocess=function(e){I(),j("addPreprocess()."),t.push(e)},this.addPostprocess=function(e){I(),j("addPostprocess()."),o.push(e)},this.setParser=function(e){I(),a=e,"function"==typeof a.setLogger&&a.setLogger(s?d:null),j("setParser().")},this.addNamespaceRoot=function(e,t,o){I(),j(`addNamespaceRoot('${e}').`),r.push({prefix:e,target:t,defaultExt:o})},this.enableTestMode=function(){I(),j("enableTestMode()."),i=!0},this.enableLogging=function(){I(),s||(s=!0,d=new N,"function"==typeof a.setLogger&&a.setLogger(d),d.log("Container.builder: enableLogging()."))},this.register=function(e,t){if(I(),j(`register('${e}').`),!0!==i)throw new Error("Container test mode is disabled.");const o=a.parse(e);n.set(v(o),t)},this.get=async function(s){if("failed"===e)throw d.error(`Container.get: rejected in failed state cdc='${s}'.`),new Error("Container is in failed state.");let p="start";try{d.log(`Container.get: cdc='${s}'.`),function(){if("notConfigured"!==e)return;d.log("Container.transition: notConfigured -> operational."),e="operational";const t=l.create({namespaces:r});"function"==typeof a.setLogger&&a.setLogger(d),c=new g({config:t,logger:d}),f=new w({parser:a,resolver:c,logger:d}),u=new $(d)}(),d.log(`Container.state: '${e}'.`),p="parse",d.log("Container.pipeline: parse:entry.");const m=a.parse(s);d.log(`Container.pipeline: parse:exit '${m.platform}::${m.moduleName}'.`),p="preprocess",d.log("Container.pipeline: preprocess:entry.");const h=function(e){let o=e;for(const e of t)o=e(o);return o}(m);if(d.log(`Container.pipeline: preprocess:exit '${h.platform}::${h.moduleName}'.`),!0===i){p="mock",d.log("Container.pipeline: mock-lookup:entry.");const e=v(h);if(n.has(e)){d.log(`Container.pipeline: mock-lookup:hit '${e}'.`),p="freeze",d.log("Container.pipeline: freeze:entry.");const t=_(n.get(e));return d.log("Container.pipeline: freeze:exit."),d.log("Container.pipeline: return:success."),t}d.log(`Container.pipeline: mock-lookup:miss '${e}'.`)}else d.log("Container.pipeline: mock-lookup:disabled.");p="resolve",d.log("Container.pipeline: resolve:entry.");const y=await f.resolve(h);d.log(`Container.pipeline: resolve:exit nodes=${y.size}.`);const N=new Map,E=function(e){if(N.has(e))return N.get(e);if(!y.has(e))throw new Error(`Resolved graph node is missing for '${e}'.`);const t=y.get(e);p="lifecycle",d.log(`Container.pipeline: lifecycle:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const r=u.apply(t.depId,function(){p="instantiate",d.log(`Container.pipeline: instantiate:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const e={},r=function(e){const t=Reflect.get(e,"__deps__");return void 0===t?{}:t}(t.namespace);for(const[t,o]of Object.entries(r)){const r=o,n=a.parse(r);e[t]=E(b(n))}const n=x.instantiate(t.depId,t.namespace,e);d.log(`Container.pipeline: instantiate:exit '${t.depId.platform}::${t.depId.moduleName}'.`),p="postprocess",d.log(`Container.pipeline: postprocess:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const i=function(e){let t=e;for(const e of o)t=e(t);return t}(n);d.log(`Container.pipeline: postprocess:exit '${t.depId.platform}::${t.depId.moduleName}'.`);const s=C.execute(t.depId,i,t.namespace);p="freeze",d.log(`Container.pipeline: freeze:entry '${t.depId.platform}::${t.depId.moduleName}'.`);const l=_(s);return d.log(`Container.pipeline: freeze:exit '${t.depId.platform}::${t.depId.moduleName}'.`),l});return d.log(`Container.pipeline: lifecycle:exit '${t.depId.platform}::${t.depId.moduleName}'.`),N.set(e,r),r},I=E(b(h));return d.log("Container.pipeline: return:success."),I}catch(t){throw d.error(`Container.pipeline: failed at stage='${p}'.`,t),d.log("Container.transition: operational -> failed."),e="failed",t}}}}});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teqfw/di",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "Dependency Injection container for ES6 modules that works in both browser and Node.js apps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dependency injection",
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
"dist/",
|
|
26
26
|
"src/",
|
|
27
27
|
"CHANGELOG.md",
|
|
28
|
-
"jsconfig.json",
|
|
29
28
|
"LICENSE",
|
|
30
29
|
"README.md",
|
|
31
30
|
"types.d.ts"
|
package/src/AGENTS.md
CHANGED
|
@@ -21,9 +21,9 @@ The following documents are mandatory:
|
|
|
21
21
|
- `ctx/docs/code/depid.md`
|
|
22
22
|
- `ctx/docs/code/testing.md`
|
|
23
23
|
- `ctx/docs/code/jsdoc-spec.md`
|
|
24
|
-
- `ctx/docs/code/
|
|
25
|
-
- `ctx/docs/code/
|
|
26
|
-
- `ctx/docs/code/
|
|
24
|
+
- `ctx/docs/code/convention/es6-modules.md`
|
|
25
|
+
- `ctx/docs/code/convention/teqfw/dto.md`
|
|
26
|
+
- `ctx/docs/code/convention/teqfw/enum.md`
|
|
27
27
|
|
|
28
28
|
Agent MUST read and follow them before generating or modifying code.
|
|
29
29
|
|
|
@@ -72,8 +72,8 @@ Absence of required JSDoc constitutes non-compliance.
|
|
|
72
72
|
|
|
73
73
|
All DTO and Enum implementations MUST strictly follow:
|
|
74
74
|
|
|
75
|
-
- `ctx/docs/code/
|
|
76
|
-
- `ctx/docs/code/
|
|
75
|
+
- `ctx/docs/code/convention/teqfw/dto.md`
|
|
76
|
+
- `ctx/docs/code/convention/teqfw/enum.md`
|
|
77
77
|
|
|
78
78
|
In particular:
|
|
79
79
|
|