@decohere/crucible 0.0.1-dev.19 → 0.0.1-dev.20261105.103
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 +15 -0
- package/README.md +354 -0
- package/es6/src/const.js +3 -5
- package/es6/src/decorators/index.js +0 -2
- package/es6/src/decorators/inject.decorator.js +27 -14
- package/es6/src/decorators/injectable.dectorator.js +0 -2
- package/es6/src/index.js +0 -2
- package/es6/src/models/service-key.js +10 -0
- package/es6/src/models/service-registration.model.js +1 -6
- package/es6/src/services/container.js +197 -0
- package/es6/src/services/index.js +2 -4
- package/es6/src/services/service-container-builder.js +57 -0
- package/es6/src/services/service-registry.js +34 -23
- package/es6/src/types/errors.js +0 -2
- package/es6/src/types/index.js +1 -2
- package/es6/src/types/types.js +0 -2
- package/package.json +13 -7
- package/types/src/const.d.ts +1 -1
- package/types/src/decorators/inject.decorator.d.ts +17 -2
- package/types/src/models/service-key.d.ts +9 -0
- package/types/src/models/service-registration.model.d.ts +5 -4
- package/types/src/services/{crucible.d.ts → container.d.ts} +16 -5
- package/types/src/services/index.d.ts +2 -2
- package/types/src/services/{crucible-builder.d.ts → service-container-builder.d.ts} +9 -5
- package/types/src/services/service-registry.d.ts +12 -6
- package/types/src/types/index.d.ts +1 -0
- package/types/src/types/types.d.ts +1 -1
- package/commonjs/src/const.js +0 -33
- package/commonjs/src/decorators/index.js +0 -21
- package/commonjs/src/decorators/inject.decorator.js +0 -27
- package/commonjs/src/decorators/injectable.dectorator.js +0 -16
- package/commonjs/src/index.js +0 -22
- package/commonjs/src/models/registration-key.model.js +0 -31
- package/commonjs/src/models/service-registration.model.js +0 -30
- package/commonjs/src/services/crucible-builder.js +0 -68
- package/commonjs/src/services/crucible.js +0 -165
- package/commonjs/src/services/index.js +0 -21
- package/commonjs/src/services/service-registry.js +0 -50
- package/commonjs/src/types/errors.js +0 -29
- package/commonjs/src/types/index.js +0 -20
- package/commonjs/src/types/types.js +0 -6
- package/es6/src/models/registration-key.model.js +0 -21
- package/es6/src/services/crucible-builder.js +0 -58
- package/es6/src/services/crucible.js +0 -155
- package/types/src/models/registration-key.model.d.ts +0 -7
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { getMeta, isArrayType, isConstructable, ReflectionMeta } from "@decohere/core/reflection";
|
|
2
|
+
import { ContainerMeta, LifetimeScopeToken, Scopes } from "../const.js";
|
|
3
|
+
import { describeKey } from "../models/service-key.js";
|
|
4
|
+
import { DuplicateScopeError, ResolveError } from "../types/errors.js";
|
|
5
|
+
import { ServiceRegistry } from "./service-registry.js";
|
|
6
|
+
function describePath(path, last) {
|
|
7
|
+
const keys = path.map((registration)=>registration.key);
|
|
8
|
+
return [
|
|
9
|
+
...keys,
|
|
10
|
+
...last == null ? [] : [
|
|
11
|
+
last
|
|
12
|
+
]
|
|
13
|
+
].map(describeKey).join(" → ");
|
|
14
|
+
}
|
|
15
|
+
export class Container {
|
|
16
|
+
key;
|
|
17
|
+
instances = new Map();
|
|
18
|
+
serviceRegistry;
|
|
19
|
+
parent;
|
|
20
|
+
rootScope;
|
|
21
|
+
scopes = new Map();
|
|
22
|
+
isDisposed = false;
|
|
23
|
+
constructor(options){
|
|
24
|
+
this.key = options?.key;
|
|
25
|
+
this.serviceRegistry = new ServiceRegistry(options?.serviceRegistry);
|
|
26
|
+
this.registerLifetimeScope();
|
|
27
|
+
this.parent = options?.parent;
|
|
28
|
+
this.rootScope = options?.parent?.rootScope ?? this;
|
|
29
|
+
}
|
|
30
|
+
resolveMany(resolveRequest) {
|
|
31
|
+
return this.resolveAll(resolveRequest, []);
|
|
32
|
+
}
|
|
33
|
+
/** Throws {@link ResolveError} when nothing is registered for the key. */ resolve(resolveRequest) {
|
|
34
|
+
return this.resolveOne(resolveRequest, [], false);
|
|
35
|
+
}
|
|
36
|
+
resolveAll(key, path) {
|
|
37
|
+
const registrations = this.serviceRegistry.getRegistration(key) ?? [];
|
|
38
|
+
return registrations.map((registration)=>this.resolveRegistration(registration, path));
|
|
39
|
+
}
|
|
40
|
+
resolveOne(key, path, optional) {
|
|
41
|
+
const registrations = this.serviceRegistry.getRegistration(key);
|
|
42
|
+
if (registrations == null || registrations.length === 0) {
|
|
43
|
+
if (optional) return undefined;
|
|
44
|
+
const requiredBy = path.length === 0 ? "" : ` (required by ${describePath(path, key)})`;
|
|
45
|
+
throw new ResolveError(`Nothing is registered for ${describeKey(key)}${requiredBy}. Register it, or mark the parameter @optional().`);
|
|
46
|
+
}
|
|
47
|
+
if (registrations.length > 1) {
|
|
48
|
+
throw new ResolveError(`There are multiple services registered with key ${describeKey(key)}. Use resolveMany to resolve all implementations.`);
|
|
49
|
+
}
|
|
50
|
+
return this.resolveRegistration(registrations[0], path);
|
|
51
|
+
}
|
|
52
|
+
beginScope(name) {
|
|
53
|
+
if (this.isDisposed) {
|
|
54
|
+
throw new Error("This container has been disposed");
|
|
55
|
+
}
|
|
56
|
+
if (name != null && this.scopes.has(name)) {
|
|
57
|
+
throw new DuplicateScopeError(`Cannot create duplicate scope. Scope with ${name} is already created and has not been disposed.`);
|
|
58
|
+
}
|
|
59
|
+
const scope = new Container({
|
|
60
|
+
key: name,
|
|
61
|
+
serviceRegistry: this.serviceRegistry,
|
|
62
|
+
parent: this
|
|
63
|
+
});
|
|
64
|
+
if (name != null) {
|
|
65
|
+
this.scopes.set(name, scope);
|
|
66
|
+
}
|
|
67
|
+
return scope;
|
|
68
|
+
}
|
|
69
|
+
[Symbol.dispose]() {
|
|
70
|
+
if (this.isDisposed) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
this.disposeSync();
|
|
74
|
+
}
|
|
75
|
+
async [Symbol.asyncDispose]() {
|
|
76
|
+
if (this.isDisposed) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await this.disposeAsync();
|
|
80
|
+
}
|
|
81
|
+
disposeSync() {
|
|
82
|
+
if (this.isDisposed) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
this.isDisposed = true;
|
|
86
|
+
this.parent?.releaseScope(this.key);
|
|
87
|
+
this.scopes.clear();
|
|
88
|
+
// Reverse creation order: dependents are cleaned up before what they depend on.
|
|
89
|
+
for (const inst of [
|
|
90
|
+
...this.instances.values()
|
|
91
|
+
].reverse()){
|
|
92
|
+
if (inst === this) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
inst[Symbol.dispose]?.();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async disposeAsync() {
|
|
99
|
+
if (this.isDisposed) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
this.isDisposed = true;
|
|
103
|
+
this.parent?.releaseScope(this.key);
|
|
104
|
+
this.scopes.clear();
|
|
105
|
+
// Reverse creation order: dependents are cleaned up before what they depend on.
|
|
106
|
+
for (const inst of [
|
|
107
|
+
...this.instances.values()
|
|
108
|
+
].reverse()){
|
|
109
|
+
if (inst === this) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (Symbol.asyncDispose in inst) {
|
|
113
|
+
await inst[Symbol.asyncDispose]();
|
|
114
|
+
} else {
|
|
115
|
+
inst[Symbol.dispose]?.();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
resolveRegistration(registration, path) {
|
|
120
|
+
this.assertNoCycle(registration, path);
|
|
121
|
+
this.assertNotCaptive(registration, path);
|
|
122
|
+
const { scope } = registration;
|
|
123
|
+
switch(scope){
|
|
124
|
+
case Scopes.transient:
|
|
125
|
+
return this.createInstance(registration, path);
|
|
126
|
+
case Scopes.singleton:
|
|
127
|
+
return this.rootScope.getOrCreateInstance(registration, path);
|
|
128
|
+
case Scopes.request:
|
|
129
|
+
return this.getOrCreateInstance(registration, path);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
assertNoCycle(registration, path) {
|
|
133
|
+
if (!path.includes(registration)) return;
|
|
134
|
+
throw new ResolveError(`Circular dependency: ${describePath(path, registration.key)}. Break the cycle, e.g. by resolving one side lazily from the LifetimeScope.`);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* A singleton lives for the whole process, so a request-scoped service it depends on (directly
|
|
138
|
+
* or through transients) would be created once and then shared by every request, e.g. one
|
|
139
|
+
* QueryRunner for the life of the process. The container's own lifetime scope is exempt: a
|
|
140
|
+
* singleton asking for it gets the root, which is the scope it lives in.
|
|
141
|
+
*/ assertNotCaptive(registration, path) {
|
|
142
|
+
if (registration.scope !== Scopes.request || registration.key === LifetimeScopeToken) return;
|
|
143
|
+
const singleton = path.find((owner)=>owner.scope === Scopes.singleton);
|
|
144
|
+
if (singleton == null) return;
|
|
145
|
+
throw new ResolveError(`Singleton ${describeKey(singleton.key)} depends on request-scoped ${describeKey(registration.key)} (${describePath(path, registration.key)}). A singleton would keep the first request's instance forever: make ${describeKey(singleton.key)} request-scoped, or resolve ${describeKey(registration.key)} per request from the LifetimeScope.`);
|
|
146
|
+
}
|
|
147
|
+
getOrCreateInstance(registration, path) {
|
|
148
|
+
if (this.isDisposed) {
|
|
149
|
+
throw new Error("This container has been disposed");
|
|
150
|
+
}
|
|
151
|
+
const { type, isInstance } = registration;
|
|
152
|
+
// One cache entry per registration: an instance registration is its own entry.
|
|
153
|
+
const cacheKey = type;
|
|
154
|
+
const existingInstance = this.instances.get(cacheKey);
|
|
155
|
+
if (existingInstance != null) {
|
|
156
|
+
return existingInstance;
|
|
157
|
+
}
|
|
158
|
+
const instance = isInstance ? type : this.createInstance(registration, path);
|
|
159
|
+
this.instances.set(cacheKey, instance);
|
|
160
|
+
return instance;
|
|
161
|
+
}
|
|
162
|
+
createInstance(registration, path) {
|
|
163
|
+
const type = registration.type;
|
|
164
|
+
const canConstruct = isConstructable(type);
|
|
165
|
+
const deps = this.resolveDependencies(type, [
|
|
166
|
+
...path,
|
|
167
|
+
registration
|
|
168
|
+
]);
|
|
169
|
+
const inst = canConstruct ? new type(...deps) : type();
|
|
170
|
+
return inst;
|
|
171
|
+
}
|
|
172
|
+
resolveDependencies(type, path) {
|
|
173
|
+
const params = getMeta(ReflectionMeta.paramtypes, type) ?? [];
|
|
174
|
+
const injectTokens = getMeta(ContainerMeta.injecttoken, type) ?? new Map();
|
|
175
|
+
return params.map((param, index)=>{
|
|
176
|
+
const token = injectTokens.get(index);
|
|
177
|
+
const key = token?.key ?? param;
|
|
178
|
+
if (key == null || key === Object || token?.key == null && isArrayType(param)) {
|
|
179
|
+
if (token?.optional) return undefined;
|
|
180
|
+
throw new ResolveError(`Cannot tell what to inject for constructor parameter ${index} of ${describePath(path)}: its type is not a class at run time (an interface, an array, or a type-only import). Add @inject(token) to the parameter.`);
|
|
181
|
+
}
|
|
182
|
+
return isArrayType(param) ? this.resolveAll(key, path) : this.resolveOne(key, path, token?.optional === true);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
releaseScope(name) {
|
|
186
|
+
if (name == null) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
this.scopes.delete(name);
|
|
190
|
+
}
|
|
191
|
+
registerLifetimeScope() {
|
|
192
|
+
this.serviceRegistry.replaceType(Scopes.request, {
|
|
193
|
+
typeOrKey: LifetimeScopeToken,
|
|
194
|
+
typeOrInstance: this
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
|
|
4
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9zZXJ2aWNlcy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi9jcnVjaWJsZS5qc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vY3J1Y2libGUtYnVpbGRlci5qc1wiO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsZ0JBQWdCO0FBQzlCLGNBQWMsd0JBQXdCIn0=
|
|
1
|
+
export * from "./container.js";
|
|
2
|
+
export * from "./service-container-builder.js";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Scopes } from "../const.js";
|
|
2
|
+
import { Container } from "./container.js";
|
|
3
|
+
import { ServiceRegistry } from "./service-registry.js";
|
|
4
|
+
export class ServiceContainerBuilder {
|
|
5
|
+
serviceRegistry;
|
|
6
|
+
constructor(options){
|
|
7
|
+
this.serviceRegistry = options?.serviceRegistry ?? new ServiceRegistry();
|
|
8
|
+
}
|
|
9
|
+
get override() {
|
|
10
|
+
return this.createRegistrar(true);
|
|
11
|
+
}
|
|
12
|
+
registerType(type, scope = Scopes.transient) {
|
|
13
|
+
return this.register(false)(scope)(type, type);
|
|
14
|
+
}
|
|
15
|
+
registerTypes(scopeOrType, ...types) {
|
|
16
|
+
return this.registerMany(false, scopeOrType, types);
|
|
17
|
+
}
|
|
18
|
+
registerTransient(typeOrKey, type) {
|
|
19
|
+
return this.register(false)(Scopes.transient)(typeOrKey, type);
|
|
20
|
+
}
|
|
21
|
+
registerSingleton(typeOrKey, typeOrInstance) {
|
|
22
|
+
return this.register(false)(Scopes.singleton)(typeOrKey, typeOrInstance);
|
|
23
|
+
}
|
|
24
|
+
registerRequestScoped(typeOrKey, type) {
|
|
25
|
+
return this.register(false)(Scopes.request)(typeOrKey, type);
|
|
26
|
+
}
|
|
27
|
+
build() {
|
|
28
|
+
return new Container({
|
|
29
|
+
serviceRegistry: this.serviceRegistry
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
register = (override)=>(scope)=>(typeOrKey, typeOrInstance)=>this.serviceRegistry.registerType(scope, {
|
|
33
|
+
typeOrKey,
|
|
34
|
+
typeOrInstance,
|
|
35
|
+
override
|
|
36
|
+
});
|
|
37
|
+
registerMany(override, scopeOrType, types) {
|
|
38
|
+
const bind = this.register(override);
|
|
39
|
+
const isScope = typeof scopeOrType !== "function";
|
|
40
|
+
const scope = isScope ? scopeOrType : Scopes.transient;
|
|
41
|
+
const allTypes = isScope ? types : [
|
|
42
|
+
scopeOrType,
|
|
43
|
+
...types
|
|
44
|
+
];
|
|
45
|
+
return allTypes.map((type)=>bind(scope)(type, type));
|
|
46
|
+
}
|
|
47
|
+
createRegistrar(override) {
|
|
48
|
+
const bind = this.register(override);
|
|
49
|
+
return {
|
|
50
|
+
registerType: (type, scope = Scopes.transient)=>bind(scope)(type, type),
|
|
51
|
+
registerTypes: (scopeOrType, ...types)=>this.registerMany(override, scopeOrType, types),
|
|
52
|
+
registerTransient: (typeOrKey, type)=>bind(Scopes.transient)(typeOrKey, type),
|
|
53
|
+
registerSingleton: (typeOrKey, typeOrInstance)=>bind(Scopes.singleton)(typeOrKey, typeOrInstance),
|
|
54
|
+
registerRequestScoped: (typeOrKey, type)=>bind(Scopes.request)(typeOrKey, type)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,40 +1,51 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { describeKey } from "../models/service-key.js";
|
|
2
2
|
import { ServiceRegistration } from "../models/service-registration.model.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { RegistrationError } from "../types/errors.js";
|
|
4
|
+
/**
|
|
5
|
+
* Registrations by key. A scope's registry holds only what the scope adds (its own lifetime
|
|
6
|
+
* scope) and looks everything else up in its parent, so beginning a scope costs the same however
|
|
7
|
+
* many services are registered.
|
|
8
|
+
*/ export class ServiceRegistry {
|
|
9
|
+
#registrations = new Map();
|
|
10
|
+
#parent;
|
|
5
11
|
constructor(parent){
|
|
6
|
-
this
|
|
12
|
+
this.#parent = parent;
|
|
7
13
|
}
|
|
8
14
|
registerType(scope, options) {
|
|
9
15
|
const registration = this.createRegistrationFrom(scope, options);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
registration,
|
|
13
|
-
|
|
16
|
+
// Override means "this key now resolves to this", e.g. a test fake: replace every binding.
|
|
17
|
+
if (options.override) {
|
|
18
|
+
this.#registrations.set(registration.key, [
|
|
19
|
+
registration
|
|
20
|
+
]);
|
|
21
|
+
return registration;
|
|
22
|
+
}
|
|
23
|
+
const existing = this.getRegistration(registration.key) ?? [];
|
|
24
|
+
const duplicate = existing.find((reg)=>reg.isEqual(registration));
|
|
25
|
+
if (duplicate != null) {
|
|
26
|
+
throw new RegistrationError(`A service is already registered for key ${describeKey(registration.key)}. Use builder.override.registerSingleton() (or the matching register* method) to replace it.`);
|
|
27
|
+
}
|
|
28
|
+
this.#registrations.set(registration.key, [
|
|
29
|
+
...existing,
|
|
30
|
+
registration
|
|
14
31
|
]);
|
|
15
32
|
return registration;
|
|
16
33
|
}
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
34
|
+
replaceType(scope, options) {
|
|
35
|
+
const registration = this.createRegistrationFrom(scope, options);
|
|
36
|
+
this.#registrations.set(registration.key, [
|
|
37
|
+
registration
|
|
38
|
+
]);
|
|
20
39
|
return registration;
|
|
21
40
|
}
|
|
41
|
+
getRegistration(key) {
|
|
42
|
+
return this.#registrations.get(key) ?? this.#parent?.getRegistration(key);
|
|
43
|
+
}
|
|
22
44
|
createRegistrationFrom(scope, options) {
|
|
23
45
|
const { typeOrKey, typeOrInstance } = options;
|
|
24
46
|
const isKey = typeof typeOrKey === "string" || typeof typeOrKey === "symbol";
|
|
25
47
|
const isInstance = typeof typeOrInstance === "object";
|
|
26
|
-
const key = new RegistrationKey(!isKey ? typeOrKey.name : typeOrKey);
|
|
27
48
|
const type = isInstance ? typeOrInstance : isKey ? typeOrInstance : typeOrKey;
|
|
28
|
-
|
|
29
|
-
return registration;
|
|
30
|
-
}
|
|
31
|
-
getRegistrations(key) {
|
|
32
|
-
const value = key.value;
|
|
33
|
-
return this.registrations.get(value);
|
|
34
|
-
}
|
|
35
|
-
setRegistration(key, registrations) {
|
|
36
|
-
this.registrations.set(key.value, registrations);
|
|
49
|
+
return new ServiceRegistration(typeOrKey, type, scope, isInstance);
|
|
37
50
|
}
|
|
38
51
|
}
|
|
39
|
-
|
|
40
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9zZXJ2aWNlcy9zZXJ2aWNlLXJlZ2lzdHJ5LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgQ29uc3RydWN0YWJsZSwgRnVuY3Rpb25UeXBlIH0gZnJvbSBcIkBkZWNvaGVyZS9uZXh1cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBSZWdpc3RyYXRpb25LZXkgfSBmcm9tIFwiLi4vbW9kZWxzL3JlZ2lzdHJhdGlvbi1rZXkubW9kZWwuanNcIjtcbmltcG9ydCB7IFNlcnZpY2VSZWdpc3RyYXRpb24gfSBmcm9tIFwiLi4vbW9kZWxzL3NlcnZpY2UtcmVnaXN0cmF0aW9uLm1vZGVsLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFNjb3BlIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzLmpzXCI7XG5cbmV4cG9ydCB0eXBlIFJlZ2lzdGVyVHlwZU9wdGlvbnMgPSB7XG5cdHR5cGVPcktleTogc3RyaW5nIHwgc3ltYm9sIHwgQ29uc3RydWN0YWJsZSB8IEZ1bmN0aW9uVHlwZTtcblx0dHlwZU9ySW5zdGFuY2U/OiBDb25zdHJ1Y3RhYmxlIHwgRnVuY3Rpb25UeXBlIHwgb2JqZWN0O1xufTtcblxuZXhwb3J0IGNsYXNzIFNlcnZpY2VSZWdpc3RyeSB7XG5cdHByaXZhdGUgcmVhZG9ubHkgcmVnaXN0cmF0aW9uczogTWFwPHN0cmluZywgU2VydmljZVJlZ2lzdHJhdGlvbltdPjtcblx0cHVibGljIGNvbnN0cnVjdG9yKHBhcmVudD86IFNlcnZpY2VSZWdpc3RyeSkge1xuXHRcdHRoaXMucmVnaXN0cmF0aW9ucyA9IG5ldyBNYXAocGFyZW50Py5yZWdpc3RyYXRpb25zKTtcblx0fVxuXG5cdHB1YmxpYyByZWdpc3RlclR5cGUoc2NvcGU6IFNjb3BlLCBvcHRpb25zOiBSZWdpc3RlclR5cGVPcHRpb25zKSB7XG5cdFx0Y29uc3QgcmVnaXN0cmF0aW9uID0gdGhpcy5jcmVhdGVSZWdpc3RyYXRpb25Gcm9tKHNjb3BlLCBvcHRpb25zKTtcblx0XHRjb25zdCBleGlzdGluZ1JlZ2lzdHJhdGlvbiA9XG5cdFx0XHR0aGlzLmdldFJlZ2lzdHJhdGlvbnMocmVnaXN0cmF0aW9uLmtleSk/LmZpbHRlcigocmVnKSA9PiAhcmVnLmlzRXF1YWwocmVnaXN0cmF0aW9uKSkgPz9cblx0XHRcdFtdO1xuXG5cdFx0dGhpcy5zZXRSZWdpc3RyYXRpb24ocmVnaXN0cmF0aW9uLmtleSwgW3JlZ2lzdHJhdGlvbiwgLi4uZXhpc3RpbmdSZWdpc3RyYXRpb25dKTtcblx0XHRyZXR1cm4gcmVnaXN0cmF0aW9uO1xuXHR9XG5cblx0cHVibGljIGdldFJlZ2lzdHJhdGlvbihrZXk6IHN0cmluZyB8IHN5bWJvbCB8IENvbnN0cnVjdGFibGUpOiBTZXJ2aWNlUmVnaXN0cmF0aW9uW10ge1xuXHRcdGNvbnN0IGtleVZhbCA9IG5ldyBSZWdpc3RyYXRpb25LZXkoa2V5KS52YWx1ZTtcblx0XHRjb25zdCByZWdpc3RyYXRpb24gPSB0aGlzLnJlZ2lzdHJhdGlvbnMuZ2V0KGtleVZhbCk7XG5cdFx0cmV0dXJuIHJlZ2lzdHJhdGlvbjtcblx0fVxuXG5cdHByaXZhdGUgY3JlYXRlUmVnaXN0cmF0aW9uRnJvbShzY29wZTogU2NvcGUsIG9wdGlvbnM6IFJlZ2lzdGVyVHlwZU9wdGlvbnMpIHtcblx0XHRjb25zdCB7IHR5cGVPcktleSwgdHlwZU9ySW5zdGFuY2UgfSA9IG9wdGlvbnM7XG5cdFx0Y29uc3QgaXNLZXkgPSB0eXBlb2YgdHlwZU9yS2V5ID09PSBcInN0cmluZ1wiIHx8IHR5cGVvZiB0eXBlT3JLZXkgPT09IFwic3ltYm9sXCI7XG5cdFx0Y29uc3QgaXNJbnN0YW5jZSA9IHR5cGVvZiB0eXBlT3JJbnN0YW5jZSA9PT0gXCJvYmplY3RcIjtcblx0XHRjb25zdCBrZXkgPSBuZXcgUmVnaXN0cmF0aW9uS2V5KCFpc0tleSA/IHR5cGVPcktleS5uYW1lIDogdHlwZU9yS2V5KTtcblx0XHRjb25zdCB0eXBlID0gaXNJbnN0YW5jZSA/IHR5cGVPckluc3RhbmNlIDogaXNLZXkgPyB0eXBlT3JJbnN0YW5jZSA6IHR5cGVPcktleTtcblx0XHRjb25zdCByZWdpc3RyYXRpb24gPSBuZXcgU2VydmljZVJlZ2lzdHJhdGlvbihrZXksIHR5cGUsIHNjb3BlLCBpc0luc3RhbmNlKTtcblx0XHRyZXR1cm4gcmVnaXN0cmF0aW9uO1xuXHR9XG5cblx0cHJpdmF0ZSBnZXRSZWdpc3RyYXRpb25zKGtleTogUmVnaXN0cmF0aW9uS2V5KSB7XG5cdFx0Y29uc3QgdmFsdWUgPSBrZXkudmFsdWU7XG5cdFx0cmV0dXJuIHRoaXMucmVnaXN0cmF0aW9ucy5nZXQodmFsdWUpO1xuXHR9XG5cblx0cHJpdmF0ZSBzZXRSZWdpc3RyYXRpb24oa2V5OiBSZWdpc3RyYXRpb25LZXksIHJlZ2lzdHJhdGlvbnM6IFNlcnZpY2VSZWdpc3RyYXRpb25bXSkge1xuXHRcdHRoaXMucmVnaXN0cmF0aW9ucy5zZXQoa2V5LnZhbHVlLCByZWdpc3RyYXRpb25zKTtcblx0fVxufVxuIl0sIm5hbWVzIjpbIlJlZ2lzdHJhdGlvbktleSIsIlNlcnZpY2VSZWdpc3RyYXRpb24iLCJTZXJ2aWNlUmVnaXN0cnkiLCJyZWdpc3RyYXRpb25zIiwicGFyZW50IiwiTWFwIiwicmVnaXN0ZXJUeXBlIiwic2NvcGUiLCJvcHRpb25zIiwicmVnaXN0cmF0aW9uIiwiY3JlYXRlUmVnaXN0cmF0aW9uRnJvbSIsImV4aXN0aW5nUmVnaXN0cmF0aW9uIiwiZ2V0UmVnaXN0cmF0aW9ucyIsImtleSIsImZpbHRlciIsInJlZyIsImlzRXF1YWwiLCJzZXRSZWdpc3RyYXRpb24iLCJnZXRSZWdpc3RyYXRpb24iLCJrZXlWYWwiLCJ2YWx1ZSIsImdldCIsInR5cGVPcktleSIsInR5cGVPckluc3RhbmNlIiwiaXNLZXkiLCJpc0luc3RhbmNlIiwibmFtZSIsInR5cGUiLCJzZXQiXSwibWFwcGluZ3MiOiJBQUNBLFNBQVNBLGVBQWUsUUFBUSxzQ0FBc0M7QUFDdEUsU0FBU0MsbUJBQW1CLFFBQVEsMENBQTBDO0FBUTlFLE9BQU8sTUFBTUM7SUFDS0MsY0FBa0Q7SUFDbkUsWUFBbUJDLE1BQXdCLENBQUU7UUFDNUMsSUFBSSxDQUFDRCxhQUFhLEdBQUcsSUFBSUUsSUFBSUQsUUFBUUQ7SUFDdEM7SUFFT0csYUFBYUMsS0FBWSxFQUFFQyxPQUE0QixFQUFFO1FBQy9ELE1BQU1DLGVBQWUsSUFBSSxDQUFDQyxzQkFBc0IsQ0FBQ0gsT0FBT0M7UUFDeEQsTUFBTUcsdUJBQ0wsSUFBSSxDQUFDQyxnQkFBZ0IsQ0FBQ0gsYUFBYUksR0FBRyxHQUFHQyxPQUFPLENBQUNDLE1BQVEsQ0FBQ0EsSUFBSUMsT0FBTyxDQUFDUCxrQkFDdEUsRUFBRTtRQUVILElBQUksQ0FBQ1EsZUFBZSxDQUFDUixhQUFhSSxHQUFHLEVBQUU7WUFBQ0o7ZUFBaUJFO1NBQXFCO1FBQzlFLE9BQU9GO0lBQ1I7SUFFT1MsZ0JBQWdCTCxHQUFvQyxFQUF5QjtRQUNuRixNQUFNTSxTQUFTLElBQUluQixnQkFBZ0JhLEtBQUtPLEtBQUs7UUFDN0MsTUFBTVgsZUFBZSxJQUFJLENBQUNOLGFBQWEsQ0FBQ2tCLEdBQUcsQ0FBQ0Y7UUFDNUMsT0FBT1Y7SUFDUjtJQUVRQyx1QkFBdUJILEtBQVksRUFBRUMsT0FBNEIsRUFBRTtRQUMxRSxNQUFNLEVBQUVjLFNBQVMsRUFBRUMsY0FBYyxFQUFFLEdBQUdmO1FBQ3RDLE1BQU1nQixRQUFRLE9BQU9GLGNBQWMsWUFBWSxPQUFPQSxjQUFjO1FBQ3BFLE1BQU1HLGFBQWEsT0FBT0YsbUJBQW1CO1FBQzdDLE1BQU1WLE1BQU0sSUFBSWIsZ0JBQWdCLENBQUN3QixRQUFRRixVQUFVSSxJQUFJLEdBQUdKO1FBQzFELE1BQU1LLE9BQU9GLGFBQWFGLGlCQUFpQkMsUUFBUUQsaUJBQWlCRDtRQUNwRSxNQUFNYixlQUFlLElBQUlSLG9CQUFvQlksS0FBS2MsTUFBTXBCLE9BQU9rQjtRQUMvRCxPQUFPaEI7SUFDUjtJQUVRRyxpQkFBaUJDLEdBQW9CLEVBQUU7UUFDOUMsTUFBTU8sUUFBUVAsSUFBSU8sS0FBSztRQUN2QixPQUFPLElBQUksQ0FBQ2pCLGFBQWEsQ0FBQ2tCLEdBQUcsQ0FBQ0Q7SUFDL0I7SUFFUUgsZ0JBQWdCSixHQUFvQixFQUFFVixhQUFvQyxFQUFFO1FBQ25GLElBQUksQ0FBQ0EsYUFBYSxDQUFDeUIsR0FBRyxDQUFDZixJQUFJTyxLQUFLLEVBQUVqQjtJQUNuQztBQUNEIn0=
|
package/es6/src/types/errors.js
CHANGED
|
@@ -4,5 +4,3 @@ export class DuplicateScopeError extends Error {
|
|
|
4
4
|
}
|
|
5
5
|
export class RegistrationError extends Error {
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy90eXBlcy9lcnJvcnMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNsYXNzIFJlc29sdmVFcnJvciBleHRlbmRzIEVycm9yIHt9XG5leHBvcnQgY2xhc3MgRHVwbGljYXRlU2NvcGVFcnJvciBleHRlbmRzIEVycm9yIHt9XG5leHBvcnQgY2xhc3MgUmVnaXN0cmF0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7fVxuIl0sIm5hbWVzIjpbIlJlc29sdmVFcnJvciIsIkVycm9yIiwiRHVwbGljYXRlU2NvcGVFcnJvciIsIlJlZ2lzdHJhdGlvbkVycm9yIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLE1BQU1BLHFCQUFxQkM7QUFBTztBQUN6QyxPQUFPLE1BQU1DLDRCQUE0QkQ7QUFBTztBQUNoRCxPQUFPLE1BQU1FLDBCQUEwQkY7QUFBTyJ9
|
package/es6/src/types/index.js
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
+
export * from "./errors.js";
|
|
1
2
|
export * from "./types.js";
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy90eXBlcy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi90eXBlcy5qc1wiO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsYUFBYSJ9
|
package/es6/src/types/types.js
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
1
|
export { };
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy90eXBlcy90eXBlcy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgdHlwZSB7XG5cdENvbnRhaW5lckJ1aWxkZXIsXG5cdElDb250YWluZXIsXG5cdExpZmV0aW1lU2NvcGUsXG5cdFJlc29sdmVSZXF1ZXN0LFxuXHRTY29wZSxcblx0U2VydmljZVByb3ZpZGVyLFxufSBmcm9tIFwiQGRlY29oZXJlL25leHVzL2NvbXBvc2l0aW9uXCI7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsV0FPcUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decohere/crucible",
|
|
3
|
-
"version": "0.0.1-dev.
|
|
3
|
+
"version": "0.0.1-dev.20261105.103",
|
|
4
4
|
"description": "Lightweight dependency injection container with decorator-based wiring",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -10,6 +10,15 @@
|
|
|
10
10
|
"decorators",
|
|
11
11
|
"decohere"
|
|
12
12
|
],
|
|
13
|
+
"homepage": "https://github.com/typesmiths/decohere/tree/main/projects/crucible#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/typesmiths/decohere/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/typesmiths/decohere.git",
|
|
20
|
+
"directory": "projects/crucible"
|
|
21
|
+
},
|
|
13
22
|
"license": "ISC",
|
|
14
23
|
"author": "Typesmiths",
|
|
15
24
|
"type": "module",
|
|
@@ -17,21 +26,18 @@
|
|
|
17
26
|
"exports": {
|
|
18
27
|
".": {
|
|
19
28
|
"types": "./types/src/index.d.ts",
|
|
20
|
-
"import": "./es6/src/index.js"
|
|
21
|
-
"require": "./commonjs/src/index.js"
|
|
29
|
+
"import": "./es6/src/index.js"
|
|
22
30
|
},
|
|
23
31
|
"./decorators": {
|
|
24
32
|
"types": "./types/src/decorators/index.d.ts",
|
|
25
|
-
"import": "./es6/src/decorators/index.js"
|
|
26
|
-
"require": "./commonjs/src/decorators/index.js"
|
|
33
|
+
"import": "./es6/src/decorators/index.js"
|
|
27
34
|
}
|
|
28
35
|
},
|
|
29
36
|
"scripts": {
|
|
30
37
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
31
38
|
},
|
|
32
39
|
"dependencies": {
|
|
33
|
-
"@decohere/
|
|
34
|
-
"@decohere/scribe": "0.0.1-dev.19"
|
|
40
|
+
"@decohere/core": "0.0.1-dev.20261105.103"
|
|
35
41
|
},
|
|
36
42
|
"devDependencies": {}
|
|
37
43
|
}
|
package/types/src/const.d.ts
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
|
+
import type { ServiceKey } from "../models/service-key.js";
|
|
1
2
|
export type InjectionMetadata = Map<number, InjectionToken>;
|
|
2
3
|
export type InjectionToken = {
|
|
3
|
-
key
|
|
4
|
+
/** The key to resolve; without one, the parameter's type is the key. */
|
|
5
|
+
key?: ServiceKey;
|
|
6
|
+
/** Pass `undefined` instead of throwing when nothing is registered for the key. */
|
|
7
|
+
optional?: boolean;
|
|
4
8
|
};
|
|
5
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Bind a constructor parameter to a registration key. Keys match by identity: a class matches only
|
|
11
|
+
* itself (not a string of its name), and a symbol only itself. Prefer the class; use a symbol for an
|
|
12
|
+
* interface or several implementations. `@inject(SomeClass)` also keeps SomeClass's import, which
|
|
13
|
+
* a parameter used only as a type can lose (its run-time type then collapses to `Object`).
|
|
14
|
+
*/
|
|
15
|
+
export declare function inject(key: ServiceKey): (target: object, _propertyKey: string | symbol | undefined, idx: number) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Mark a constructor parameter as optional: when nothing is registered for it, the container
|
|
18
|
+
* passes `undefined` (so a default value applies) instead of throwing.
|
|
19
|
+
*/
|
|
20
|
+
export declare function optional(): (target: object, _propertyKey: string | symbol | undefined, idx: number) => void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Constructable, FunctionType } from "@decohere/core/reflection";
|
|
2
|
+
/**
|
|
3
|
+
* What a service is registered and resolved under, compared by identity: the class (or factory)
|
|
4
|
+
* itself, a symbol, or a string. A string never matches a class with that name, and two symbols
|
|
5
|
+
* with the same description are different keys.
|
|
6
|
+
*/
|
|
7
|
+
export type ServiceKey = string | symbol | Constructable | FunctionType;
|
|
8
|
+
/** A readable name for a key, for error messages. */
|
|
9
|
+
export declare function describeKey(key: ServiceKey): string;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { Constructable, FunctionType } from "@decohere/
|
|
1
|
+
import type { Constructable, FunctionType } from "@decohere/core/reflection";
|
|
2
2
|
import type { Scope } from "../types/types.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { ServiceKey } from "./service-key.js";
|
|
4
4
|
export declare class ServiceRegistration {
|
|
5
|
-
key:
|
|
5
|
+
key: ServiceKey;
|
|
6
6
|
scope: Scope;
|
|
7
7
|
type: Constructable | FunctionType | object;
|
|
8
8
|
isInstance: boolean;
|
|
9
|
-
constructor(key:
|
|
9
|
+
constructor(key: ServiceKey, type: Constructable | FunctionType | object, scope: Scope, isInstance: boolean);
|
|
10
|
+
/** Same class, or the same instance object. */
|
|
10
11
|
isEqual(other: ServiceRegistration): boolean;
|
|
11
12
|
}
|
|
@@ -2,30 +2,41 @@ import type { IContainer, ResolveRequest } from "../types/types.js";
|
|
|
2
2
|
import { ServiceRegistry } from "./service-registry.js";
|
|
3
3
|
type CrucibleOptions = {
|
|
4
4
|
key?: string;
|
|
5
|
-
|
|
5
|
+
parent?: Container;
|
|
6
6
|
serviceRegistry: ServiceRegistry;
|
|
7
7
|
};
|
|
8
|
-
export declare class
|
|
8
|
+
export declare class Container implements IContainer {
|
|
9
9
|
key: string;
|
|
10
10
|
protected instances: Map<unknown, object>;
|
|
11
11
|
private serviceRegistry;
|
|
12
|
+
private parent?;
|
|
12
13
|
private rootScope;
|
|
13
14
|
private scopes;
|
|
14
|
-
private logger;
|
|
15
15
|
private isDisposed;
|
|
16
16
|
constructor(options?: CrucibleOptions);
|
|
17
17
|
resolveMany<T extends object = object>(resolveRequest: ResolveRequest<T>): T[];
|
|
18
|
+
/** Throws {@link ResolveError} when nothing is registered for the key. */
|
|
18
19
|
resolve<T extends object | object[]>(resolveRequest: ResolveRequest<T>): T;
|
|
19
|
-
|
|
20
|
+
private resolveAll;
|
|
21
|
+
private resolveOne;
|
|
22
|
+
beginScope(name?: string): Container;
|
|
20
23
|
[Symbol.dispose](): void;
|
|
21
24
|
[Symbol.asyncDispose](): Promise<void>;
|
|
22
25
|
private disposeSync;
|
|
23
26
|
private disposeAsync;
|
|
24
|
-
private getRegistrationFrom;
|
|
25
27
|
private resolveRegistration;
|
|
28
|
+
private assertNoCycle;
|
|
29
|
+
/**
|
|
30
|
+
* A singleton lives for the whole process, so a request-scoped service it depends on (directly
|
|
31
|
+
* or through transients) would be created once and then shared by every request, e.g. one
|
|
32
|
+
* QueryRunner for the life of the process. The container's own lifetime scope is exempt: a
|
|
33
|
+
* singleton asking for it gets the root, which is the scope it lives in.
|
|
34
|
+
*/
|
|
35
|
+
private assertNotCaptive;
|
|
26
36
|
private getOrCreateInstance;
|
|
27
37
|
private createInstance;
|
|
28
38
|
private resolveDependencies;
|
|
39
|
+
private releaseScope;
|
|
29
40
|
private registerLifetimeScope;
|
|
30
41
|
}
|
|
31
42
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
1
|
+
export * from "./container.js";
|
|
2
|
+
export * from "./service-container-builder.js";
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import type { Constructable, FunctionType } from "@decohere/
|
|
1
|
+
import type { Constructable, FunctionType } from "@decohere/core/reflection";
|
|
2
2
|
import type { ServiceRegistration } from "../models/service-registration.model.js";
|
|
3
|
-
import type { ContainerBuilder, Scope } from "../types/types.js";
|
|
4
|
-
import {
|
|
3
|
+
import type { ContainerBuilder, ContainerRegistrar, Scope } from "../types/types.js";
|
|
4
|
+
import { Container } from "./container.js";
|
|
5
5
|
import { ServiceRegistry } from "./service-registry.js";
|
|
6
6
|
type ContainerBuilderOptions = {
|
|
7
7
|
serviceRegistry: ServiceRegistry;
|
|
8
8
|
};
|
|
9
|
-
export declare class
|
|
9
|
+
export declare class ServiceContainerBuilder implements ContainerBuilder {
|
|
10
10
|
private serviceRegistry;
|
|
11
11
|
constructor(options?: ContainerBuilderOptions);
|
|
12
|
+
get override(): ContainerRegistrar;
|
|
12
13
|
registerType(type: Constructable, scope?: Scope): ServiceRegistration;
|
|
13
14
|
registerTypes(...types: Constructable[]): ServiceRegistration[];
|
|
14
15
|
registerTypes(scope: Scope, ...types: Constructable[]): ServiceRegistration[];
|
|
@@ -21,6 +22,9 @@ export declare class CrucibleBuilder implements ContainerBuilder {
|
|
|
21
22
|
registerRequestScoped<T>(key: string | symbol, type: () => T): ServiceRegistration;
|
|
22
23
|
registerRequestScoped(key: string | symbol, type: Constructable): ServiceRegistration;
|
|
23
24
|
registerRequestScoped(type: Constructable): ServiceRegistration;
|
|
24
|
-
build():
|
|
25
|
+
build(): Container;
|
|
26
|
+
private register;
|
|
27
|
+
private registerMany;
|
|
28
|
+
private createRegistrar;
|
|
25
29
|
}
|
|
26
30
|
export {};
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import type { Constructable, FunctionType } from "@decohere/
|
|
1
|
+
import type { Constructable, FunctionType } from "@decohere/core/reflection";
|
|
2
|
+
import { type ServiceKey } from "../models/service-key.js";
|
|
2
3
|
import { ServiceRegistration } from "../models/service-registration.model.js";
|
|
3
4
|
import type { Scope } from "../types/types.js";
|
|
4
5
|
export type RegisterTypeOptions = {
|
|
5
|
-
typeOrKey:
|
|
6
|
+
typeOrKey: ServiceKey;
|
|
6
7
|
typeOrInstance?: Constructable | FunctionType | object;
|
|
8
|
+
override?: boolean;
|
|
7
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* Registrations by key. A scope's registry holds only what the scope adds (its own lifetime
|
|
12
|
+
* scope) and looks everything else up in its parent, so beginning a scope costs the same however
|
|
13
|
+
* many services are registered.
|
|
14
|
+
*/
|
|
8
15
|
export declare class ServiceRegistry {
|
|
9
|
-
private
|
|
16
|
+
#private;
|
|
10
17
|
constructor(parent?: ServiceRegistry);
|
|
11
18
|
registerType(scope: Scope, options: RegisterTypeOptions): ServiceRegistration;
|
|
12
|
-
|
|
19
|
+
replaceType(scope: Scope, options: RegisterTypeOptions): ServiceRegistration;
|
|
20
|
+
getRegistration(key: ServiceKey): ServiceRegistration[] | undefined;
|
|
13
21
|
private createRegistrationFrom;
|
|
14
|
-
private getRegistrations;
|
|
15
|
-
private setRegistration;
|
|
16
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { ContainerBuilder, IContainer, LifetimeScope, ResolveRequest, Scope, ServiceProvider, } from "@decohere/
|
|
1
|
+
export type { ContainerBuilder, ContainerRegistrar, IContainer, LifetimeScope, ResolveRequest, Scope, ServiceProvider, } from "@decohere/core/composition";
|
package/commonjs/src/const.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get CrucibleMeta () {
|
|
13
|
-
return CrucibleMeta;
|
|
14
|
-
},
|
|
15
|
-
get LifetimeScopeToken () {
|
|
16
|
-
return LifetimeScopeToken;
|
|
17
|
-
},
|
|
18
|
-
get Scopes () {
|
|
19
|
-
return Scopes;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
const Crucible = "Crucible";
|
|
23
|
-
const LifetimeScopeToken = Symbol("LifetimeScope");
|
|
24
|
-
const CrucibleMeta = {
|
|
25
|
-
injecttoken: `${Crucible}:injecttoken`
|
|
26
|
-
};
|
|
27
|
-
const Scopes = {
|
|
28
|
-
request: "request",
|
|
29
|
-
singleton: "single-instance",
|
|
30
|
-
transient: "transient"
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NydWNpYmxlL3NyYy9jb25zdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFNjb3BlIH0gZnJvbSBcIi4vdHlwZXMvdHlwZXMuanNcIjtcblxuY29uc3QgQ3J1Y2libGUgPSBcIkNydWNpYmxlXCI7XG50eXBlIENydWNpYmxlTWV0YSA9IFwiaW5qZWN0dG9rZW5cIjtcblxuZXhwb3J0IGNvbnN0IExpZmV0aW1lU2NvcGVUb2tlbiA9IFN5bWJvbChcIkxpZmV0aW1lU2NvcGVcIik7XG5cbmV4cG9ydCBjb25zdCBDcnVjaWJsZU1ldGEgPSB7XG5cdGluamVjdHRva2VuOiBgJHtDcnVjaWJsZX06aW5qZWN0dG9rZW5gLFxufSBzYXRpc2ZpZXMgUmVjb3JkPENydWNpYmxlTWV0YSwgc3RyaW5nPjtcblxuZXhwb3J0IGNvbnN0IFNjb3BlcyA9IHtcblx0cmVxdWVzdDogXCJyZXF1ZXN0XCIsXG5cdHNpbmdsZXRvbjogXCJzaW5nbGUtaW5zdGFuY2VcIixcblx0dHJhbnNpZW50OiBcInRyYW5zaWVudFwiLFxufSBzYXRpc2ZpZXMgUmVjb3JkPHN0cmluZywgU2NvcGU+O1xuIl0sIm5hbWVzIjpbIkNydWNpYmxlTWV0YSIsIkxpZmV0aW1lU2NvcGVUb2tlbiIsIlNjb3BlcyIsIkNydWNpYmxlIiwiU3ltYm9sIiwiaW5qZWN0dG9rZW4iLCJyZXF1ZXN0Iiwic2luZ2xldG9uIiwidHJhbnNpZW50Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztRQU9hQTtlQUFBQTs7UUFGQUM7ZUFBQUE7O1FBTUFDO2VBQUFBOzs7QUFUYixNQUFNQyxXQUFXO0FBR1YsTUFBTUYscUJBQXFCRyxPQUFPO0FBRWxDLE1BQU1KLGVBQWU7SUFDM0JLLGFBQWEsR0FBR0YsU0FBUyxZQUFZLENBQUM7QUFDdkM7QUFFTyxNQUFNRCxTQUFTO0lBQ3JCSSxTQUFTO0lBQ1RDLFdBQVc7SUFDWEMsV0FBVztBQUNaIn0=
|