@djodjonx/neo-syringe 1.1.5 → 1.2.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/.github/workflows/ci.yml +6 -5
- package/.github/workflows/docs.yml +59 -0
- package/CHANGELOG.md +27 -0
- package/README.md +74 -740
- package/dist/{GraphValidator-G0F4QiLk.cjs → GraphValidator-CV4VoJl0.cjs} +18 -10
- package/dist/{GraphValidator-C8ldJtNp.mjs → GraphValidator-DXqqkNdS.mjs} +18 -10
- package/dist/cli/index.cjs +16 -1
- package/dist/cli/index.mjs +16 -1
- package/dist/index.d.cts +31 -5
- package/dist/index.d.mts +31 -5
- package/dist/lsp/index.cjs +1 -1
- package/dist/lsp/index.mjs +1 -1
- package/dist/unplugin/index.cjs +33 -9
- package/dist/unplugin/index.d.cts +7 -5
- package/dist/unplugin/index.d.mts +7 -5
- package/dist/unplugin/index.mjs +33 -9
- package/docs/.vitepress/config.ts +109 -0
- package/docs/.vitepress/theme/custom.css +150 -0
- package/docs/.vitepress/theme/index.ts +17 -0
- package/docs/api/configuration.md +274 -0
- package/docs/api/functions.md +291 -0
- package/docs/api/types.md +158 -0
- package/docs/guide/basic-usage.md +267 -0
- package/docs/guide/cli.md +174 -0
- package/docs/guide/generated-code.md +284 -0
- package/docs/guide/getting-started.md +171 -0
- package/docs/guide/ide-plugin.md +203 -0
- package/docs/guide/injection-types.md +287 -0
- package/docs/guide/legacy-migration.md +333 -0
- package/docs/guide/lifecycle.md +223 -0
- package/docs/guide/parent-container.md +321 -0
- package/docs/guide/scoped-injections.md +271 -0
- package/docs/guide/what-is-neo-syringe.md +162 -0
- package/docs/guide/why-neo-syringe.md +219 -0
- package/docs/index.md +138 -0
- package/docs/public/logo.png +0 -0
- package/package.json +15 -12
- package/src/analyzer/Analyzer.ts +20 -10
- package/src/analyzer/types.ts +55 -49
- package/src/cli/index.ts +15 -0
- package/src/generator/Generator.ts +24 -2
- package/src/generator/GraphValidator.ts +6 -2
- package/src/types.ts +30 -4
- package/src/unplugin/index.ts +13 -41
- package/tests/analyzer/Analyzer.test.ts +4 -4
- package/tests/analyzer/AnalyzerDeclarative.test.ts +1 -1
- package/tests/analyzer/Factory.test.ts +2 -2
- package/tests/analyzer/Scoped.test.ts +434 -0
- package/tests/cli/cli.test.ts +91 -0
- package/tests/e2e/container-integration.test.ts +21 -21
- package/tests/e2e/generated-code.test.ts +7 -7
- package/tests/e2e/scoped.test.ts +370 -0
- package/tests/e2e/snapshots.test.ts +2 -2
- package/tests/e2e/standalone.test.ts +2 -2
- package/tests/generator/ExternalGenerator.test.ts +1 -1
- package/tests/generator/FactoryGenerator.test.ts +6 -6
- package/tests/generator/Generator.test.ts +2 -2
- package/tests/generator/GeneratorDeclarative.test.ts +1 -1
- package/tests/generator/GraphValidator.test.ts +1 -1
- package/tsconfig.json +2 -1
- package/typedoc.json +0 -5
package/src/analyzer/types.ts
CHANGED
|
@@ -1,87 +1,93 @@
|
|
|
1
1
|
import type { Symbol, Node } from 'typescript';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Unique identifier for a token (interface name or class name).
|
|
5
|
+
*/
|
|
6
|
+
export type TokenId = string;
|
|
4
7
|
|
|
8
|
+
/**
|
|
9
|
+
* How a service was registered in the container.
|
|
10
|
+
* - `explicit`: Provider was explicitly specified.
|
|
11
|
+
* - `autowire`: Token is both the token and provider (self-binding).
|
|
12
|
+
* - `parent`: Inherited from parent container.
|
|
13
|
+
* - `factory`: Provider is a factory function.
|
|
14
|
+
*/
|
|
5
15
|
export type RegistrationType = 'explicit' | 'autowire' | 'parent' | 'factory';
|
|
6
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Represents a single service definition in the dependency graph.
|
|
19
|
+
*/
|
|
7
20
|
export interface ServiceDefinition {
|
|
21
|
+
/** Unique identifier for this service token. */
|
|
8
22
|
tokenId: TokenId;
|
|
23
|
+
|
|
9
24
|
/**
|
|
10
|
-
* The symbol of the concrete class implementation.
|
|
25
|
+
* The TypeScript symbol of the concrete class implementation.
|
|
11
26
|
* Undefined if the provider is a factory function.
|
|
12
27
|
*/
|
|
13
28
|
implementationSymbol?: Symbol;
|
|
14
29
|
|
|
15
30
|
/**
|
|
16
|
-
* The symbol of the token (if it is a Class/Value).
|
|
17
|
-
* Undefined if the token is a
|
|
31
|
+
* The TypeScript symbol of the token (if it is a Class/Value).
|
|
32
|
+
* Undefined if the token is a virtual interface ID.
|
|
18
33
|
*/
|
|
19
34
|
tokenSymbol?: Symbol;
|
|
20
35
|
|
|
21
|
-
/**
|
|
22
|
-
* The source node where the registration happened (for error reporting).
|
|
23
|
-
*/
|
|
36
|
+
/** The source node where the registration happened (for error reporting). */
|
|
24
37
|
registrationNode: Node;
|
|
25
38
|
|
|
39
|
+
/** How this service was registered. */
|
|
26
40
|
type: RegistrationType;
|
|
27
|
-
scope: 'singleton' | 'transient';
|
|
28
41
|
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
/** Lifecycle of the service instance. */
|
|
43
|
+
lifecycle: 'singleton' | 'transient';
|
|
44
|
+
|
|
45
|
+
/** True if the token is an interface (requires string literal key). */
|
|
33
46
|
isInterfaceToken?: boolean;
|
|
34
47
|
|
|
35
|
-
/**
|
|
36
|
-
* True if the token is a Value Token (useToken<T>('name')).
|
|
37
|
-
* Used for primitive values like string, number, boolean.
|
|
38
|
-
*/
|
|
48
|
+
/** True if the token is a value token for primitives. */
|
|
39
49
|
isValueToken?: boolean;
|
|
40
50
|
|
|
41
|
-
/**
|
|
42
|
-
* True if the provider is a factory function.
|
|
43
|
-
*/
|
|
51
|
+
/** True if the provider is a factory function. */
|
|
44
52
|
isFactory?: boolean;
|
|
45
53
|
|
|
46
|
-
/**
|
|
47
|
-
* The raw source text of the factory function (for code generation).
|
|
48
|
-
*/
|
|
54
|
+
/** The raw source text of the factory function (for code generation). */
|
|
49
55
|
factorySource?: string;
|
|
56
|
+
|
|
57
|
+
/** True if this injection is scoped to the local container. */
|
|
58
|
+
isScoped?: boolean;
|
|
50
59
|
}
|
|
51
60
|
|
|
61
|
+
/**
|
|
62
|
+
* A node in the dependency graph representing a service and its dependencies.
|
|
63
|
+
*/
|
|
52
64
|
export interface DependencyNode {
|
|
65
|
+
/** The service definition. */
|
|
53
66
|
service: ServiceDefinition;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* Maps parameter index to the TokenId it depends on.
|
|
57
|
-
*/
|
|
67
|
+
|
|
68
|
+
/** Token IDs of dependencies required by this service's constructor. */
|
|
58
69
|
dependencies: TokenId[];
|
|
59
70
|
}
|
|
60
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Complete dependency graph for a container configuration.
|
|
74
|
+
*/
|
|
61
75
|
export interface DependencyGraph {
|
|
76
|
+
/** All service nodes indexed by their token ID. */
|
|
62
77
|
nodes: Map<TokenId, DependencyNode>;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
*/
|
|
78
|
+
|
|
79
|
+
/** Root services that are explicitly requested or exported. */
|
|
66
80
|
roots: TokenId[];
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
* Captured as raw source text to be injected into the generated constructor.
|
|
70
|
-
*/
|
|
81
|
+
|
|
82
|
+
/** Arguments passed to the .build() method call (raw source text). */
|
|
71
83
|
buildArguments?: string[];
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Tokens provided by the parent container (useContainer).
|
|
84
|
-
* Used for validation - these tokens don't need local bindings.
|
|
85
|
-
*/
|
|
86
|
-
parentProvidedTokens?: Set<TokenId>;
|
|
87
|
-
}
|
|
84
|
+
|
|
85
|
+
/** Optional container name for debugging. */
|
|
86
|
+
containerName?: string;
|
|
87
|
+
|
|
88
|
+
/** Legacy container variable names to delegate to. */
|
|
89
|
+
legacyContainers?: string[];
|
|
90
|
+
|
|
91
|
+
/** Tokens provided by the parent container (used for validation). */
|
|
92
|
+
parentProvidedTokens?: Set<TokenId>;
|
|
93
|
+
}
|
package/src/cli/index.ts
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Neo-Syringe CLI
|
|
4
|
+
*
|
|
5
|
+
* Validates the dependency graph for a TypeScript project.
|
|
6
|
+
* Detects circular dependencies, missing bindings, and duplicate registrations.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```bash
|
|
10
|
+
* npx neo-syringe
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
2
13
|
import * as ts from 'typescript';
|
|
3
14
|
import { Analyzer } from '../analyzer/Analyzer';
|
|
4
15
|
import { GraphValidator } from '../generator/GraphValidator';
|
|
5
16
|
|
|
17
|
+
/**
|
|
18
|
+
* CLI entry point.
|
|
19
|
+
* Reads tsconfig.json, analyzes the project, and validates the dependency graph.
|
|
20
|
+
*/
|
|
6
21
|
function main() {
|
|
7
22
|
const cwd = process.cwd();
|
|
8
23
|
const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, 'tsconfig.json');
|
|
@@ -2,11 +2,24 @@ import * as ts from 'typescript';
|
|
|
2
2
|
import { DependencyGraph, TokenId } from '../analyzer/types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Generates
|
|
5
|
+
* Generates TypeScript code for the dependency injection container.
|
|
6
|
+
*
|
|
7
|
+
* Takes a validated dependency graph and produces:
|
|
8
|
+
* - Import statements for all dependencies
|
|
9
|
+
* - Factory functions for each service
|
|
10
|
+
* - A NeoContainer class with resolve logic
|
|
6
11
|
*/
|
|
7
12
|
export class Generator {
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new Generator.
|
|
15
|
+
* @param graph - The validated dependency graph to generate code from.
|
|
16
|
+
*/
|
|
8
17
|
constructor(private graph: DependencyGraph) {}
|
|
9
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Generates the complete container code as a string.
|
|
21
|
+
* @returns TypeScript source code for the generated container.
|
|
22
|
+
*/
|
|
10
23
|
public generate(): string {
|
|
11
24
|
const sorted = this.topologicalSort();
|
|
12
25
|
const imports = new Map<string, string>(); // filePath -> importAliasPrefix
|
|
@@ -78,7 +91,7 @@ function ${factoryId}(container: NeoContainer) {
|
|
|
78
91
|
}
|
|
79
92
|
|
|
80
93
|
// 2. Generate Resolve Switch Case
|
|
81
|
-
const isTransient = node.service.
|
|
94
|
+
const isTransient = node.service.lifecycle === 'transient';
|
|
82
95
|
|
|
83
96
|
// Determine key for instances Map and token check
|
|
84
97
|
let tokenKey: string;
|
|
@@ -196,6 +209,10 @@ export const container = new NeoContainer(${containerArgs});
|
|
|
196
209
|
`;
|
|
197
210
|
}
|
|
198
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Sorts services in topological order (dependencies before dependents).
|
|
214
|
+
* @returns Array of TokenIds in dependency order.
|
|
215
|
+
*/
|
|
199
216
|
private topologicalSort(): TokenId[] {
|
|
200
217
|
const visited = new Set<TokenId>();
|
|
201
218
|
const sorted: TokenId[] = [];
|
|
@@ -220,6 +237,11 @@ export const container = new NeoContainer(${containerArgs});
|
|
|
220
237
|
return sorted;
|
|
221
238
|
}
|
|
222
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Creates a valid JavaScript function name from a token ID.
|
|
242
|
+
* @param tokenId - The token identifier.
|
|
243
|
+
* @returns A sanitized factory function name.
|
|
244
|
+
*/
|
|
223
245
|
private getFactoryName(tokenId: TokenId): string {
|
|
224
246
|
return `create_${tokenId.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
|
225
247
|
}
|
|
@@ -19,11 +19,15 @@ export class GraphValidator {
|
|
|
19
19
|
const parentTokens = graph.parentProvidedTokens ?? new Set<TokenId>();
|
|
20
20
|
|
|
21
21
|
// 1. Check for Duplicate Registrations (local token already in parent)
|
|
22
|
-
for (const nodeId of graph.nodes
|
|
22
|
+
for (const [nodeId, node] of graph.nodes) {
|
|
23
23
|
if (parentTokens.has(nodeId)) {
|
|
24
|
+
// Allow if scoped: true (intentional override)
|
|
25
|
+
if (node.service.isScoped) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
24
28
|
throw new Error(
|
|
25
29
|
`Duplicate registration: '${nodeId}' is already registered in the parent container. ` +
|
|
26
|
-
`
|
|
30
|
+
`Use 'scoped: true' to override the parent's registration intentionally.`
|
|
27
31
|
);
|
|
28
32
|
}
|
|
29
33
|
}
|
package/src/types.ts
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* Represents a generic class constructor.
|
|
3
3
|
* @template T - The type of the instance created by the constructor.
|
|
4
4
|
*/
|
|
5
|
-
export type Constructor<T =
|
|
5
|
+
export type Constructor<T = any> = new (...args: any[]) => T;
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Defines the lifecycle
|
|
8
|
+
* Defines the lifecycle of a service.
|
|
9
9
|
* - `singleton`: One instance per container.
|
|
10
10
|
* - `transient`: A new instance every time it is resolved.
|
|
11
11
|
*/
|
|
12
|
-
export type
|
|
12
|
+
export type Lifecycle = 'singleton' | 'transient';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* The dependency injection container interface.
|
|
@@ -86,7 +86,33 @@ export interface Injection<T = any> {
|
|
|
86
86
|
* Required when provider is a function, not a class.
|
|
87
87
|
*/
|
|
88
88
|
useFactory?: boolean;
|
|
89
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Lifecycle of the service.
|
|
91
|
+
* - `singleton`: One instance per container (default).
|
|
92
|
+
* - `transient`: A new instance every time it is resolved.
|
|
93
|
+
*/
|
|
94
|
+
lifecycle?: Lifecycle;
|
|
95
|
+
/**
|
|
96
|
+
* If true, this injection is scoped to this container only.
|
|
97
|
+
* Allows overriding a token from a parent container without causing a duplicate error.
|
|
98
|
+
* The local instance will be used instead of delegating to the parent.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const parent = defineBuilderConfig({
|
|
103
|
+
* injections: [{ token: useInterface<ILogger>(), provider: ConsoleLogger }]
|
|
104
|
+
* });
|
|
105
|
+
*
|
|
106
|
+
* const child = defineBuilderConfig({
|
|
107
|
+
* useContainer: parent,
|
|
108
|
+
* injections: [
|
|
109
|
+
* // Override parent's ILogger with a local FileLogger
|
|
110
|
+
* { token: useInterface<ILogger>(), provider: FileLogger, scoped: true }
|
|
111
|
+
* ]
|
|
112
|
+
* });
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
scoped?: boolean;
|
|
90
116
|
}
|
|
91
117
|
|
|
92
118
|
/**
|
package/src/unplugin/index.ts
CHANGED
|
@@ -5,46 +5,35 @@ import { GraphValidator } from '../generator/GraphValidator';
|
|
|
5
5
|
import { Generator } from '../generator/Generator';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Neo-Syringe build plugin for Vite, Rollup, Webpack, and other bundlers.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Intercepts files containing `defineBuilderConfig` calls, analyzes the
|
|
11
|
+
* dependency graph, validates it, and replaces the configuration with
|
|
12
|
+
* generated factory code.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
|
+
* ```typescript
|
|
15
16
|
* // vite.config.ts
|
|
16
17
|
* import { neoSyringePlugin } from '@djodjonx/neo-syringe/plugin';
|
|
17
18
|
*
|
|
18
19
|
* export default defineConfig({
|
|
19
|
-
* plugins: [neoSyringePlugin.vite()]
|
|
20
|
+
* plugins: [neoSyringePlugin.vite()]
|
|
20
21
|
* });
|
|
22
|
+
* ```
|
|
21
23
|
*/
|
|
22
|
-
export const neoSyringePlugin = createUnplugin((
|
|
24
|
+
export const neoSyringePlugin = createUnplugin(() => {
|
|
23
25
|
return {
|
|
24
26
|
name: 'neo-syringe-plugin',
|
|
25
|
-
|
|
26
|
-
* Includes .ts and .tsx files for transformation.
|
|
27
|
-
* @param id - The file path.
|
|
28
|
-
*/
|
|
27
|
+
|
|
29
28
|
transformInclude(id) {
|
|
30
29
|
return id.endsWith('.ts') || id.endsWith('.tsx');
|
|
31
30
|
},
|
|
32
|
-
|
|
33
|
-
* Transforms the code by replacing container definitions with generated factories.
|
|
34
|
-
* @param code - The source code.
|
|
35
|
-
* @param id - The file path.
|
|
36
|
-
*/
|
|
31
|
+
|
|
37
32
|
transform(code, id) {
|
|
38
33
|
if (!code.includes('defineBuilderConfig')) return;
|
|
39
34
|
|
|
40
|
-
// naive check, but saves performance.
|
|
41
|
-
|
|
42
|
-
// We need to parse this file to see if it really defines a container.
|
|
43
|
-
// We need a full Program to resolve types across files.
|
|
44
|
-
// Using existing tsconfig if possible.
|
|
45
|
-
|
|
46
35
|
const configFile = ts.findConfigFile(process.cwd(), ts.sys.fileExists, 'tsconfig.json');
|
|
47
|
-
if (!configFile) return;
|
|
36
|
+
if (!configFile) return;
|
|
48
37
|
|
|
49
38
|
const { config } = ts.readConfigFile(configFile, ts.sys.readFile);
|
|
50
39
|
const { options: compilerOptions } = ts.parseJsonConfigFileContent(config, ts.sys, process.cwd());
|
|
@@ -53,30 +42,13 @@ export const neoSyringePlugin = createUnplugin((_options) => {
|
|
|
53
42
|
const analyzer = new Analyzer(program);
|
|
54
43
|
const graph = analyzer.extract();
|
|
55
44
|
|
|
56
|
-
if (graph.nodes.size === 0) return;
|
|
45
|
+
if (graph.nodes.size === 0) return;
|
|
57
46
|
|
|
58
|
-
// Validate
|
|
59
47
|
const validator = new GraphValidator();
|
|
60
48
|
validator.validate(graph);
|
|
61
49
|
|
|
62
|
-
// Generate
|
|
63
50
|
const generator = new Generator(graph);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// We need to replace the export.
|
|
67
|
-
// Strategy: Use the generated code AS the content of this file?
|
|
68
|
-
// If the file *only* exports the container, yes.
|
|
69
|
-
// But if it exports other things, we might break them.
|
|
70
|
-
|
|
71
|
-
// Safer strategy:
|
|
72
|
-
// Replace the `createContainer()...build()` expression with the object literal from generated code.
|
|
73
|
-
// But the generated code includes imports. Imports must be at top level.
|
|
74
|
-
|
|
75
|
-
// So we must REPLACE the whole file content with the generated code.
|
|
76
|
-
// This implies the user should put the container in a dedicated file.
|
|
77
|
-
// We can warn or document this.
|
|
78
|
-
|
|
79
|
-
return generatedCode;
|
|
51
|
+
return generator.generate();
|
|
80
52
|
},
|
|
81
53
|
};
|
|
82
54
|
});
|
|
@@ -49,8 +49,8 @@ describe('Analyzer', () => {
|
|
|
49
49
|
class B {}
|
|
50
50
|
export const container = defineBuilderConfig({
|
|
51
51
|
injections: [
|
|
52
|
-
{ token: A,
|
|
53
|
-
{ token: B,
|
|
52
|
+
{ token: A, lifecycle: 'transient' },
|
|
53
|
+
{ token: B, lifecycle: 'singleton' }
|
|
54
54
|
]
|
|
55
55
|
});
|
|
56
56
|
`;
|
|
@@ -69,7 +69,7 @@ describe('Analyzer', () => {
|
|
|
69
69
|
const analyzer = new Analyzer(program);
|
|
70
70
|
const graph = analyzer.extract();
|
|
71
71
|
|
|
72
|
-
expect(graph.nodes.get('A')?.service.
|
|
73
|
-
expect(graph.nodes.get('B')?.service.
|
|
72
|
+
expect(graph.nodes.get('A')?.service.lifecycle).toBe('transient');
|
|
73
|
+
expect(graph.nodes.get('B')?.service.lifecycle).toBe('singleton');
|
|
74
74
|
});
|
|
75
75
|
});
|
|
@@ -80,7 +80,7 @@ describe('Analyzer - Declarative Config (defineBuilderConfig)', () => {
|
|
|
80
80
|
|
|
81
81
|
// Since we don't know the ID yet, let's iterate.
|
|
82
82
|
const nodes = Array.from(graph.nodes.values());
|
|
83
|
-
const loggerNode = nodes.find(n => n.service.implementationSymbol
|
|
83
|
+
const loggerNode = nodes.find(n => n.service.implementationSymbol?.getName() === 'ConsoleLogger');
|
|
84
84
|
|
|
85
85
|
expect(loggerNode).toBeDefined();
|
|
86
86
|
expect(loggerNode?.service.type).toBe('explicit');
|
|
@@ -151,7 +151,7 @@ describe('Analyzer - Factory Support', () => {
|
|
|
151
151
|
{
|
|
152
152
|
token: useInterface<IRequest>(),
|
|
153
153
|
provider: () => ({ id: ++counter }),
|
|
154
|
-
|
|
154
|
+
lifecycle: 'transient'
|
|
155
155
|
}
|
|
156
156
|
]
|
|
157
157
|
});
|
|
@@ -163,7 +163,7 @@ describe('Analyzer - Factory Support', () => {
|
|
|
163
163
|
|
|
164
164
|
const node = findNodeByName(graph, 'IRequest');
|
|
165
165
|
expect(node?.service.isFactory).toBe(true);
|
|
166
|
-
expect(node?.service.
|
|
166
|
+
expect(node?.service.lifecycle).toBe('transient');
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
it('should not treat class as factory', () => {
|