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.
- package/LICENSE +21 -0
- package/README.md +280 -0
- package/dist/acquisition-context.d.ts +42 -0
- package/dist/acquisition-context.js +19 -0
- package/dist/acquisition-family.d.ts +32 -0
- package/dist/acquisition-family.js +135 -0
- package/dist/acquisition-mode.d.ts +34 -0
- package/dist/acquisition-mode.js +35 -0
- package/dist/acquisition.d.ts +44 -0
- package/dist/acquisition.js +395 -0
- package/dist/alias-types.d.ts +22 -0
- package/dist/alias-types.js +2 -0
- package/dist/aliases.d.ts +4 -0
- package/dist/aliases.js +24 -0
- package/dist/composition.d.ts +41 -0
- package/dist/composition.js +45 -0
- package/dist/contribution-types.d.ts +57 -0
- package/dist/contribution-types.js +2 -0
- package/dist/contributions.d.ts +3 -0
- package/dist/contributions.js +11 -0
- package/dist/dependency-references.d.ts +52 -0
- package/dist/dependency-references.js +53 -0
- package/dist/di-bag.d.ts +247 -0
- package/dist/di-bag.js +211 -0
- package/dist/errors.d.ts +66 -0
- package/dist/errors.js +89 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +10 -0
- package/dist/inspection.d.ts +36 -0
- package/dist/inspection.js +2 -0
- package/dist/lifetime-types.d.ts +214 -0
- package/dist/lifetime-types.js +2 -0
- package/dist/lifetime.d.ts +42 -0
- package/dist/lifetime.js +31 -0
- package/dist/module-types.d.ts +182 -0
- package/dist/module-types.js +2 -0
- package/dist/module.d.ts +45 -0
- package/dist/module.js +118 -0
- package/dist/node.d.ts +4 -0
- package/dist/node.js +22 -0
- package/dist/observers.d.ts +71 -0
- package/dist/observers.js +58 -0
- package/dist/persistent-map.d.ts +29 -0
- package/dist/persistent-map.js +146 -0
- package/dist/persistent-sequence.d.ts +9 -0
- package/dist/persistent-sequence.js +20 -0
- package/dist/plugins.d.ts +32 -0
- package/dist/plugins.js +82 -0
- package/dist/provider-execution.d.ts +59 -0
- package/dist/provider-execution.js +271 -0
- package/dist/provider-operations.d.ts +59 -0
- package/dist/provider-operations.js +38 -0
- package/dist/provider.d.ts +199 -0
- package/dist/provider.js +158 -0
- package/dist/registration.d.ts +32 -0
- package/dist/registration.js +45 -0
- package/dist/replacement-types.d.ts +30 -0
- package/dist/replacement-types.js +2 -0
- package/dist/runtime.d.ts +90 -0
- package/dist/runtime.js +428 -0
- package/dist/scope-selection.d.ts +6 -0
- package/dist/scope-selection.js +62 -0
- package/dist/scope-types.d.ts +58 -0
- package/dist/scope-types.js +2 -0
- package/dist/startup.d.ts +14 -0
- package/dist/startup.js +141 -0
- package/dist/token-types.d.ts +67 -0
- package/dist/token-types.js +2 -0
- package/dist/tokens.d.ts +47 -0
- package/dist/tokens.js +69 -0
- package/dist/types.d.ts +174 -0
- package/dist/types.js +2 -0
- package/package.json +64 -0
package/dist/startup.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startRuntime = startRuntime;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
const runtime_1 = require("./runtime");
|
|
6
|
+
const tokens_1 = require("./tokens");
|
|
7
|
+
const errors_2 = require("./errors");
|
|
8
|
+
function snapshotOptions(options) {
|
|
9
|
+
if (options === undefined)
|
|
10
|
+
return {};
|
|
11
|
+
if (typeof options !== 'object' || options === null || Array.isArray(options))
|
|
12
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_STARTUP', 'invalid buildAndStart options', { operation: 'buildAndStart' });
|
|
13
|
+
const supported = ['signal', 'timeoutMs', 'startupOrder'];
|
|
14
|
+
if (Reflect.ownKeys(options).some(key => typeof key !== 'string' || !supported.includes(key)) ||
|
|
15
|
+
supported.some(key => key in options && !Object.hasOwn(options, key)))
|
|
16
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_STARTUP', 'invalid buildAndStart options', { operation: 'buildAndStart' });
|
|
17
|
+
const selected = Object.create(null);
|
|
18
|
+
for (const key of supported)
|
|
19
|
+
if (Object.hasOwn(options, key))
|
|
20
|
+
selected[key] = Reflect.get(options, key);
|
|
21
|
+
if (Object.hasOwn(selected, 'timeoutMs') && (typeof selected.timeoutMs !== 'number' || !Number.isFinite(selected.timeoutMs) || selected.timeoutMs <= 0)) {
|
|
22
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_STARTUP', 'buildAndStart timeoutMs must be finite and positive', { operation: 'buildAndStart' });
|
|
23
|
+
}
|
|
24
|
+
if (Object.hasOwn(selected, 'startupOrder') && selected.startupOrder !== 'parallel' && selected.startupOrder !== 'sequential' &&
|
|
25
|
+
!(typeof selected.startupOrder === 'number' && Number.isSafeInteger(selected.startupOrder) && selected.startupOrder > 0))
|
|
26
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_STARTUP', 'buildAndStart startupOrder must be parallel, sequential, or a positive safe integer', { operation: 'buildAndStart', option: 'startupOrder' });
|
|
27
|
+
if (Object.hasOwn(selected, 'signal')) {
|
|
28
|
+
try {
|
|
29
|
+
Object.getOwnPropertyDescriptor(AbortSignal.prototype, 'aborted').get.call(selected.signal);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_STARTUP', 'buildAndStart signal must be an AbortSignal', { operation: 'buildAndStart' });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return selected;
|
|
36
|
+
}
|
|
37
|
+
/** One startup transaction; never assimilate an exposed service to establish readiness. */
|
|
38
|
+
function startRuntime(graph, context, keys, options) {
|
|
39
|
+
if (!Array.isArray(keys))
|
|
40
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_STARTUP', 'buildAndStart requires selected keys', { operation: 'buildAndStart' });
|
|
41
|
+
const selected = [];
|
|
42
|
+
const length = keys.length;
|
|
43
|
+
for (let index = 0; index < length; index++) {
|
|
44
|
+
const value = keys[index];
|
|
45
|
+
const key = typeof value === 'string' ? value : (0, tokens_1.readTokenKey)(value);
|
|
46
|
+
if (!graph.hasPublic(key))
|
|
47
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_STARTUP', `buildAndStart accepts existing names or typed tokens only: ${String(key)}`, { operation: 'buildAndStart' });
|
|
48
|
+
selected.push(key);
|
|
49
|
+
}
|
|
50
|
+
const { signal, timeoutMs, startupOrder = 'parallel' } = snapshotOptions(options);
|
|
51
|
+
const runtime = new runtime_1.BagRuntime(graph, context);
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
let settled = false;
|
|
54
|
+
let timer;
|
|
55
|
+
const began = performance.now();
|
|
56
|
+
const release = () => {
|
|
57
|
+
if (timer !== undefined)
|
|
58
|
+
clearTimeout(timer);
|
|
59
|
+
signal?.removeEventListener('abort', aborted);
|
|
60
|
+
};
|
|
61
|
+
const cancel = (reason, cause) => {
|
|
62
|
+
if (settled)
|
|
63
|
+
return;
|
|
64
|
+
settled = true;
|
|
65
|
+
release();
|
|
66
|
+
reject(new errors_2.DiBagStartupCancelledError(reason, cause, runtime.close(cause)));
|
|
67
|
+
};
|
|
68
|
+
const aborted = () => { if (signal?.aborted)
|
|
69
|
+
cancel('aborted', signal.reason); };
|
|
70
|
+
const checkCancellation = () => {
|
|
71
|
+
aborted();
|
|
72
|
+
if (!settled && timeoutMs !== undefined && performance.now() - began >= timeoutMs) {
|
|
73
|
+
cancel('timeout', (0, errors_1.diagnostic)(new DOMException('Bag startup timed out', 'TimeoutError'), 'DI_BAG_STARTUP_TIMEOUT', { operation: 'buildAndStart', timeoutMs }));
|
|
74
|
+
}
|
|
75
|
+
return settled;
|
|
76
|
+
};
|
|
77
|
+
const schedule = () => {
|
|
78
|
+
if (checkCancellation() || timeoutMs === undefined)
|
|
79
|
+
return;
|
|
80
|
+
// Long deadlines must not wrap into an immediate timer on Node/Bun.
|
|
81
|
+
timer = setTimeout(schedule, Math.min(2 ** 31 - 1, Math.max(1, timeoutMs - (performance.now() - began))));
|
|
82
|
+
};
|
|
83
|
+
signal?.addEventListener('abort', aborted, { once: true });
|
|
84
|
+
if (checkCancellation())
|
|
85
|
+
return;
|
|
86
|
+
if (timeoutMs !== undefined)
|
|
87
|
+
schedule();
|
|
88
|
+
const runBounded = (limit) => {
|
|
89
|
+
let next = 0;
|
|
90
|
+
let failed = false;
|
|
91
|
+
const worker = async () => {
|
|
92
|
+
while (next < selected.length) {
|
|
93
|
+
if (failed || checkCancellation())
|
|
94
|
+
return;
|
|
95
|
+
const key = selected[next++];
|
|
96
|
+
try {
|
|
97
|
+
await runtime.acquire(key);
|
|
98
|
+
}
|
|
99
|
+
catch (cause) {
|
|
100
|
+
// Stop other workers before rollback begins, even if cleanup waits.
|
|
101
|
+
failed = true;
|
|
102
|
+
throw cause;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
return Promise.all(Array.from({ length: Math.min(limit, selected.length) }, worker));
|
|
107
|
+
};
|
|
108
|
+
const runParallel = () => {
|
|
109
|
+
const pending = [];
|
|
110
|
+
for (const key of selected) {
|
|
111
|
+
if (checkCancellation())
|
|
112
|
+
break;
|
|
113
|
+
pending.push(runtime.acquire(key));
|
|
114
|
+
}
|
|
115
|
+
return Promise.all(pending);
|
|
116
|
+
};
|
|
117
|
+
const work = startupOrder === 'parallel' ? runParallel() : runBounded(startupOrder === 'sequential' ? 1 : startupOrder);
|
|
118
|
+
void work.then(() => {
|
|
119
|
+
if (checkCancellation())
|
|
120
|
+
return;
|
|
121
|
+
settled = true;
|
|
122
|
+
release();
|
|
123
|
+
resolve(runtime);
|
|
124
|
+
}, async (cause) => {
|
|
125
|
+
if (checkCancellation())
|
|
126
|
+
return;
|
|
127
|
+
let cleanupError;
|
|
128
|
+
try {
|
|
129
|
+
await runtime.close(cause);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
cleanupError = error;
|
|
133
|
+
}
|
|
134
|
+
if (checkCancellation())
|
|
135
|
+
return;
|
|
136
|
+
settled = true;
|
|
137
|
+
release();
|
|
138
|
+
reject(new errors_2.DiBagStartupError(cause, cleanupError instanceof errors_2.DiBagCleanupError ? cleanupError.failures : [], cleanupError));
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { TokenBase, TokenKey, TokenService } from './tokens';
|
|
2
|
+
import type { DependencyReference, DependencyValue, DependencyToken, DependencyKind, ValidDependency } from './dependency-references';
|
|
3
|
+
import type { Unsatisfied } from './types';
|
|
4
|
+
import type { Registration, Registrations } from './registration';
|
|
5
|
+
import type { BoundToken, Provider, ProviderFactory, ProviderGraphContract, ProviderRegistrationMetadata, ProviderAcquisitionMetadata, ProviderAcquiredValue, ProviderOutput, ProviderRequiredTokens, ProviderOptionalTokens } from './provider';
|
|
6
|
+
/** A provider's retained required, bound, and optional typed-token contracts. */
|
|
7
|
+
export type TokenDependencyContract<T extends readonly TokenBase[] = readonly [], B extends TokenBase = never, O extends readonly TokenBase[] = readonly []> = {
|
|
8
|
+
readonly kind: 'tokens';
|
|
9
|
+
readonly required: T;
|
|
10
|
+
readonly bound: B;
|
|
11
|
+
readonly optional: O;
|
|
12
|
+
};
|
|
13
|
+
export type OpaqueGraph = {
|
|
14
|
+
readonly kind: 'opaque';
|
|
15
|
+
};
|
|
16
|
+
export type GraphContract = TokenDependencyContract<readonly TokenBase[], TokenBase, readonly TokenBase[]> | OpaqueGraph;
|
|
17
|
+
type IsUnion<T, Whole = T> = T extends Whole ? [Whole] extends [T] ? false : true : never;
|
|
18
|
+
type SingletonSymbol<K> = [K] extends [never] ? false : [K] extends [symbol] ? symbol extends K ? false : true extends IsUnion<K> ? false : true : false;
|
|
19
|
+
export type TokenKeyAdmission<K> = SingletonSymbol<K> extends true ? unknown : Unsatisfied<'token requires a singleton unique-symbol key', {}>;
|
|
20
|
+
export type ValidToken<T> = [T] extends [never] ? false : true extends IsUnion<T> ? false : T extends TokenBase ? SingletonSymbol<TokenKey<T>> : false;
|
|
21
|
+
type InvalidElements<T extends readonly unknown[]> = {
|
|
22
|
+
[I in keyof T]-?: ValidToken<T[I]> extends true ? never : I;
|
|
23
|
+
}[number];
|
|
24
|
+
export type TokenTupleAdmission<T extends readonly unknown[]> = true extends IsUnion<T> ? InvalidTuple : number extends T['length'] ? InvalidTuple : T extends Required<T> ? [InvalidElements<T>] extends [never] ? unknown : InvalidTuple : InvalidTuple;
|
|
25
|
+
type InvalidTuple = Unsatisfied<'tokens require a finite tuple of individually known token handles', {}>;
|
|
26
|
+
type InvalidDependencies<T extends readonly unknown[]> = {
|
|
27
|
+
[I in keyof T]-?: true extends IsUnion<T[I]> ? I : ValidDependency<T[I]> extends true ? never : I;
|
|
28
|
+
}[number];
|
|
29
|
+
export type DependencyTupleAdmission<T extends readonly unknown[]> = true extends IsUnion<T> ? InvalidTuple : number extends T['length'] ? InvalidTuple : T extends Required<T> ? [InvalidDependencies<T>] extends [never] ? unknown : InvalidTuple : InvalidTuple;
|
|
30
|
+
export type TokenArguments<T extends readonly DependencyReference[]> = {
|
|
31
|
+
-readonly [I in keyof T]: DependencyValue<T[I]>;
|
|
32
|
+
};
|
|
33
|
+
type ReferenceTokens<T extends readonly DependencyReference[], Kind extends 'required' | 'optional' | 'all', SelectedRegistrations extends readonly TokenBase[] = readonly []> = T extends readonly [infer H extends DependencyReference, ...infer Rest extends readonly DependencyReference[]] ? (DependencyKind<H> extends 'lazy' ? 'required' : DependencyKind<H>) extends Kind ? ReferenceTokens<Rest, Kind, readonly [...SelectedRegistrations, DependencyToken<H>]> : ReferenceTokens<Rest, Kind, SelectedRegistrations> : SelectedRegistrations;
|
|
34
|
+
export type ReferenceGraph<T extends readonly DependencyReference[]> = T extends readonly TokenBase[] ? TokenDependencyContract<T> : TokenDependencyContract<ReferenceTokens<T, 'required'>, never, ReferenceTokens<T, 'optional'>> & (ReferenceTokens<T, 'all'> extends readonly [] ? unknown : {
|
|
35
|
+
readonly all: ReferenceTokens<T, 'all'>;
|
|
36
|
+
});
|
|
37
|
+
export type ReboundGraph<G extends GraphContract, T extends TokenBase> = G extends infer U & {} ? U extends TokenDependencyContract<readonly TokenBase[], TokenBase, readonly TokenBase[]> ? {
|
|
38
|
+
[K in keyof U]: K extends 'bound' ? T : U[K];
|
|
39
|
+
} : U extends GraphContract ? U : never : never;
|
|
40
|
+
/** A registration rebound to an invariant typed-token service contract. */
|
|
41
|
+
export type TokenBinding<T extends TokenBase, R extends Registration> = Provider<ProviderFactory<R>, ProviderRegistrationMetadata<R> & object, ProviderAcquisitionMetadata<R>, ReboundGraph<ProviderGraphContract<R>, T>, ProviderAcquiredValue<R>>;
|
|
42
|
+
export type BindingOutput<T extends TokenBase, R extends Registration> = [ProviderOutput<R>] extends [TokenService<T>] ? unknown : Unsatisfied<'token binding output is not assignable to its service', {
|
|
43
|
+
token: TokenKey<T>;
|
|
44
|
+
expected: TokenService<T>;
|
|
45
|
+
provided: ProviderOutput<R>;
|
|
46
|
+
}>;
|
|
47
|
+
/** Convert a string selection to itself or a typed token to its symbol key. */
|
|
48
|
+
export type SelectionKey<T> = T extends string ? T : TokenKey<T>;
|
|
49
|
+
type SameToken<A, B> = [A] extends [B] ? [B] extends [A] ? true : false : false;
|
|
50
|
+
export type WrongToken<T, R extends Registrations> = T extends unknown ? ValidToken<T> extends true ? TokenKey<T> extends keyof R ? SameToken<T, BoundToken<R[TokenKey<T>]>> extends true ? never : TokenKey<T> : never : 'opaque token contract' : never;
|
|
51
|
+
export type MissingToken<T, R extends Registrations> = T extends unknown ? ValidToken<T> extends true ? Exclude<TokenKey<T>, keyof R> : 'opaque token contract' : never;
|
|
52
|
+
/** Admit a genuine token only when it exactly matches an existing binding contract. */
|
|
53
|
+
export type TokenMember<R extends Registrations, T> = ValidToken<T> extends true ? [WrongToken<T, R> | MissingToken<T, R>] extends [never] ? unknown : Unsatisfied<'token must match an existing binding contract', {}> : Unsatisfied<'token must be an individually known genuine handle', {}>;
|
|
54
|
+
export type InvalidGraphs<R extends Registrations> = {
|
|
55
|
+
[K in keyof R]: [ProviderGraphContract<R[K]>] extends [TokenDependencyContract<readonly TokenBase[], TokenBase, readonly TokenBase[]>] ? WrongToken<ProviderRequiredTokens<R[K]> | ProviderOptionalTokens<R[K]>, R> | InvalidBound<BoundToken<R[K]>> : K;
|
|
56
|
+
}[keyof R];
|
|
57
|
+
type InvalidBound<B> = B extends unknown ? ValidToken<B> extends true ? never : 'opaque binding contract' : never;
|
|
58
|
+
export type MissingTokens<R extends Registrations> = {
|
|
59
|
+
[K in keyof R]: MissingToken<ProviderRequiredTokens<R[K]>, R>;
|
|
60
|
+
}[keyof R];
|
|
61
|
+
/** Rebind symbol-keyed override registrations to the original typed-token contracts. */
|
|
62
|
+
export type ReboundProviders<R extends Registrations, O extends Registrations> = {
|
|
63
|
+
[K in keyof O]: K extends keyof R ? K extends symbol ? TokenBinding<BoundToken<R[K]>, O[K]> : O[K] : O[K];
|
|
64
|
+
};
|
|
65
|
+
/** Preserve named overrides and rebind any symbol-keyed override providers. */
|
|
66
|
+
export type ReboundSelection<R extends Registrations, O extends Registrations> = [Extract<keyof O, symbol>] extends [never] ? O : ReboundProviders<R, O>;
|
|
67
|
+
export {};
|
package/dist/tokens.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { TokenKeyAdmission } from './token-types';
|
|
2
|
+
declare const tokenInvariant: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* The common type-only base for genuine typed-token handles.
|
|
5
|
+
* Create tokens through `DiBag.token`; fabricated structural values are not authenticated.
|
|
6
|
+
*/
|
|
7
|
+
declare class TokenBase {
|
|
8
|
+
private readonly nominal;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* An immutable typed-token handle pairing a canonical symbol with an invariant service contract.
|
|
12
|
+
* Create one with `DiBag.token(key).of<Service>()`.
|
|
13
|
+
*/
|
|
14
|
+
declare class Token<K extends symbol, S> extends TokenBase {
|
|
15
|
+
readonly key: K;
|
|
16
|
+
/** @internal */
|
|
17
|
+
readonly [tokenInvariant]: (value: [K, S]) => [K, S];
|
|
18
|
+
constructor(key: K);
|
|
19
|
+
}
|
|
20
|
+
/** Extract the canonical unique-symbol key from a typed token. */
|
|
21
|
+
export type TokenKey<T> = T extends infer U & {} ? U extends Token<infer K, infer _S> ? K : never : never;
|
|
22
|
+
/** Extract the invariant service contract declared by a typed token. */
|
|
23
|
+
export type TokenService<T> = T extends infer U & {} ? U extends Token<infer _K, infer S> ? S : never : never;
|
|
24
|
+
/**
|
|
25
|
+
* Create a typed-token factory from the caller's canonical unique symbol.
|
|
26
|
+
* Reusing the same key and service type produces compatible handles; copied or fabricated
|
|
27
|
+
* objects are rejected at runtime.
|
|
28
|
+
* @param key - An individually known unique symbol used as the runtime binding identity.
|
|
29
|
+
* @returns An object whose `of<Service>()` method creates an immutable typed token.
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const clockKey = Symbol('clock');
|
|
33
|
+
* const clock = DiBag.token(clockKey).of<{ now(): number }>();
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function token<const K extends symbol>(key: K & TokenKeyAdmission<K>, ...invalid: [K] extends [never] ? [TokenKeyAdmission<K>] : []): {
|
|
37
|
+
/**
|
|
38
|
+
* Declare the invariant service contract carried by this token handle.
|
|
39
|
+
* @typeParam S - The service type accepted by bindings and returned by resolution.
|
|
40
|
+
* @returns A genuine immutable token paired with the canonical symbol key.
|
|
41
|
+
*/
|
|
42
|
+
readonly of: <S>() => Token<K, S>;
|
|
43
|
+
};
|
|
44
|
+
/** A copied, proxied or fabricated shape cannot authenticate a token. */
|
|
45
|
+
export declare function readTokenKey(value: unknown): symbol;
|
|
46
|
+
export declare function snapshotTokens(value: unknown): readonly TokenBase[];
|
|
47
|
+
export type { Token, TokenBase };
|
package/dist/tokens.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.token = token;
|
|
4
|
+
exports.readTokenKey = readTokenKey;
|
|
5
|
+
exports.snapshotTokens = snapshotTokens;
|
|
6
|
+
const errors_1 = require("./errors");
|
|
7
|
+
/**
|
|
8
|
+
* The common type-only base for genuine typed-token handles.
|
|
9
|
+
* Create tokens through `DiBag.token`; fabricated structural values are not authenticated.
|
|
10
|
+
*/
|
|
11
|
+
class TokenBase {
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* An immutable typed-token handle pairing a canonical symbol with an invariant service contract.
|
|
15
|
+
* Create one with `DiBag.token(key).of<Service>()`.
|
|
16
|
+
*/
|
|
17
|
+
class Token extends TokenBase {
|
|
18
|
+
key;
|
|
19
|
+
constructor(key) {
|
|
20
|
+
super();
|
|
21
|
+
this.key = key;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const keys = new WeakMap();
|
|
25
|
+
/**
|
|
26
|
+
* Create a typed-token factory from the caller's canonical unique symbol.
|
|
27
|
+
* Reusing the same key and service type produces compatible handles; copied or fabricated
|
|
28
|
+
* objects are rejected at runtime.
|
|
29
|
+
* @param key - An individually known unique symbol used as the runtime binding identity.
|
|
30
|
+
* @returns An object whose `of<Service>()` method creates an immutable typed token.
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const clockKey = Symbol('clock');
|
|
34
|
+
* const clock = DiBag.token(clockKey).of<{ now(): number }>();
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function token(key,
|
|
38
|
+
// An uninhabited key is assignable to every intersection; arity rejects its
|
|
39
|
+
// explicit generic erasure without weakening ordinary key inference.
|
|
40
|
+
...invalid) {
|
|
41
|
+
if (typeof key !== 'symbol')
|
|
42
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_TOKEN', 'token key must be a symbol', { operation: 'token' });
|
|
43
|
+
return Object.freeze({ of: () => {
|
|
44
|
+
const handle = new Token(key);
|
|
45
|
+
keys.set(handle, key);
|
|
46
|
+
Object.freeze(handle);
|
|
47
|
+
return handle;
|
|
48
|
+
} });
|
|
49
|
+
}
|
|
50
|
+
/** A copied, proxied or fabricated shape cannot authenticate a token. */
|
|
51
|
+
function readTokenKey(value) {
|
|
52
|
+
if (typeof value !== 'object' || value === null)
|
|
53
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_TOKEN', 'invalid token', { expected: 'genuine typed token' });
|
|
54
|
+
const key = keys.get(value);
|
|
55
|
+
if (key === undefined)
|
|
56
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_TOKEN', 'invalid token', { expected: 'genuine typed token' });
|
|
57
|
+
return key;
|
|
58
|
+
}
|
|
59
|
+
function snapshotTokens(value) {
|
|
60
|
+
if (!Array.isArray(value))
|
|
61
|
+
throw (0, errors_1.libraryError)('DI_BAG_INVALID_TOKEN', 'tokens must be a tuple', { expected: 'finite token tuple' });
|
|
62
|
+
const selected = [];
|
|
63
|
+
const length = value.length;
|
|
64
|
+
for (let index = 0; index < length; index++)
|
|
65
|
+
selected[index] = value[index];
|
|
66
|
+
for (const handle of selected)
|
|
67
|
+
readTokenKey(handle);
|
|
68
|
+
return Object.freeze(selected);
|
|
69
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { FactoryWithDisposal, Registration, Registrations } from './registration';
|
|
2
|
+
import type { ProviderContext, ProviderNamedDependencies, ProviderOutput, ProviderGraphContract, ProviderRequiredTokens, ProviderOptionalTokens } from './provider';
|
|
3
|
+
import type { InvalidGraphs, MissingTokens, SelectionKey, TokenMember, ValidToken, TokenDependencyContract, WrongToken } from './token-types';
|
|
4
|
+
export type Needs<R extends Registration> = ProviderNamedDependencies<R>;
|
|
5
|
+
/** Map registrations to the exact service values they expose. */
|
|
6
|
+
export type ServicesOf<R extends Registrations> = {
|
|
7
|
+
[K in keyof R]: ProviderOutput<R[K]>;
|
|
8
|
+
};
|
|
9
|
+
export type Entry = {
|
|
10
|
+
key: string | symbol;
|
|
11
|
+
registration: Registration;
|
|
12
|
+
};
|
|
13
|
+
type RegistrationEntry<K extends string | symbol, V extends Registration> = {
|
|
14
|
+
key: K;
|
|
15
|
+
registration: V;
|
|
16
|
+
};
|
|
17
|
+
/** Convert a registration map to the union of entries retained by a builder. */
|
|
18
|
+
export type RegistrationEntries<R extends Registrations> = {
|
|
19
|
+
[K in keyof R & (string | symbol)]: RegistrationEntry<K, R[K]>;
|
|
20
|
+
}[keyof R & (string | symbol)];
|
|
21
|
+
/** Reconstruct a registration map from a builder's retained entry union. */
|
|
22
|
+
export type RegistrationsFromEntries<E extends Entry> = {
|
|
23
|
+
[P in E as P['key']]: P['registration'];
|
|
24
|
+
};
|
|
25
|
+
/** Replace overlapping registrations in `F` with registrations from `N`. */
|
|
26
|
+
export type OverrideRegistrations<F extends Registrations, N extends Registrations> = Omit<F, keyof N> & N;
|
|
27
|
+
declare const diBagTypeError: unique symbol;
|
|
28
|
+
export type Unsatisfied<Message extends string, Details> = {
|
|
29
|
+
readonly [diBagTypeError]: Message;
|
|
30
|
+
} & Details;
|
|
31
|
+
type IsUnion<T, Whole = T> = T extends Whole ? [Whole] extends [T] ? false : true : never;
|
|
32
|
+
type NonFiniteKeys<T> = {
|
|
33
|
+
[K in keyof T]-?: Record<never, never> extends Record<K, never> ? K : never;
|
|
34
|
+
}[keyof T];
|
|
35
|
+
type InvalidNeeds<R extends Registrations> = {
|
|
36
|
+
[K in keyof R]: true extends IsUnion<Needs<R[K]>> ? K : Needs<R[K]> extends (...args: never[]) => unknown ? K : Needs<R[K]> extends abstract new (...args: never[]) => unknown ? K : [Needs<R[K]>] extends [object] ? [NonFiniteKeys<Needs<R[K]>>] extends [never] ? [Exclude<keyof Needs<R[K]>, string>] extends [never] ? never : K : K : K;
|
|
37
|
+
}[keyof R];
|
|
38
|
+
type WrongShapes<R extends Registrations> = {
|
|
39
|
+
[K in keyof R]: Pick<ServicesOf<R>, keyof Needs<R[K]> & keyof R> extends Pick<Needs<R[K]>, keyof Needs<R[K]> & keyof R> ? never : K;
|
|
40
|
+
}[keyof R];
|
|
41
|
+
type WrongRelationships<R extends Registrations, Consumers extends keyof R> = {
|
|
42
|
+
[Consumer in Consumers]: {
|
|
43
|
+
[DependencyReference in keyof Needs<R[Consumer]> & keyof R]: ServicesOf<R>[DependencyReference] extends Required<Needs<R[Consumer]>>[DependencyReference] ? never : {
|
|
44
|
+
consumer: Consumer;
|
|
45
|
+
dependency: DependencyReference;
|
|
46
|
+
expected: Required<Needs<R[Consumer]>>[DependencyReference];
|
|
47
|
+
provided: ServicesOf<R>[DependencyReference];
|
|
48
|
+
};
|
|
49
|
+
}[keyof Needs<R[Consumer]> & keyof R];
|
|
50
|
+
}[Consumers];
|
|
51
|
+
type MissingRelationships<R extends Registrations> = {
|
|
52
|
+
[Consumer in keyof R]: {
|
|
53
|
+
[DependencyReference in Exclude<keyof Needs<R[Consumer]>, keyof R>]: {
|
|
54
|
+
consumer: Consumer;
|
|
55
|
+
dependency: DependencyReference;
|
|
56
|
+
expected: Needs<R[Consumer]>[DependencyReference];
|
|
57
|
+
provided: undefined;
|
|
58
|
+
};
|
|
59
|
+
}[Exclude<keyof Needs<R[Consumer]>, keyof R>];
|
|
60
|
+
}[keyof R];
|
|
61
|
+
/** Compile-time admission for finite dependency objects and compatible known services. */
|
|
62
|
+
export type CheckDependencyCompatibility<R extends Registrations> = [
|
|
63
|
+
InvalidNeeds<R> | NonFiniteKeys<R> | Extract<keyof R, number>
|
|
64
|
+
] extends [never] ? [InvalidGraphs<R>] extends [never] ? [WrongShapes<R>] extends [never] ? unknown : Unsatisfied<'provided service does not satisfy its consumer dependency', {
|
|
65
|
+
tokens: WrongShapes<R>;
|
|
66
|
+
relationships: WrongRelationships<R, WrongShapes<R>>;
|
|
67
|
+
}> : Unsatisfied<'token dependency has an incompatible or opaque contract', {
|
|
68
|
+
tokens: InvalidGraphs<R>;
|
|
69
|
+
}> : [NonFiniteKeys<R> | Extract<keyof R, number>] extends [never] ? Unsatisfied<'factory dependencies must be finite string-keyed objects', {
|
|
70
|
+
tokens: InvalidNeeds<R>;
|
|
71
|
+
}> : Unsatisfied<'registration keys must be finite string or unique-symbol keys', {
|
|
72
|
+
keys: NonFiniteKeys<R> | Extract<keyof R, number>;
|
|
73
|
+
}>;
|
|
74
|
+
type NewWrong<E extends Entry, N extends Registrations> = {
|
|
75
|
+
[K in keyof N]: [Exclude<keyof Needs<N[K]>, keyof N> & E['key']] extends [never] ? never : Pick<ServicesOf<RegistrationsFromEntries<E>>, Exclude<keyof Needs<N[K]>, keyof N> & E['key']> extends Pick<Needs<N[K]>, Exclude<keyof Needs<N[K]>, keyof N> & E['key']> ? never : K;
|
|
76
|
+
}[keyof N];
|
|
77
|
+
type OldWrong<E extends Entry, N extends Registrations> = E extends Entry ? E['key'] extends keyof N ? never : Pick<ServicesOf<N>, keyof Needs<E['registration']> & keyof N> extends Pick<Needs<E['registration']>, keyof Needs<E['registration']> & keyof N> ? never : E['key'] : never;
|
|
78
|
+
type NewTokenWrong<E extends Entry, N extends Registrations> = {
|
|
79
|
+
[K in keyof N]: WrongToken<ProviderRequiredTokens<N[K]> | ProviderOptionalTokens<N[K]>, RegistrationsFromEntries<[E['key'] & keyof N] extends [never] ? E : Exclude<E, {
|
|
80
|
+
key: keyof N;
|
|
81
|
+
}>>>;
|
|
82
|
+
}[keyof N];
|
|
83
|
+
type OpaqueTokenNeeds<E extends Entry> = E extends Entry ? E['key'] extends never ? never : WrongToken<ProviderRequiredTokens<E['registration']> | ProviderOptionalTokens<E['registration']>, {}> : never;
|
|
84
|
+
type RetainedTokenNeeds<E extends Entry> = E extends Entry ? E['key'] extends never ? never : ProviderRequiredTokens<E['registration']> | ProviderOptionalTokens<E['registration']> : never;
|
|
85
|
+
type OldTokenWrong<E extends Entry, N extends Registrations> = [Extract<keyof N, symbol>] extends [never] ? OpaqueTokenNeeds<[E['key'] & keyof N] extends [never] ? E : Exclude<E, {
|
|
86
|
+
key: keyof N;
|
|
87
|
+
}>> : string extends E['key'] ? E extends Entry ? E['key'] extends keyof N ? never : WrongToken<ProviderRequiredTokens<E['registration']> | ProviderOptionalTokens<E['registration']>, N> : never : [E['key']] extends [never] ? never : WrongToken<RetainedTokenNeeds<[E['key'] & keyof N] extends [never] ? E : Exclude<E, {
|
|
88
|
+
key: keyof N;
|
|
89
|
+
}>>, N>;
|
|
90
|
+
export type IncrementalChecked<E extends Entry, N extends Registrations> = unknown extends CheckDependencyCompatibility<N> ? [NewTokenWrong<E, N> | OldTokenWrong<E, N>] extends [never] ? [NewWrong<E, N> | OldWrong<E, N>] extends [never] ? unknown : Unsatisfied<'provided service does not satisfy its consumer dependency', {
|
|
91
|
+
tokens: NewWrong<E, N> | OldWrong<E, N>;
|
|
92
|
+
relationships: WrongRelationships<OverrideRegistrations<RegistrationsFromEntries<E>, N>, (NewWrong<E, N> | OldWrong<E, N>) & keyof OverrideRegistrations<RegistrationsFromEntries<E>, N>>;
|
|
93
|
+
}> : Unsatisfied<'token dependency has an incompatible or opaque contract', {
|
|
94
|
+
tokens: NewTokenWrong<E, N> | OldTokenWrong<E, N>;
|
|
95
|
+
}> : CheckDependencyCompatibility<N>;
|
|
96
|
+
export type NamedAdmission<R> = [NonFiniteKeys<R> | Exclude<keyof R, string>] extends [never] ? unknown : Unsatisfied<'register requires finite string-keyed registration objects', {
|
|
97
|
+
keys: NonFiniteKeys<R> | Exclude<keyof R, string>;
|
|
98
|
+
}>;
|
|
99
|
+
type RequiredOf<R extends Registrations> = {
|
|
100
|
+
[K in keyof R]: keyof Needs<R[K]>;
|
|
101
|
+
}[keyof R];
|
|
102
|
+
type CompletionMap<R extends Registrations> = {
|
|
103
|
+
[K in keyof R]: R[K];
|
|
104
|
+
};
|
|
105
|
+
/** Compile-time admission requiring every named and typed-token dependency to be bound. */
|
|
106
|
+
export type CheckDependencyCompleteness<R extends Registrations> = [
|
|
107
|
+
Exclude<RequiredOf<R>, keyof R> | MissingTokens<CompletionMap<R>>
|
|
108
|
+
] extends [never] ? [InvalidGraphs<CompletionMap<R>>] extends [never] ? unknown : Unsatisfied<'token dependency has an incompatible or opaque contract', {
|
|
109
|
+
tokens: InvalidGraphs<CompletionMap<R>>;
|
|
110
|
+
}> : Unsatisfied<'required service registrations are missing', {
|
|
111
|
+
missing: Exclude<RequiredOf<R>, keyof R> | MissingTokens<CompletionMap<R>>;
|
|
112
|
+
relationships: MissingRelationships<R>;
|
|
113
|
+
}>;
|
|
114
|
+
type BadOverrides<F extends Registrations, O extends Registrations> = {
|
|
115
|
+
[K in keyof O & keyof F]: ServicesOf<O>[K] extends ServicesOf<F>[K] ? never : K;
|
|
116
|
+
}[keyof O & keyof F];
|
|
117
|
+
/** Admit overrides only for existing keys whose service values remain assignable. */
|
|
118
|
+
export type Overrides<F extends Registrations, O extends Registrations> = [
|
|
119
|
+
Exclude<keyof O, keyof F>
|
|
120
|
+
] extends [never] ? [BadOverrides<F, O>] extends [never] ? unknown : Unsatisfied<'override value is not assignable to the original token', {
|
|
121
|
+
tokens: BadOverrides<F, O>;
|
|
122
|
+
}> : Unsatisfied<'fork accepts existing names or typed tokens only', {
|
|
123
|
+
extra: Exclude<keyof O, keyof F>;
|
|
124
|
+
}>;
|
|
125
|
+
export type Introduces<F extends Registrations, N extends Registrations> = [
|
|
126
|
+
keyof F & keyof N
|
|
127
|
+
] extends [never] ? unknown : Unsatisfied<'register introduces new names or typed tokens only', {
|
|
128
|
+
duplicates: keyof F & keyof N;
|
|
129
|
+
}>;
|
|
130
|
+
export type EntryKeys<E extends Entry> = string extends E['key'] ? keyof RegistrationsFromEntries<E> : E['key'];
|
|
131
|
+
export type IntroducesKeys<Known extends PropertyKey, New extends PropertyKey> = [Known & New] extends [never] ? unknown : Unsatisfied<'register introduces new names or typed tokens only', {
|
|
132
|
+
duplicates: Known & New;
|
|
133
|
+
}>;
|
|
134
|
+
export type Singleton<K> = [K] extends [never] ? false : [K] extends [string] ? true extends IsUnion<K> ? false : [NonFiniteKeys<Record<K & string, never>>] extends [never] ? true : false : false;
|
|
135
|
+
export type ReplacementKey<R extends Registrations, K extends string> = Singleton<K> extends true ? K extends keyof R ? unknown : Unsatisfied<'replace requires one existing singleton string-literal key', {
|
|
136
|
+
key: K;
|
|
137
|
+
}> : Unsatisfied<'replace requires one existing singleton string-literal key', {
|
|
138
|
+
key: K;
|
|
139
|
+
}>;
|
|
140
|
+
export type ReplacementKeyOf<Keys extends PropertyKey, K extends string> = Singleton<K> extends true ? K extends Keys ? unknown : Unsatisfied<'replace requires one existing singleton string-literal key', {
|
|
141
|
+
key: K;
|
|
142
|
+
}> : Unsatisfied<'replace requires one existing singleton string-literal key', {
|
|
143
|
+
key: K;
|
|
144
|
+
}>;
|
|
145
|
+
type ReplacementRequirement<N, K extends PropertyKey> = K extends keyof N ? (value: N[K]) => void : never;
|
|
146
|
+
type LocalReplacementRequirement<R extends Registrations, K extends PropertyKey, P extends keyof R> = P extends unknown ? ReplacementRequirement<Required<Needs<R[P]>>, K> : never;
|
|
147
|
+
type LocalReplacementRequirements<R extends Registrations, K extends PropertyKey> = LocalReplacementRequirement<R, K, Exclude<keyof R, K>>;
|
|
148
|
+
type RetainedReplacementRequirements<C, K extends PropertyKey> = C extends {
|
|
149
|
+
readonly needs: infer N;
|
|
150
|
+
} ? ReplacementRequirement<N, K> : never;
|
|
151
|
+
type ReplacementRequirements<R extends Registrations, K extends PropertyKey, C> = LocalReplacementRequirements<R, K> | RetainedReplacementRequirements<C, K>;
|
|
152
|
+
export type ReplacementOutput<R extends Registrations, K extends PropertyKey, C = never> = [
|
|
153
|
+
ReplacementRequirements<R, K, C>
|
|
154
|
+
] extends [never] ? unknown : ReplacementRequirements<R, K, C> extends (value: infer O) => void ? O : unknown;
|
|
155
|
+
type InvalidElements<K extends readonly unknown[]> = {
|
|
156
|
+
[I in keyof K]-?: Singleton<K[I]> extends true ? never : ValidToken<K[I]> extends true ? never : I;
|
|
157
|
+
}[number];
|
|
158
|
+
type InvalidMembers<R extends Registrations, T> = T extends string ? never : unknown extends TokenMember<R, T> ? never : T;
|
|
159
|
+
/** Validate a finite tuple of existing singleton names or genuine typed tokens. */
|
|
160
|
+
export type Selection<R extends Registrations, K extends readonly unknown[], Operation extends string = 'fork'> = true extends IsUnion<K> ? InvalidSelection<Operation> : number extends K['length'] ? InvalidSelection<Operation> : K extends Required<K> ? [InvalidElements<K>] extends [never] ? [Exclude<SelectionKey<K[number]>, keyof R> | InvalidMembers<R, K[number]>] extends [never] ? unknown : Unsatisfied<`${Operation} accepts existing names or typed tokens only`, {
|
|
161
|
+
extra: Exclude<SelectionKey<K[number]>, keyof R> | InvalidMembers<R, K[number]>;
|
|
162
|
+
}> : InvalidSelection<Operation> : InvalidSelection<Operation>;
|
|
163
|
+
type InvalidSelection<Operation extends string> = Unsatisfied<`${Operation} requires a finite tuple of singleton string-literal names or typed tokens`, {
|
|
164
|
+
selection: 'use a const tuple with individually known names or typed tokens';
|
|
165
|
+
}>;
|
|
166
|
+
/** Select registration-valued own fields corresponding to a checked key tuple. */
|
|
167
|
+
export type SelectedRegistrations<K extends readonly unknown[], O> = {
|
|
168
|
+
[P in Extract<SelectionKey<K[number]>, keyof O>]: Extract<O[P], Registration>;
|
|
169
|
+
};
|
|
170
|
+
/** Contextual override shape used to infer a selected fork or child-scope graph. */
|
|
171
|
+
export type OverrideFactoryContext<R extends Registrations, K extends readonly unknown[], O> = {
|
|
172
|
+
[P in Extract<SelectionKey<K[number]>, keyof R>]: ((this: void, deps: ServicesOf<OverrideRegistrations<R, SelectedRegistrations<K, O>>>) => ServicesOf<R>[P]) | FactoryWithDisposal<(this: void, deps: ServicesOf<OverrideRegistrations<R, SelectedRegistrations<K, O>>>) => ServicesOf<R>[P]> | ProviderContext<(this: void, deps: ServicesOf<OverrideRegistrations<R, SelectedRegistrations<K, O>>>) => ServicesOf<R>[P], P extends keyof O ? ProviderGraphContract<Extract<O[P], Registration>> : TokenDependencyContract>;
|
|
173
|
+
};
|
|
174
|
+
export {};
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "di-bag",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Type-checked dependency composition with lazy factories, forks, and optional disposal.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./node": {
|
|
9
|
+
"types": "./dist/node.d.ts",
|
|
10
|
+
"default": "./dist/node.js"
|
|
11
|
+
},
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"test": "bun test tests",
|
|
22
|
+
"typecheck": "tsc6 -p tsconfig.json",
|
|
23
|
+
"typecheck:native": "tsc -p tsconfig.json",
|
|
24
|
+
"build:native": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json",
|
|
25
|
+
"check:native": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON scripts/check-native-contracts.ts",
|
|
26
|
+
"example:wbs": "bun run examples/wbs-scope.ts",
|
|
27
|
+
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc6 -p ./tsconfig.build.json",
|
|
28
|
+
"benchmark:types": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON scripts/benchmark-types.ts",
|
|
29
|
+
"benchmark:compiler-controls": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON scripts/benchmark-compiler-controls.ts",
|
|
30
|
+
"benchmark:runtime": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON scripts/performance-evidence.ts --current",
|
|
31
|
+
"evidence:platform": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON scripts/platform-evidence.ts",
|
|
32
|
+
"platform:pin": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON scripts/pin-platform-tools.ts",
|
|
33
|
+
"check:platform": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON scripts/platform-evidence.ts --required",
|
|
34
|
+
"docs:generate": "node tools/docs/generate.mjs",
|
|
35
|
+
"docs:check": "node --test --test-isolation=none tools/docs/test/*.test.mjs && node tools/docs/generate.mjs --check && node tools/docs/site.mjs check",
|
|
36
|
+
"docs:build": "node tools/docs/site.mjs build",
|
|
37
|
+
"docs:dev": "node tools/docs/site.mjs dev",
|
|
38
|
+
"docs:preview": "node tools/docs/site.mjs preview",
|
|
39
|
+
"prepack": "npm run build",
|
|
40
|
+
"check": "npm run typecheck && npm test && npm run build"
|
|
41
|
+
},
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/dany-fedorov/di-bag.git"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://dany-fedorov.github.io/di-bag",
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"di",
|
|
52
|
+
"bag"
|
|
53
|
+
],
|
|
54
|
+
"author": "Dany Fedorov",
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/bun": "^1.3.0",
|
|
58
|
+
"@typescript/native": "npm:typescript@7.0.2",
|
|
59
|
+
"typescript": "npm:@typescript/typescript6@6.0.2"
|
|
60
|
+
},
|
|
61
|
+
"overrides": {
|
|
62
|
+
"@typescript/old": "npm:typescript@6.0.3"
|
|
63
|
+
}
|
|
64
|
+
}
|