@codefast/di 0.3.14-canary.1 → 0.3.14-canary.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +42 -26
- package/dist/binding-scope.d.mts +11 -0
- package/dist/binding-scope.mjs +19 -0
- package/dist/binding-select.d.mts +8 -26
- package/dist/binding-select.mjs +56 -49
- package/dist/binding.d.mts +107 -335
- package/dist/binding.mjs +19 -332
- package/dist/constraints.d.mts +11 -29
- package/dist/constraints.mjs +32 -36
- package/dist/constructor-type.d.mts +17 -0
- package/dist/constructor-type.mjs +1 -0
- package/dist/container.d.mts +43 -122
- package/dist/container.mjs +667 -482
- package/dist/decorators/inject.d.mts +19 -50
- package/dist/decorators/inject.mjs +131 -93
- package/dist/decorators/injectable.d.mts +16 -37
- package/dist/decorators/injectable.mjs +47 -66
- package/dist/decorators/lifecycle-decorators.d.mts +2 -22
- package/dist/decorators/lifecycle-decorators.mjs +81 -37
- package/dist/dependency-graph.d.mts +24 -54
- package/dist/dependency-graph.mjs +51 -153
- package/dist/environment.d.mts +38 -12
- package/dist/environment.mjs +82 -16
- package/dist/errors.d.mts +70 -189
- package/dist/errors.mjs +92 -219
- package/dist/graph-adapters/cytoscape.d.mts +21 -7
- package/dist/graph-adapters/cytoscape.mjs +18 -35
- package/dist/graph-adapters/dot.d.mts +1 -4
- package/dist/graph-adapters/dot.mjs +6 -86
- package/dist/graph-adapters/reactflow.d.mts +26 -7
- package/dist/graph-adapters/reactflow.mjs +21 -72
- package/dist/graph-adapters/types.d.mts +2 -91
- package/dist/index.d.mts +16 -8
- package/dist/index.mjs +8 -5
- package/dist/inspector.d.mts +35 -74
- package/dist/inspector.mjs +61 -88
- package/dist/lifecycle.d.mts +20 -53
- package/dist/lifecycle.mjs +129 -99
- package/dist/metadata/metadata-keys.d.mts +9 -26
- package/dist/metadata/metadata-keys.mjs +7 -28
- package/dist/metadata/metadata-reader-token.d.mts +7 -0
- package/dist/metadata/metadata-reader-token.mjs +5 -0
- package/dist/metadata/metadata-types.d.mts +26 -75
- package/dist/metadata/symbol-metadata-reader.d.mts +10 -26
- package/dist/metadata/symbol-metadata-reader.mjs +32 -45
- package/dist/module.d.mts +30 -96
- package/dist/module.mjs +26 -72
- package/dist/registry.d.mts +32 -63
- package/dist/registry.mjs +131 -82
- package/dist/resolve-options.d.mts +18 -0
- package/dist/resolve-options.mjs +22 -0
- package/dist/resolver.d.mts +67 -190
- package/dist/resolver.mjs +715 -424
- package/dist/scope.d.mts +19 -106
- package/dist/scope.mjs +37 -196
- package/dist/token.d.mts +8 -22
- package/dist/token.mjs +9 -11
- package/dist/types.d.mts +48 -0
- package/dist/types.mjs +1 -0
- package/package.json +36 -14
- package/dist/metadata/param-registry.d.mts +0 -16
- package/dist/metadata/param-registry.mjs +0 -31
- package/dist/scope-validation.d.mts +0 -21
- package/dist/scope-validation.mjs +0 -35
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @codefast/di
|
|
2
2
|
|
|
3
|
+
## 0.3.14-canary.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`4435cfb`](https://github.com/codefastlabs/codefast/commit/4435cfbf4883d018c29942aa571422bb95f73f97) Thanks [@thevuong](https://github.com/thevuong)! - refactor(di): enhance binding key generation and simplify transient binding logic
|
|
8
|
+
|
|
9
|
+
- [`427bff6`](https://github.com/codefastlabs/codefast/commit/427bff64196ba62ccfcf1e893d93714875b7b42e) Thanks [@thevuong](https://github.com/thevuong)! - refactor(di): update predicates and improve documentation
|
|
10
|
+
|
|
11
|
+
- [`408a9ad`](https://github.com/codefastlabs/codefast/commit/408a9ad5903eb7f1f15ebc576017d2122a18722f) Thanks [@thevuong](https://github.com/thevuong)! - refactor(di): improve binding resolution logic in DefaultContainer and BindingRegistry
|
|
12
|
+
|
|
13
|
+
- [`4957e0e`](https://github.com/codefastlabs/codefast/commit/4957e0e8b4b2428447ef11380397b03deef0b092) Thanks [@thevuong](https://github.com/thevuong)! - fix(vitest): update test file patterns to use .test extension
|
|
14
|
+
|
|
15
|
+
- [`4601be2`](https://github.com/codefastlabs/codefast/commit/4601be25746e628c7d74cebaa9ee362e80301a19) Thanks [@thevuong](https://github.com/thevuong)! - feat(di): implement fast resolution mechanism in DefaultContainer
|
|
16
|
+
|
|
17
|
+
- [`568f370`](https://github.com/codefastlabs/codefast/commit/568f370143b5951fa018472ba6e882d8d599f5e7) Thanks [@thevuong](https://github.com/thevuong)! - refactor(di): enhance transient binding handling in DependencyResolver
|
|
18
|
+
|
|
19
|
+
- [`ea57eab`](https://github.com/codefastlabs/codefast/commit/ea57eab321f4e57361520de3d6356abf900acbf8) Thanks [@thevuong](https://github.com/thevuong)! - refactor(benchmarks): enhance binding resolution and improve transient binding handling
|
|
20
|
+
|
|
3
21
|
## 0.3.14-canary.1
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -93,32 +93,42 @@ yarn add @codefast/di
|
|
|
93
93
|
## Quick Start
|
|
94
94
|
|
|
95
95
|
```typescript
|
|
96
|
-
import { Container,
|
|
96
|
+
import { Container, injectable, token } from "@codefast/di";
|
|
97
97
|
|
|
98
98
|
interface Logger {
|
|
99
|
-
|
|
99
|
+
info(message: string): void;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
const LoggerToken = token<Logger>("Logger");
|
|
103
103
|
|
|
104
104
|
@injectable([LoggerToken])
|
|
105
|
-
class
|
|
105
|
+
class CheckoutService {
|
|
106
106
|
constructor(private readonly logger: Logger) {}
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
this.logger.
|
|
108
|
+
complete(orderId: string): void {
|
|
109
|
+
this.logger.info(`Order ${orderId} completed`);
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
const container = Container.create();
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
container.bind(
|
|
115
|
+
// Production wiring
|
|
116
|
+
container.bind(LoggerToken).toConstantValue({
|
|
117
|
+
info: (message) => console.log(`[prod] ${message}`),
|
|
118
|
+
});
|
|
119
|
+
container.bind(CheckoutService).toSelf();
|
|
120
|
+
|
|
121
|
+
container.resolve(CheckoutService).complete("ORD-1001");
|
|
122
|
+
|
|
123
|
+
// Same service, test wiring
|
|
124
|
+
container.rebind(LoggerToken).toConstantValue({
|
|
125
|
+
info: (message) => console.log(`[test] ${message}`),
|
|
126
|
+
});
|
|
117
127
|
|
|
118
|
-
container.resolve(
|
|
128
|
+
container.resolve(CheckoutService).complete("ORD-1002");
|
|
119
129
|
```
|
|
120
130
|
|
|
121
|
-
|
|
131
|
+
`@injectable([...])` lists constructor dependencies in order. The key idea: business classes (`CheckoutService`) stay unchanged while behavior swaps by rebinding infrastructure (`LoggerToken`) per environment.
|
|
122
132
|
|
|
123
133
|
---
|
|
124
134
|
|
|
@@ -217,8 +227,8 @@ Multiple bindings can share the same token. A constraint picks the right one at
|
|
|
217
227
|
**Named**
|
|
218
228
|
|
|
219
229
|
```typescript
|
|
220
|
-
container.bind(LoggerToken).whenNamed("file")
|
|
221
|
-
container.bind(LoggerToken).whenNamed("console")
|
|
230
|
+
container.bind(LoggerToken).toConstantValue(fileLogger).whenNamed("file");
|
|
231
|
+
container.bind(LoggerToken).toConstantValue(consoleLogger).whenNamed("console");
|
|
222
232
|
|
|
223
233
|
container.resolve(LoggerToken, { name: "file" });
|
|
224
234
|
```
|
|
@@ -226,8 +236,8 @@ container.resolve(LoggerToken, { name: "file" });
|
|
|
226
236
|
**Tagged** — the hint is a tuple `[tag, value]`:
|
|
227
237
|
|
|
228
238
|
```typescript
|
|
229
|
-
container.bind(StorageToken).whenTagged("provider", "s3")
|
|
230
|
-
container.bind(StorageToken).whenTagged("provider", "local")
|
|
239
|
+
container.bind(StorageToken).to(S3Storage).whenTagged("provider", "s3");
|
|
240
|
+
container.bind(StorageToken).to(LocalStorage).whenTagged("provider", "local");
|
|
231
241
|
|
|
232
242
|
container.resolve(StorageToken, { tag: ["provider", "s3"] });
|
|
233
243
|
```
|
|
@@ -235,9 +245,9 @@ container.resolve(StorageToken, { tag: ["provider", "s3"] });
|
|
|
235
245
|
**Predicate** — inspect the full resolution graph:
|
|
236
246
|
|
|
237
247
|
```typescript
|
|
238
|
-
import { whenAnyAncestorIs, whenParentIs,
|
|
248
|
+
import { whenAnyAncestorIs, whenParentIs, whenParentTagged } from "@codefast/di/constraints";
|
|
239
249
|
|
|
240
|
-
container.bind(LoggerToken).when(whenParentIs(DiagnosticsService))
|
|
250
|
+
container.bind(LoggerToken).toConstantValue(verboseLogger).when(whenParentIs(DiagnosticsService));
|
|
241
251
|
```
|
|
242
252
|
|
|
243
253
|
Built-in predicates:
|
|
@@ -246,7 +256,7 @@ Built-in predicates:
|
|
|
246
256
|
| ------------------------------ | --------------------------------------------------------------------------- |
|
|
247
257
|
| `whenParentIs(key)` | the direct parent binding was registered for `key`. |
|
|
248
258
|
| `whenAnyAncestorIs(key)` | any ancestor binding on the materialization stack was registered for `key`. |
|
|
249
|
-
| `
|
|
259
|
+
| `whenParentTagged(tag, value)` | the immediate parent binding carries `tag` with `value`. |
|
|
250
260
|
|
|
251
261
|
For anything else, pass a custom `(ctx: ConstraintContext) => boolean` to `.when(predicate)`.
|
|
252
262
|
|
|
@@ -473,22 +483,21 @@ Sync `using` is intentionally rejected: calling `Symbol.dispose` throws. Use `aw
|
|
|
473
483
|
|
|
474
484
|
Modules bundle related bindings into reusable units. A module holds no runtime state and can be loaded into any number of containers.
|
|
475
485
|
|
|
476
|
-
|
|
486
|
+
Use the same fluent order everywhere (including inside modules): `bind(token).to*(…).when*(…).scope()…`.
|
|
477
487
|
|
|
478
|
-
- `api.bind(
|
|
479
|
-
-
|
|
480
|
-
- `api.bind(Token).to*(...).whenNamed(...)` updates only that single built binding; it does not switch later lines into append mode.
|
|
488
|
+
- Register **multiple** implementations for one token with separate chains, e.g. `api.bind(T).to(A).whenNamed("a")` and `api.bind(T).to(B).whenNamed("b")`.
|
|
489
|
+
- **Last-wins** applies per slot (default vs named vs tag-set), as in the main container API.
|
|
481
490
|
|
|
482
491
|
```typescript
|
|
483
492
|
import { Container, Module } from "@codefast/di";
|
|
484
493
|
|
|
485
|
-
const
|
|
494
|
+
const InfrastructureModule = Module.create("Infra", (api) => {
|
|
486
495
|
api.bind(LoggerToken).toConstantValue(console);
|
|
487
496
|
api.bind(ConfigToken).toConstantValue(loadConfig());
|
|
488
497
|
});
|
|
489
498
|
|
|
490
499
|
const AppModule = Module.create("App", (api) => {
|
|
491
|
-
api.import(
|
|
500
|
+
api.import(InfrastructureModule);
|
|
492
501
|
api.bind(UserRepository).toSelf().singleton();
|
|
493
502
|
api.bind(UserServiceToken).to(UserService).transient();
|
|
494
503
|
});
|
|
@@ -510,7 +519,7 @@ const container = await Container.fromModulesAsync(DbModule, AppModule);
|
|
|
510
519
|
Load and unload on an existing container:
|
|
511
520
|
|
|
512
521
|
```typescript
|
|
513
|
-
container.load(
|
|
522
|
+
container.load(InfrastructureModule, AppModule);
|
|
514
523
|
await container.loadAsync(DbModule);
|
|
515
524
|
|
|
516
525
|
container.unload(AppModule);
|
|
@@ -569,17 +578,24 @@ The root entry re-exports the full public API. Subpath exports are provided for
|
|
|
569
578
|
| `@codefast/di/decorators/inject` | `inject`, `optional`, `injectAll`, `isInjectionDescriptor` |
|
|
570
579
|
| `@codefast/di/decorators/injectable` | `@injectable`, `getAutoRegistered` |
|
|
571
580
|
| `@codefast/di/decorators/lifecycle-decorators` | `@postConstruct`, `@preDestroy` |
|
|
572
|
-
| `@codefast/di/constraints` | `whenParentIs`, `whenAnyAncestorIs`, `
|
|
581
|
+
| `@codefast/di/constraints` | `whenParentIs`, `whenAnyAncestorIs`, `whenParentTagged` |
|
|
573
582
|
| `@codefast/di/registry` | `BindingRegistry` |
|
|
574
583
|
| `@codefast/di/resolver` | `DependencyResolver` internals |
|
|
575
584
|
| `@codefast/di/scope` | `ScopeManager` |
|
|
576
|
-
| `@codefast/di/scope-validation` | `validateScopeRules` |
|
|
577
585
|
| `@codefast/di/lifecycle` | Activation/deactivation runners |
|
|
578
586
|
| `@codefast/di/dependency-graph` | Dependency-edge collection helpers |
|
|
587
|
+
| `@codefast/di/graph-adapters/cytoscape` | Cytoscape adapter for `ContainerGraphJson` |
|
|
588
|
+
| `@codefast/di/graph-adapters/dot` | DOT adapter for `ContainerGraphJson` |
|
|
589
|
+
| `@codefast/di/graph-adapters/reactflow` | React Flow adapter for `ContainerGraphJson` |
|
|
590
|
+
| `@codefast/di/graph-adapters/types` | Shared graph adapter type definitions |
|
|
579
591
|
| `@codefast/di/inspector` | `ContainerInspector`, snapshot + graph types |
|
|
580
592
|
| `@codefast/di/errors` | Full `DiError` hierarchy |
|
|
581
593
|
| `@codefast/di/environment` | `isDevelopmentOrTestEnvironment`, `isProductionEnvironment` |
|
|
582
|
-
| `@codefast/di/metadata
|
|
594
|
+
| `@codefast/di/metadata/metadata-keys` | Metadata symbol keys |
|
|
595
|
+
| `@codefast/di/metadata/metadata-types` | Metadata type definitions |
|
|
596
|
+
| `@codefast/di/metadata/param-registry` | Constructor parameter metadata registry |
|
|
597
|
+
| `@codefast/di/metadata/symbol-metadata-reader` | Symbol metadata reader utilities |
|
|
598
|
+
| `@codefast/di/package.json` | Package metadata |
|
|
583
599
|
|
|
584
600
|
See `package.json → exports` for the authoritative list.
|
|
585
601
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BindingScope } from "./types.mjs";
|
|
2
|
+
import { Binding } from "./binding.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/binding-scope.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Runtime scope used for validation and introspection. Alias bindings are treated as transient
|
|
7
|
+
* because they defer scope to the aliased target at resolve time.
|
|
8
|
+
*/
|
|
9
|
+
declare function effectiveBindingScope(binding: Binding): BindingScope;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { effectiveBindingScope };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/binding-scope.ts
|
|
2
|
+
/**
|
|
3
|
+
* Runtime scope used for validation and introspection. Alias bindings are treated as transient
|
|
4
|
+
* because they defer scope to the aliased target at resolve time.
|
|
5
|
+
*/
|
|
6
|
+
function effectiveBindingScope(binding) {
|
|
7
|
+
switch (binding.kind) {
|
|
8
|
+
case "alias": return "transient";
|
|
9
|
+
case "class":
|
|
10
|
+
case "constant":
|
|
11
|
+
case "dynamic":
|
|
12
|
+
case "dynamic-async":
|
|
13
|
+
case "resolved":
|
|
14
|
+
case "resolved-async": return binding.scope;
|
|
15
|
+
default: return binding;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { effectiveBindingScope };
|
|
@@ -1,33 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Binding, ConstraintContext, Constructor, ResolveHint } from "./binding.mjs";
|
|
1
|
+
import { ConstraintContext, ResolveOptions } from "./types.mjs";
|
|
2
|
+
import { Binding } from "./binding.mjs";
|
|
4
3
|
|
|
5
4
|
//#region src/binding-select.d.ts
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
6
|
+
* Select a single candidate from a list of bindings using slot matching + predicates.
|
|
7
|
+
* Returns undefined if no match, throws AmbiguousBindingError if multiple match.
|
|
8
8
|
*/
|
|
9
|
-
declare function
|
|
9
|
+
declare function selectBinding(bindings: readonly Binding[], hint: ResolveOptions | undefined, ctx: ConstraintContext, tName: string): Binding | undefined;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Filtering order: name filter → tag filter → constraint predicate. Bindings without a
|
|
14
|
-
* constraint predicate always pass the constraint stage. Returns the surviving candidates
|
|
15
|
-
* (may be empty).
|
|
11
|
+
* Select all candidates matching hint + predicates.
|
|
16
12
|
*/
|
|
17
|
-
declare function
|
|
18
|
-
/**
|
|
19
|
-
* Selects exactly one binding from the provided list, applying hint and constraint filtering.
|
|
20
|
-
*
|
|
21
|
-
* @throws {@link TokenNotBoundError} — `bindings` list is empty, or no candidate survives
|
|
22
|
-
* filtering without a name/tag hint.
|
|
23
|
-
* @throws {@link NoMatchingBindingError} — a name/tag hint was provided but no candidate matched.
|
|
24
|
-
* @throws {@link InternalError} — multiple candidates survive filtering (ambiguous binding).
|
|
25
|
-
*/
|
|
26
|
-
declare function selectBindingForRegistry(bindings: readonly Binding<unknown>[], hint: ResolveHint | undefined, tokenLabel: string, pathLabels: readonly string[], constraintCtx: ConstraintContext | undefined): Binding<unknown>;
|
|
27
|
-
/**
|
|
28
|
-
* Convenience wrapper: looks up bindings for `key` and selects the default (no-hint,
|
|
29
|
-
* no-constraint) binding. Throws {@link TokenNotBoundError} if the key is unregistered.
|
|
30
|
-
*/
|
|
31
|
-
declare function selectDefaultBindingForKey(lookup: (key: RegistryKey) => readonly Binding<unknown>[] | undefined, key: RegistryKey, pathPrefix: readonly string[]): Binding<unknown>;
|
|
13
|
+
declare function selectAllBindings(bindings: readonly Binding[], hint: ResolveOptions | undefined, ctx: ConstraintContext): Binding[];
|
|
32
14
|
//#endregion
|
|
33
|
-
export {
|
|
15
|
+
export { selectAllBindings, selectBinding };
|
package/dist/binding-select.mjs
CHANGED
|
@@ -1,61 +1,68 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AmbiguousBindingError } from "./errors.mjs";
|
|
2
2
|
//#region src/binding-select.ts
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Select a single candidate from a list of bindings using slot matching + predicates.
|
|
5
|
+
* Returns undefined if no match, throws AmbiguousBindingError if multiple match.
|
|
5
6
|
*/
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
function selectBinding(bindings, hint, ctx, tName) {
|
|
8
|
+
const candidates = filterBindings(bindings, hint, ctx);
|
|
9
|
+
if (candidates.length === 0) return;
|
|
10
|
+
if (candidates.length === 1) return candidates[0];
|
|
11
|
+
throw new AmbiguousBindingError(tName, candidates.map((c) => c.id));
|
|
9
12
|
}
|
|
10
13
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Filtering order: name filter → tag filter → constraint predicate. Bindings without a
|
|
14
|
-
* constraint predicate always pass the constraint stage. Returns the surviving candidates
|
|
15
|
-
* (may be empty).
|
|
14
|
+
* Select all candidates matching hint + predicates.
|
|
16
15
|
*/
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
if (hint?.name !== void 0) candidates = candidates.filter((binding) => binding.bindingName === hint.name);
|
|
20
|
-
if (hint?.tag !== void 0) {
|
|
21
|
-
const [tagKey, tagValue] = hint.tag;
|
|
22
|
-
candidates = candidates.filter((binding) => Object.is(binding.tags.get(tagKey), tagValue));
|
|
23
|
-
}
|
|
24
|
-
if (constraintCtx !== void 0) candidates = candidates.filter((binding) => binding.constraint === void 0 || binding.constraint(constraintCtx));
|
|
25
|
-
return candidates;
|
|
16
|
+
function selectAllBindings(bindings, hint, ctx) {
|
|
17
|
+
return filterBindings(bindings, hint, ctx, "all");
|
|
26
18
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const candidates = filterMatchingBindings(bindings, hint, constraintCtx);
|
|
38
|
-
if (candidates.length === 1) {
|
|
39
|
-
const [only] = candidates;
|
|
40
|
-
if (only === void 0) throw new InternalError(`Internal: expected binding candidate for "${tokenLabel}" (resolution path: ${pathLabels.join(" -> ")})`);
|
|
41
|
-
return only;
|
|
19
|
+
function filterBindings(bindings, hint, ctx, mode = "single") {
|
|
20
|
+
if (hint === void 0) {
|
|
21
|
+
const resultWithoutHint = [];
|
|
22
|
+
if (mode === "all") {
|
|
23
|
+
for (const binding of bindings) if (matchesPredicate(binding, ctx)) resultWithoutHint.push(binding);
|
|
24
|
+
} else for (const binding of bindings) {
|
|
25
|
+
const slot = binding.slot;
|
|
26
|
+
if (slot.name === void 0 && slot.tags.length === 0 && matchesPredicate(binding, ctx)) resultWithoutHint.push(binding);
|
|
27
|
+
}
|
|
28
|
+
return resultWithoutHint;
|
|
42
29
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
30
|
+
const result = [];
|
|
31
|
+
for (const binding of bindings) if ((mode === "all" ? matchesSlotForResolveAll(binding, hint) : matchesSlot(binding, hint)) && matchesPredicate(binding, ctx)) result.push(binding);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
function matchesSlotForResolveAll(binding, hint) {
|
|
35
|
+
if (!(hint !== void 0 && (hint.name !== void 0 || hint.tags !== void 0 && hint.tags.length > 0 || hint.tag !== void 0))) return true;
|
|
36
|
+
return matchesSlot(binding, hint);
|
|
37
|
+
}
|
|
38
|
+
function matchesSlot(binding, hint) {
|
|
39
|
+
const slot = binding.slot;
|
|
40
|
+
const hintName = hint?.name;
|
|
41
|
+
const hintTags = hint?.tags;
|
|
42
|
+
const singleHintTag = hint?.tag;
|
|
43
|
+
const hasHintTags = (hintTags?.length ?? 0) > 0 || singleHintTag !== void 0;
|
|
44
|
+
if (slot.name !== void 0) {
|
|
45
|
+
if (hintName === void 0) return false;
|
|
46
|
+
if (slot.name !== hintName) return false;
|
|
47
|
+
} else if (hintName !== void 0) return false;
|
|
48
|
+
if (slot.tags.length > 0) {
|
|
49
|
+
if (!hasHintTags) return false;
|
|
50
|
+
for (const [tagKey, tagValue] of slot.tags) if (!matchHintTag(tagKey, tagValue, hintTags, singleHintTag)) return false;
|
|
51
|
+
} else if (hasHintTags) return false;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
function matchHintTag(tagKey, tagValue, hintTags, singleHintTag) {
|
|
55
|
+
if (singleHintTag !== void 0 && singleHintTag[0] === tagKey && Object.is(singleHintTag[1], tagValue)) return true;
|
|
56
|
+
if (hintTags === void 0 || hintTags.length === 0) return false;
|
|
57
|
+
for (let index = 0; index < hintTags.length; index += 1) {
|
|
58
|
+
const hintTag = hintTags[index];
|
|
59
|
+
if (hintTag[0] === tagKey && Object.is(hintTag[1], tagValue)) return true;
|
|
46
60
|
}
|
|
47
|
-
|
|
61
|
+
return false;
|
|
48
62
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
*/
|
|
53
|
-
function selectDefaultBindingForKey(lookup, key, pathPrefix) {
|
|
54
|
-
const label = registryKeyLabel(key);
|
|
55
|
-
const nextPath = [...pathPrefix, label];
|
|
56
|
-
const bindings = lookup(key);
|
|
57
|
-
if (bindings === void 0 || bindings.length === 0) throw new TokenNotBoundError(label, nextPath);
|
|
58
|
-
return selectBindingForRegistry(bindings, void 0, label, nextPath, void 0);
|
|
63
|
+
function matchesPredicate(binding, ctx) {
|
|
64
|
+
if (binding.predicate === void 0) return true;
|
|
65
|
+
return binding.predicate(ctx);
|
|
59
66
|
}
|
|
60
67
|
//#endregion
|
|
61
|
-
export {
|
|
68
|
+
export { selectAllBindings, selectBinding };
|