@decohere/crucible 0.0.1-dev.115 → 0.0.1-dev.117
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/README.md +24 -24
- package/commonjs/src/const.js +5 -5
- package/commonjs/src/decorators/inject.decorator.js +3 -3
- package/commonjs/src/services/{crucible.js → container.js} +6 -6
- package/commonjs/src/services/index.js +2 -2
- package/commonjs/src/services/{crucible-builder.js → service-container-builder.js} +5 -5
- package/es6/src/const.js +3 -3
- package/es6/src/decorators/inject.decorator.js +4 -4
- package/es6/src/services/{crucible.js → container.js} +5 -5
- package/es6/src/services/index.js +2 -2
- package/es6/src/services/{crucible-builder.js → service-container-builder.js} +3 -3
- package/package.json +2 -2
- package/types/src/const.d.ts +1 -1
- package/types/src/models/service-key.d.ts +1 -1
- package/types/src/models/service-registration.model.d.ts +1 -1
- package/types/src/services/{crucible.d.ts → container.d.ts} +3 -3
- package/types/src/services/index.d.ts +2 -2
- package/types/src/services/{crucible-builder.d.ts → service-container-builder.d.ts} +4 -4
- package/types/src/services/service-registry.d.ts +1 -1
- package/types/src/types/types.d.ts +1 -1
package/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# @decohere/crucible
|
|
2
2
|
|
|
3
|
-
Lightweight dependency injection for Decohere. Register classes (or tokens) on a `
|
|
3
|
+
Lightweight dependency injection for Decohere. Register classes (or tokens) on a `ServiceContainerBuilder`, `build()` a container, then `resolve()` graphs of constructor-injected services.
|
|
4
4
|
|
|
5
|
-
Higher layers (for example
|
|
5
|
+
Higher layers (for example `@decohere/http`'s `Builder.withServices`) register on a `ServiceContainerBuilder`. You can also build and resolve from a container yourself.
|
|
6
6
|
|
|
7
7
|
## When to use
|
|
8
8
|
|
|
9
|
-
| Use
|
|
9
|
+
| Use `@decohere/crucible` | Do not use it |
|
|
10
10
|
|---|---|
|
|
11
|
-
| Constructor-injected services and controllers | Replacing
|
|
11
|
+
| Constructor-injected services and controllers | Replacing the HTTP, config or data packages — those compose *on top of* the container |
|
|
12
12
|
| Tokens for interfaces, config objects, and “many of this kind” | Auto-scanning folders or Nest-style modules (not in this package) |
|
|
13
13
|
| Request / singleton / transient lifetimes and `using` disposal | Compile-time graph checking (the graph is checked when a service is first resolved) |
|
|
14
14
|
|
|
@@ -19,7 +19,7 @@ pnpm add @decohere/crucible
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
|
-
import {
|
|
22
|
+
import { ServiceContainerBuilder, LifetimeScopeToken, Scopes } from "@decohere/crucible";
|
|
23
23
|
import { inject, injectable } from "@decohere/crucible/decorators";
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -34,13 +34,13 @@ Decorator metadata is required. Enable it in `tsconfig.json` (the Decohere scaff
|
|
|
34
34
|
}
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
`@decohere/
|
|
37
|
+
`@decohere/core/reflection` loads `reflect-metadata`. Import `@decohere/crucible` (or `@decohere/core`) before constructing decorated classes.
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
41
|
## Constructor injection — `@inject` is usually unnecessary
|
|
42
42
|
|
|
43
|
-
If the constructor parameter is a **concrete class**,
|
|
43
|
+
If the constructor parameter is a **concrete class**, the container reads `design:paramtypes` and resolves that class. Mark the *consumer* `@injectable()` so TypeScript/SWC emit that metadata. Do **not** add `@inject` for that parameter.
|
|
44
44
|
|
|
45
45
|
```ts
|
|
46
46
|
import { injectable } from "@decohere/crucible/decorators";
|
|
@@ -53,9 +53,9 @@ export class HelloController {
|
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
```ts
|
|
56
|
-
import {
|
|
56
|
+
import { ServiceContainerBuilder } from "@decohere/crucible";
|
|
57
57
|
|
|
58
|
-
const builder = new
|
|
58
|
+
const builder = new ServiceContainerBuilder();
|
|
59
59
|
builder.registerSingleton(SampleService);
|
|
60
60
|
builder.registerRequestScoped(HelloController);
|
|
61
61
|
const container = builder.build();
|
|
@@ -68,7 +68,7 @@ const hello = scope.resolve(HelloController);
|
|
|
68
68
|
|
|
69
69
|
### Do not `import type` injected classes
|
|
70
70
|
|
|
71
|
-
`import type` is erased at compile time. `emitDecoratorMetadata` then records `Object` (or nothing) instead of the constructor.
|
|
71
|
+
`import type` is erased at compile time. `emitDecoratorMetadata` then records `Object` (or nothing) instead of the constructor. The container cannot tell what to inject and **throws `ResolveError`** when the consumer is resolved, naming the parameter and telling you to add `@inject`.
|
|
72
72
|
|
|
73
73
|
```ts
|
|
74
74
|
// Wrong — SampleService does not exist at runtime, paramtypes collapse to Object
|
|
@@ -84,7 +84,7 @@ Linters that prefer type-only imports (`import type` / `import { type X }`) will
|
|
|
84
84
|
|
|
85
85
|
```ts
|
|
86
86
|
// oxlint-disable-next-line typescript/consistent-type-imports -- constructor injection needs the class at runtime
|
|
87
|
-
import { Workspace } from "@decohere/
|
|
87
|
+
import { Workspace } from "@decohere/workspace";
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
That pattern is used throughout Forge (`Build`, `Clean`, …). Same idea applies to ESLint `consistent-type-imports` or equivalent.
|
|
@@ -133,7 +133,7 @@ builder.registerSingleton(SampleStoreToken, store);
|
|
|
133
133
|
|
|
134
134
|
## Registration and lifetimes
|
|
135
135
|
|
|
136
|
-
Keys match by **identity** ([ADR 0013](../../docs/adr/0013-
|
|
136
|
+
Keys match by **identity** ([ADR 0013](../../docs/adr/0013-container-keys-and-lifetimes.md)): a class matches only itself, a symbol only itself, a string only an equal string. So `resolve("SampleService")` does not find `registerSingleton(SampleService)`, `Symbol("TokenService")` does not collide with a class `TokenService`, two classes with the same name in different modules stay apart, and minified class names still work.
|
|
137
137
|
|
|
138
138
|
Registering the same class (or the same type on a token) twice **throws** `RegistrationError` — silent last-wins hides accidental double-registers. Replace it explicitly:
|
|
139
139
|
|
|
@@ -169,7 +169,7 @@ builder.registerTransient(Token, Helper);
|
|
|
169
169
|
|
|
170
170
|
`registerType(type, scope?)` and `registerTypes(...)` are the same registrations without the lifetime in the method name (default **transient**). `Scopes.singleton` is the string `"single-instance"`.
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
HTTP (`@decohere/http`): controllers are **request-scoped** (one per request). Services are usually **singletons**.
|
|
173
173
|
|
|
174
174
|
`registerSingleton(Class, instance)` binds an existing object under the class. The CLI does this for the workspace:
|
|
175
175
|
|
|
@@ -226,7 +226,7 @@ await using scope = container.beginScope("req-2");
|
|
|
226
226
|
- Disposing a parent does **not** dispose child scopes. Dispose the scope you created.
|
|
227
227
|
- Singletons are cached on the root container and shared with nested scopes. Resolving a singleton after the root is disposed throws.
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
`App.dispose` (`@decohere/http`) (Flux HMR / SIGINT) disposes the **root** container, then Scribe. Implement `Symbol.asyncDispose` (or `Symbol.dispose`) on long-lived services — sockets, pools, timers. Only **constructed** instances are disposed (resolve them at boot; transients are not cached). `export default app` is the composition-root contract; do not wrap it for extra teardown.
|
|
230
230
|
|
|
231
231
|
The current scope is always registered as `LifetimeScopeToken`:
|
|
232
232
|
|
|
@@ -249,7 +249,7 @@ builder.registerRequestScoped("connection", () => createConnection());
|
|
|
249
249
|
const connection = container.resolve("connection");
|
|
250
250
|
```
|
|
251
251
|
|
|
252
|
-
Arrow factories are called as functions (not `new`). Use them when construction needs arguments
|
|
252
|
+
Arrow factories are called as functions (not `new`). Use them when construction needs arguments the container should not know about.
|
|
253
253
|
|
|
254
254
|
### Optional / missing dependencies
|
|
255
255
|
|
|
@@ -266,11 +266,11 @@ export class App {
|
|
|
266
266
|
}
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
-
###
|
|
269
|
+
### HTTP apps
|
|
270
270
|
|
|
271
271
|
```ts
|
|
272
|
-
import { Builder } from "@decohere/
|
|
273
|
-
import { FastifyProvider } from "@decohere/
|
|
272
|
+
import { Builder } from "@decohere/http";
|
|
273
|
+
import { FastifyProvider } from "@decohere/http/providers";
|
|
274
274
|
import { SampleService } from "./services/sample.service.js";
|
|
275
275
|
import { HelloController } from "./controllers/hello.controller.js";
|
|
276
276
|
|
|
@@ -287,10 +287,10 @@ await Builder.create()
|
|
|
287
287
|
|
|
288
288
|
### Tests
|
|
289
289
|
|
|
290
|
-
Prefer constructing the subject with explicit fakes when you do not need the container. Use `
|
|
290
|
+
Prefer constructing the subject with explicit fakes when you do not need the container. Use `ServiceContainerBuilder` when the test *is* the wiring (scopes, tokens, many-implementations).
|
|
291
291
|
|
|
292
292
|
```ts
|
|
293
|
-
const builder = new
|
|
293
|
+
const builder = new ServiceContainerBuilder();
|
|
294
294
|
builder.registerSingleton(SampleService, fakeSample);
|
|
295
295
|
builder.registerRequestScoped(HelloController);
|
|
296
296
|
const container = builder.build();
|
|
@@ -298,7 +298,7 @@ using scope = container.beginScope("test");
|
|
|
298
298
|
const hello = scope.resolve(HelloController);
|
|
299
299
|
```
|
|
300
300
|
|
|
301
|
-
To assert constructor arguments under DI, use `spyOnConstructor` from `@decohere/
|
|
301
|
+
To assert constructor arguments under DI, use `spyOnConstructor` from `@decohere/core/testing` — a bare `vi.spyOn` / `vi.fn` constructor drops `design:paramtypes`. See [Asserting DI constructor arguments](../../docs/testing/how-tos/vitest-constructor-spy-with-di.md).
|
|
302
302
|
|
|
303
303
|
---
|
|
304
304
|
|
|
@@ -308,8 +308,8 @@ To assert constructor arguments under DI, use `spyOnConstructor` from `@decohere
|
|
|
308
308
|
|
|
309
309
|
| Export | Role |
|
|
310
310
|
|---|---|
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
311
|
+
| `ServiceContainerBuilder` | Fluent registration; `build()` → `Container` |
|
|
312
|
+
| `Container` | The container: `resolve`, `resolveMany`, `beginScope`, `Symbol.dispose` / `Symbol.asyncDispose` |
|
|
313
313
|
| `IContainer` / `LifetimeScope` / `ContainerBuilder` / `ServiceProvider` | Composition interfaces |
|
|
314
314
|
| `Scopes` | `{ request, singleton: "single-instance", transient }` |
|
|
315
315
|
| `LifetimeScopeToken` | Symbol for the current scope |
|
|
@@ -349,6 +349,6 @@ To assert constructor arguments under DI, use `spyOnConstructor` from `@decohere
|
|
|
349
349
|
|
|
350
350
|
| Package | Role |
|
|
351
351
|
|---|---|
|
|
352
|
-
| [`@decohere/
|
|
352
|
+
| [`@decohere/core`](../core) | Reflection helpers for `design:paramtypes` (`getMeta`, `isConstructable`, …) |
|
|
353
353
|
|
|
354
354
|
Layering: [architecture](../../docs/architecture/).
|
package/commonjs/src/const.js
CHANGED
|
@@ -9,8 +9,8 @@ function _export(target, all) {
|
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
-
get
|
|
13
|
-
return
|
|
12
|
+
get ContainerMeta () {
|
|
13
|
+
return ContainerMeta;
|
|
14
14
|
},
|
|
15
15
|
get LifetimeScopeToken () {
|
|
16
16
|
return LifetimeScopeToken;
|
|
@@ -19,10 +19,10 @@ _export(exports, {
|
|
|
19
19
|
return Scopes;
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
|
-
const
|
|
22
|
+
const Container = "Container";
|
|
23
23
|
const LifetimeScopeToken = Symbol("LifetimeScope");
|
|
24
|
-
const
|
|
25
|
-
injecttoken: `${
|
|
24
|
+
const ContainerMeta = {
|
|
25
|
+
injecttoken: `${Container}:injecttoken`
|
|
26
26
|
};
|
|
27
27
|
const Scopes = {
|
|
28
28
|
request: "request",
|
|
@@ -16,7 +16,7 @@ _export(exports, {
|
|
|
16
16
|
return optional;
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
|
-
const _reflection = require("@decohere/
|
|
19
|
+
const _reflection = require("@decohere/core/reflection");
|
|
20
20
|
const _const = require("../const.js");
|
|
21
21
|
function inject(key) {
|
|
22
22
|
return updateToken((token)=>({
|
|
@@ -33,8 +33,8 @@ function optional() {
|
|
|
33
33
|
function updateToken(update) {
|
|
34
34
|
return (target, _propertyKey, idx)=>{
|
|
35
35
|
// Copy: the metadata can be inherited from a base class, which must not change.
|
|
36
|
-
const metadata = new Map((0, _reflection.getMeta)(_const.
|
|
36
|
+
const metadata = new Map((0, _reflection.getMeta)(_const.ContainerMeta.injecttoken, target));
|
|
37
37
|
metadata.set(idx, update(metadata.get(idx)));
|
|
38
|
-
(0, _reflection.defineMeta)(_const.
|
|
38
|
+
(0, _reflection.defineMeta)(_const.ContainerMeta.injecttoken, metadata, target);
|
|
39
39
|
};
|
|
40
40
|
}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
Object.defineProperty(exports, "
|
|
5
|
+
Object.defineProperty(exports, "Container", {
|
|
6
6
|
enumerable: true,
|
|
7
7
|
get: function() {
|
|
8
|
-
return
|
|
8
|
+
return Container;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
const _reflection = require("@decohere/
|
|
11
|
+
const _reflection = require("@decohere/core/reflection");
|
|
12
12
|
const _const = require("../const.js");
|
|
13
13
|
const _servicekey = require("../models/service-key.js");
|
|
14
14
|
const _errors = require("../types/errors.js");
|
|
@@ -22,7 +22,7 @@ function describePath(path, last) {
|
|
|
22
22
|
]
|
|
23
23
|
].map(_servicekey.describeKey).join(" → ");
|
|
24
24
|
}
|
|
25
|
-
class
|
|
25
|
+
class Container {
|
|
26
26
|
key;
|
|
27
27
|
instances = new Map();
|
|
28
28
|
serviceRegistry;
|
|
@@ -66,7 +66,7 @@ class Crucible {
|
|
|
66
66
|
if (name != null && this.scopes.has(name)) {
|
|
67
67
|
throw new _errors.DuplicateScopeError(`Cannot create duplicate scope. Scope with ${name} is already created and has not been disposed.`);
|
|
68
68
|
}
|
|
69
|
-
const scope = new
|
|
69
|
+
const scope = new Container({
|
|
70
70
|
key: name,
|
|
71
71
|
serviceRegistry: this.serviceRegistry,
|
|
72
72
|
parent: this
|
|
@@ -181,7 +181,7 @@ class Crucible {
|
|
|
181
181
|
}
|
|
182
182
|
resolveDependencies(type, path) {
|
|
183
183
|
const params = (0, _reflection.getMeta)(_reflection.ReflectionMeta.paramtypes, type) ?? [];
|
|
184
|
-
const injectTokens = (0, _reflection.getMeta)(_const.
|
|
184
|
+
const injectTokens = (0, _reflection.getMeta)(_const.ContainerMeta.injecttoken, type) ?? new Map();
|
|
185
185
|
return params.map((param, index)=>{
|
|
186
186
|
const token = injectTokens.get(index);
|
|
187
187
|
const key = token?.key ?? param;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
_export_star(require("./
|
|
6
|
-
_export_star(require("./
|
|
5
|
+
_export_star(require("./container.js"), exports);
|
|
6
|
+
_export_star(require("./service-container-builder.js"), exports);
|
|
7
7
|
function _export_star(from, to) {
|
|
8
8
|
Object.keys(from).forEach(function(k) {
|
|
9
9
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
Object.defineProperty(exports, "
|
|
5
|
+
Object.defineProperty(exports, "ServiceContainerBuilder", {
|
|
6
6
|
enumerable: true,
|
|
7
7
|
get: function() {
|
|
8
|
-
return
|
|
8
|
+
return ServiceContainerBuilder;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _const = require("../const.js");
|
|
12
|
-
const
|
|
12
|
+
const _container = require("./container.js");
|
|
13
13
|
const _serviceregistry = require("./service-registry.js");
|
|
14
|
-
class
|
|
14
|
+
class ServiceContainerBuilder {
|
|
15
15
|
serviceRegistry;
|
|
16
16
|
constructor(options){
|
|
17
17
|
this.serviceRegistry = options?.serviceRegistry ?? new _serviceregistry.ServiceRegistry();
|
|
@@ -35,7 +35,7 @@ class CrucibleBuilder {
|
|
|
35
35
|
return this.register(false)(_const.Scopes.request)(typeOrKey, type);
|
|
36
36
|
}
|
|
37
37
|
build() {
|
|
38
|
-
return new
|
|
38
|
+
return new _container.Container({
|
|
39
39
|
serviceRegistry: this.serviceRegistry
|
|
40
40
|
});
|
|
41
41
|
}
|
package/es6/src/const.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const
|
|
1
|
+
const Container = "Container";
|
|
2
2
|
export const LifetimeScopeToken = Symbol("LifetimeScope");
|
|
3
|
-
export const
|
|
4
|
-
injecttoken: `${
|
|
3
|
+
export const ContainerMeta = {
|
|
4
|
+
injecttoken: `${Container}:injecttoken`
|
|
5
5
|
};
|
|
6
6
|
export const Scopes = {
|
|
7
7
|
request: "request",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineMeta, getMeta } from "@decohere/
|
|
2
|
-
import {
|
|
1
|
+
import { defineMeta, getMeta } from "@decohere/core/reflection";
|
|
2
|
+
import { ContainerMeta } from "../const.js";
|
|
3
3
|
/**
|
|
4
4
|
* Bind a constructor parameter to a registration key. Keys match by identity: a class matches only
|
|
5
5
|
* itself (not a string of its name), and a symbol only itself. Prefer the class; use a symbol for an
|
|
@@ -23,8 +23,8 @@ import { CrucibleMeta } from "../const.js";
|
|
|
23
23
|
function updateToken(update) {
|
|
24
24
|
return (target, _propertyKey, idx)=>{
|
|
25
25
|
// Copy: the metadata can be inherited from a base class, which must not change.
|
|
26
|
-
const metadata = new Map(getMeta(
|
|
26
|
+
const metadata = new Map(getMeta(ContainerMeta.injecttoken, target));
|
|
27
27
|
metadata.set(idx, update(metadata.get(idx)));
|
|
28
|
-
defineMeta(
|
|
28
|
+
defineMeta(ContainerMeta.injecttoken, metadata, target);
|
|
29
29
|
};
|
|
30
30
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getMeta, isArrayType, isConstructable, ReflectionMeta } from "@decohere/
|
|
2
|
-
import {
|
|
1
|
+
import { getMeta, isArrayType, isConstructable, ReflectionMeta } from "@decohere/core/reflection";
|
|
2
|
+
import { ContainerMeta, LifetimeScopeToken, Scopes } from "../const.js";
|
|
3
3
|
import { describeKey } from "../models/service-key.js";
|
|
4
4
|
import { DuplicateScopeError, ResolveError } from "../types/errors.js";
|
|
5
5
|
import { ServiceRegistry } from "./service-registry.js";
|
|
@@ -12,7 +12,7 @@ function describePath(path, last) {
|
|
|
12
12
|
]
|
|
13
13
|
].map(describeKey).join(" → ");
|
|
14
14
|
}
|
|
15
|
-
export class
|
|
15
|
+
export class Container {
|
|
16
16
|
key;
|
|
17
17
|
instances = new Map();
|
|
18
18
|
serviceRegistry;
|
|
@@ -56,7 +56,7 @@ export class Crucible {
|
|
|
56
56
|
if (name != null && this.scopes.has(name)) {
|
|
57
57
|
throw new DuplicateScopeError(`Cannot create duplicate scope. Scope with ${name} is already created and has not been disposed.`);
|
|
58
58
|
}
|
|
59
|
-
const scope = new
|
|
59
|
+
const scope = new Container({
|
|
60
60
|
key: name,
|
|
61
61
|
serviceRegistry: this.serviceRegistry,
|
|
62
62
|
parent: this
|
|
@@ -171,7 +171,7 @@ export class Crucible {
|
|
|
171
171
|
}
|
|
172
172
|
resolveDependencies(type, path) {
|
|
173
173
|
const params = getMeta(ReflectionMeta.paramtypes, type) ?? [];
|
|
174
|
-
const injectTokens = getMeta(
|
|
174
|
+
const injectTokens = getMeta(ContainerMeta.injecttoken, type) ?? new Map();
|
|
175
175
|
return params.map((param, index)=>{
|
|
176
176
|
const token = injectTokens.get(index);
|
|
177
177
|
const key = token?.key ?? param;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
1
|
+
export * from "./container.js";
|
|
2
|
+
export * from "./service-container-builder.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Scopes } from "../const.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Container } from "./container.js";
|
|
3
3
|
import { ServiceRegistry } from "./service-registry.js";
|
|
4
|
-
export class
|
|
4
|
+
export class ServiceContainerBuilder {
|
|
5
5
|
serviceRegistry;
|
|
6
6
|
constructor(options){
|
|
7
7
|
this.serviceRegistry = options?.serviceRegistry ?? new ServiceRegistry();
|
|
@@ -25,7 +25,7 @@ export class CrucibleBuilder {
|
|
|
25
25
|
return this.register(false)(Scopes.request)(typeOrKey, type);
|
|
26
26
|
}
|
|
27
27
|
build() {
|
|
28
|
-
return new
|
|
28
|
+
return new Container({
|
|
29
29
|
serviceRegistry: this.serviceRegistry
|
|
30
30
|
});
|
|
31
31
|
}
|
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.117",
|
|
4
4
|
"description": "Lightweight dependency injection container with decorator-based wiring",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@decohere/
|
|
33
|
+
"@decohere/core": "0.0.1-dev.117"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {}
|
|
36
36
|
}
|
package/types/src/const.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Constructable, FunctionType } from "@decohere/
|
|
1
|
+
import type { Constructable, FunctionType } from "@decohere/core/reflection";
|
|
2
2
|
/**
|
|
3
3
|
* What a service is registered and resolved under, compared by identity: the class (or factory)
|
|
4
4
|
* itself, a symbol, or a string. A string never matches a class with that name, and two symbols
|
|
@@ -1,4 +1,4 @@
|
|
|
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
3
|
import type { ServiceKey } from "./service-key.js";
|
|
4
4
|
export declare class ServiceRegistration {
|
|
@@ -2,10 +2,10 @@ 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
|
-
parent?:
|
|
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;
|
|
@@ -19,7 +19,7 @@ export declare class Crucible implements IContainer {
|
|
|
19
19
|
resolve<T extends object | object[]>(resolveRequest: ResolveRequest<T>): T;
|
|
20
20
|
private resolveAll;
|
|
21
21
|
private resolveOne;
|
|
22
|
-
beginScope(name?: string):
|
|
22
|
+
beginScope(name?: string): Container;
|
|
23
23
|
[Symbol.dispose](): void;
|
|
24
24
|
[Symbol.asyncDispose](): Promise<void>;
|
|
25
25
|
private disposeSync;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
1
|
+
export * from "./container.js";
|
|
2
|
+
export * from "./service-container-builder.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
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
3
|
import type { ContainerBuilder, ContainerRegistrar, Scope } from "../types/types.js";
|
|
4
|
-
import {
|
|
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
12
|
get override(): ContainerRegistrar;
|
|
@@ -22,7 +22,7 @@ export declare class CrucibleBuilder implements ContainerBuilder {
|
|
|
22
22
|
registerRequestScoped<T>(key: string | symbol, type: () => T): ServiceRegistration;
|
|
23
23
|
registerRequestScoped(key: string | symbol, type: Constructable): ServiceRegistration;
|
|
24
24
|
registerRequestScoped(type: Constructable): ServiceRegistration;
|
|
25
|
-
build():
|
|
25
|
+
build(): Container;
|
|
26
26
|
private register;
|
|
27
27
|
private registerMany;
|
|
28
28
|
private createRegistrar;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Constructable, FunctionType } from "@decohere/
|
|
1
|
+
import type { Constructable, FunctionType } from "@decohere/core/reflection";
|
|
2
2
|
import { type ServiceKey } from "../models/service-key.js";
|
|
3
3
|
import { ServiceRegistration } from "../models/service-registration.model.js";
|
|
4
4
|
import type { Scope } from "../types/types.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { ContainerBuilder, ContainerRegistrar, IContainer, LifetimeScope, ResolveRequest, Scope, ServiceProvider, } from "@decohere/
|
|
1
|
+
export type { ContainerBuilder, ContainerRegistrar, IContainer, LifetimeScope, ResolveRequest, Scope, ServiceProvider, } from "@decohere/core/composition";
|