@djodjonx/neosyringe-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,69 @@
1
+ import { t as DependencyGraph } from "../types-DeLOEpiR.cjs";
2
+
3
+ //#region src/generator/Generator.d.ts
4
+ /**
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
11
+ */
12
+ declare class Generator {
13
+ private graph;
14
+ private useDirectSymbolNames;
15
+ /**
16
+ * Creates a new Generator.
17
+ * @param graph - The validated dependency graph to generate code from.
18
+ * @param useDirectSymbolNames - If true, uses symbol names directly without import prefixes.
19
+ */
20
+ constructor(graph: DependencyGraph, useDirectSymbolNames?: boolean);
21
+ /**
22
+ * Generates the complete container code as a string.
23
+ * @returns TypeScript source code for the generated container.
24
+ */
25
+ generate(): string;
26
+ /**
27
+ * Generates only the instantiation expression: new NeoContainer(...)
28
+ * This is used to replace defineBuilderConfig(...) in the source.
29
+ */
30
+ generateInstantiation(): string;
31
+ /**
32
+ * Sorts services in topological order (dependencies before dependents).
33
+ * @returns Array of TokenIds in dependency order.
34
+ */
35
+ private topologicalSort;
36
+ /**
37
+ * Creates a valid JavaScript function name from a token ID.
38
+ * @param tokenId - The token identifier.
39
+ * @returns A sanitized factory function name.
40
+ */
41
+ private getFactoryName;
42
+ }
43
+ //#endregion
44
+ //#region src/generator/GraphValidator.d.ts
45
+ /**
46
+ * Validates the dependency graph for correctness.
47
+ * Detects circular dependencies, missing bindings, and duplicates.
48
+ */
49
+ declare class GraphValidator {
50
+ /**
51
+ * Validates the graph structure.
52
+ *
53
+ * @param graph - The dependency graph to validate.
54
+ * @throws {Error} If a circular dependency or missing binding is detected.
55
+ */
56
+ validate(graph: DependencyGraph): void;
57
+ /**
58
+ * Recursive Helper for Cycle Detection (DFS).
59
+ *
60
+ * @param nodeId - The current node ID.
61
+ * @param graph - The graph.
62
+ * @param visited - Set of all visited nodes.
63
+ * @param stack - Set of nodes in the current recursion stack (path).
64
+ * @param parentTokens - Tokens from parent container (skip traversal).
65
+ */
66
+ private detectCycle;
67
+ }
68
+ //#endregion
69
+ export { Generator, GraphValidator };
@@ -0,0 +1,69 @@
1
+ import { t as DependencyGraph } from "../types-EnrcFw9C.mjs";
2
+
3
+ //#region src/generator/Generator.d.ts
4
+ /**
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
11
+ */
12
+ declare class Generator {
13
+ private graph;
14
+ private useDirectSymbolNames;
15
+ /**
16
+ * Creates a new Generator.
17
+ * @param graph - The validated dependency graph to generate code from.
18
+ * @param useDirectSymbolNames - If true, uses symbol names directly without import prefixes.
19
+ */
20
+ constructor(graph: DependencyGraph, useDirectSymbolNames?: boolean);
21
+ /**
22
+ * Generates the complete container code as a string.
23
+ * @returns TypeScript source code for the generated container.
24
+ */
25
+ generate(): string;
26
+ /**
27
+ * Generates only the instantiation expression: new NeoContainer(...)
28
+ * This is used to replace defineBuilderConfig(...) in the source.
29
+ */
30
+ generateInstantiation(): string;
31
+ /**
32
+ * Sorts services in topological order (dependencies before dependents).
33
+ * @returns Array of TokenIds in dependency order.
34
+ */
35
+ private topologicalSort;
36
+ /**
37
+ * Creates a valid JavaScript function name from a token ID.
38
+ * @param tokenId - The token identifier.
39
+ * @returns A sanitized factory function name.
40
+ */
41
+ private getFactoryName;
42
+ }
43
+ //#endregion
44
+ //#region src/generator/GraphValidator.d.ts
45
+ /**
46
+ * Validates the dependency graph for correctness.
47
+ * Detects circular dependencies, missing bindings, and duplicates.
48
+ */
49
+ declare class GraphValidator {
50
+ /**
51
+ * Validates the graph structure.
52
+ *
53
+ * @param graph - The dependency graph to validate.
54
+ * @throws {Error} If a circular dependency or missing binding is detected.
55
+ */
56
+ validate(graph: DependencyGraph): void;
57
+ /**
58
+ * Recursive Helper for Cycle Detection (DFS).
59
+ *
60
+ * @param nodeId - The current node ID.
61
+ * @param graph - The graph.
62
+ * @param visited - Set of all visited nodes.
63
+ * @param stack - Set of nodes in the current recursion stack (path).
64
+ * @param parentTokens - Tokens from parent container (skip traversal).
65
+ */
66
+ private detectCycle;
67
+ }
68
+ //#endregion
69
+ export { Generator, GraphValidator };
@@ -0,0 +1,247 @@
1
+ //#region src/generator/Generator.ts
2
+ /**
3
+ * Generates TypeScript code for the dependency injection container.
4
+ *
5
+ * Takes a validated dependency graph and produces:
6
+ * - Import statements for all dependencies
7
+ * - Factory functions for each service
8
+ * - A NeoContainer class with resolve logic
9
+ */
10
+ var Generator = class {
11
+ /**
12
+ * Creates a new Generator.
13
+ * @param graph - The validated dependency graph to generate code from.
14
+ * @param useDirectSymbolNames - If true, uses symbol names directly without import prefixes.
15
+ */
16
+ constructor(graph, useDirectSymbolNames = false) {
17
+ this.graph = graph;
18
+ this.useDirectSymbolNames = useDirectSymbolNames;
19
+ }
20
+ /**
21
+ * Generates the complete container code as a string.
22
+ * @returns TypeScript source code for the generated container.
23
+ */
24
+ generate() {
25
+ const sorted = this.topologicalSort();
26
+ const imports = /* @__PURE__ */ new Map();
27
+ const factories = [];
28
+ const resolveCases = [];
29
+ const getImport = (symbol) => {
30
+ if (this.useDirectSymbolNames) return symbol.getName();
31
+ const decl = symbol.declarations?.[0];
32
+ if (!decl) return "UNKNOWN";
33
+ const filePath = decl.getSourceFile().fileName;
34
+ if (!imports.has(filePath)) {
35
+ const alias = `Import_${imports.size}`;
36
+ imports.set(filePath, alias);
37
+ }
38
+ return `${imports.get(filePath)}.${symbol.getName()}`;
39
+ };
40
+ for (const tokenId of sorted) {
41
+ const node = this.graph.nodes.get(tokenId);
42
+ if (!node) continue;
43
+ if (node.service.type === "parent") continue;
44
+ const factoryId = this.getFactoryName(tokenId);
45
+ if (node.service.isFactory && node.service.factorySource) {
46
+ const userFactory = node.service.factorySource;
47
+ factories.push(`
48
+ private ${factoryId}(): any {
49
+ const userFactory = ${userFactory};
50
+ return userFactory(this);
51
+ }`);
52
+ } else {
53
+ const className = node.service.implementationSymbol ? getImport(node.service.implementationSymbol) : "undefined";
54
+ const args = node.dependencies.map((depId) => {
55
+ const depNode = this.graph.nodes.get(depId);
56
+ if (!depNode) return "undefined";
57
+ if (depNode.service.isInterfaceToken) return `this.resolve("${depNode.service.tokenId}")`;
58
+ else if (depNode.service.tokenSymbol) return `this.resolve(${getImport(depNode.service.tokenSymbol)})`;
59
+ else if (depNode.service.implementationSymbol) return `this.resolve(${getImport(depNode.service.implementationSymbol)})`;
60
+ return "undefined";
61
+ }).join(", ");
62
+ factories.push(`
63
+ private ${factoryId}(): any {
64
+ return new ${className}(${args});
65
+ }`);
66
+ }
67
+ const isTransient = node.service.lifecycle === "transient";
68
+ let tokenKey;
69
+ let tokenCheck;
70
+ if (node.service.isInterfaceToken) {
71
+ tokenKey = `"${node.service.tokenId}"`;
72
+ tokenCheck = `if (token === "${node.service.tokenId}")`;
73
+ } else if (node.service.tokenSymbol) {
74
+ const tokenClass = getImport(node.service.tokenSymbol);
75
+ tokenKey = tokenClass;
76
+ tokenCheck = `if (token === ${tokenClass})`;
77
+ } else if (node.service.implementationSymbol) {
78
+ const className = getImport(node.service.implementationSymbol);
79
+ tokenKey = className;
80
+ tokenCheck = `if (token === ${className})`;
81
+ } else {
82
+ tokenKey = `"${node.service.tokenId}"`;
83
+ tokenCheck = `if (token === "${node.service.tokenId}")`;
84
+ }
85
+ const creationLogic = isTransient ? `return this.${factoryId}();` : `
86
+ if (!this.instances.has(${tokenKey})) {
87
+ const instance = this.${factoryId}();
88
+ this.instances.set(${tokenKey}, instance);
89
+ return instance;
90
+ }
91
+ return this.instances.get(${tokenKey});
92
+ `;
93
+ resolveCases.push(`${tokenCheck} { ${creationLogic} }`);
94
+ }
95
+ const importLines = [];
96
+ if (!this.useDirectSymbolNames) for (const [filePath, alias] of imports) importLines.push(`import * as ${alias} from '${filePath}';`);
97
+ return `
98
+ ${importLines.join("\n")}
99
+
100
+ // -- Container --
101
+ export class NeoContainer {
102
+ private instances = new Map<any, any>();
103
+
104
+ // -- Factories --
105
+ ${factories.join("\n ")}
106
+
107
+ constructor(
108
+ private parent?: any,
109
+ private legacy?: any[],
110
+ private name: string = 'NeoContainer'
111
+ ) {}
112
+
113
+ public resolve(token: any): any {
114
+ // 1. Try to resolve locally (or create if singleton)
115
+ const result = this.resolveLocal(token);
116
+ if (result !== undefined) return result;
117
+
118
+ // 2. Delegate to parent
119
+ if (this.parent) {
120
+ try {
121
+ return this.parent.resolve(token);
122
+ } catch (e) {
123
+ // Ignore error, try legacy
124
+ }
125
+ }
126
+
127
+ // 3. Delegate to legacy
128
+ if (this.legacy) {
129
+ for (const legacyContainer of this.legacy) {
130
+ // Assume legacy container has resolve()
131
+ try {
132
+ if (legacyContainer.resolve) return legacyContainer.resolve(token);
133
+ } catch (e) {
134
+ // Ignore
135
+ }
136
+ }
137
+ }
138
+
139
+ throw new Error(\`[\${this.name}] Service not found or token not registered: \${token}\`);
140
+ }
141
+
142
+ private resolveLocal(token: any): any {
143
+ ${resolveCases.join("\n ")}
144
+ return undefined;
145
+ }
146
+
147
+ // For debugging/inspection
148
+ public get _graph() {
149
+ return ${JSON.stringify(Array.from(this.graph.nodes.keys()))};
150
+ }
151
+ }
152
+ ${this.useDirectSymbolNames ? "" : `
153
+ // -- Container Instance --
154
+ export const ${this.graph.exportedVariableName || "container"} = ${this.generateInstantiation()};
155
+ `}`;
156
+ }
157
+ /**
158
+ * Generates only the instantiation expression: new NeoContainer(...)
159
+ * This is used to replace defineBuilderConfig(...) in the source.
160
+ */
161
+ generateInstantiation() {
162
+ return `new NeoContainer(${this.graph.buildArguments && this.graph.buildArguments.length > 0 ? this.graph.buildArguments[0] : "undefined"}, ${this.graph.legacyContainers ? `[${this.graph.legacyContainers.join(", ")}]` : "undefined"}, ${this.graph.containerName ? `'${this.graph.containerName}'` : "undefined"})`;
163
+ }
164
+ /**
165
+ * Sorts services in topological order (dependencies before dependents).
166
+ * @returns Array of TokenIds in dependency order.
167
+ */
168
+ topologicalSort() {
169
+ const visited = /* @__PURE__ */ new Set();
170
+ const sorted = [];
171
+ const visit = (id) => {
172
+ if (visited.has(id)) return;
173
+ visited.add(id);
174
+ const node = this.graph.nodes.get(id);
175
+ if (node) {
176
+ for (const depId of node.dependencies) visit(depId);
177
+ sorted.push(id);
178
+ }
179
+ };
180
+ for (const id of this.graph.nodes.keys()) visit(id);
181
+ return sorted;
182
+ }
183
+ /**
184
+ * Creates a valid JavaScript function name from a token ID.
185
+ * @param tokenId - The token identifier.
186
+ * @returns A sanitized factory function name.
187
+ */
188
+ getFactoryName(tokenId) {
189
+ return `create_${tokenId.replace(/[^a-zA-Z0-9]/g, "_")}`;
190
+ }
191
+ };
192
+
193
+ //#endregion
194
+ //#region src/generator/GraphValidator.ts
195
+ /**
196
+ * Validates the dependency graph for correctness.
197
+ * Detects circular dependencies, missing bindings, and duplicates.
198
+ */
199
+ var GraphValidator = class {
200
+ /**
201
+ * Validates the graph structure.
202
+ *
203
+ * @param graph - The dependency graph to validate.
204
+ * @throws {Error} If a circular dependency or missing binding is detected.
205
+ */
206
+ validate(graph) {
207
+ const visited = /* @__PURE__ */ new Set();
208
+ const recursionStack = /* @__PURE__ */ new Set();
209
+ const parentTokens = graph.parentProvidedTokens ?? /* @__PURE__ */ new Set();
210
+ for (const [nodeId, node] of graph.nodes) if (parentTokens.has(nodeId)) {
211
+ if (node.service.isScoped) continue;
212
+ throw new Error(`Duplicate registration: '${nodeId}' is already registered in the parent container. Use 'scoped: true' to override the parent's registration intentionally.`);
213
+ }
214
+ for (const [nodeId, node] of graph.nodes) for (const depId of node.dependencies) {
215
+ const isProvidedLocally = graph.nodes.has(depId);
216
+ const isProvidedByParent = parentTokens.has(depId);
217
+ if (!isProvidedLocally && !isProvidedByParent) {
218
+ const serviceName = nodeId;
219
+ throw new Error(`Missing binding: Service '${serviceName}' depends on '${depId}', but no provider was registered.`);
220
+ }
221
+ }
222
+ for (const nodeId of graph.nodes.keys()) if (!visited.has(nodeId)) this.detectCycle(nodeId, graph, visited, recursionStack, parentTokens);
223
+ }
224
+ /**
225
+ * Recursive Helper for Cycle Detection (DFS).
226
+ *
227
+ * @param nodeId - The current node ID.
228
+ * @param graph - The graph.
229
+ * @param visited - Set of all visited nodes.
230
+ * @param stack - Set of nodes in the current recursion stack (path).
231
+ * @param parentTokens - Tokens from parent container (skip traversal).
232
+ */
233
+ detectCycle(nodeId, graph, visited, stack, parentTokens) {
234
+ visited.add(nodeId);
235
+ stack.add(nodeId);
236
+ const node = graph.nodes.get(nodeId);
237
+ if (node) for (const depId of node.dependencies) {
238
+ if (parentTokens.has(depId)) continue;
239
+ if (!visited.has(depId)) this.detectCycle(depId, graph, visited, stack, parentTokens);
240
+ else if (stack.has(depId)) throw new Error(`Circular dependency detected: ${[...stack, depId].join(" -> ")}`);
241
+ }
242
+ stack.delete(nodeId);
243
+ }
244
+ };
245
+
246
+ //#endregion
247
+ export { Generator, GraphValidator };
@@ -0,0 +1,84 @@
1
+ import { Node, Symbol } from "typescript";
2
+
3
+ //#region src/analyzer/types.d.ts
4
+ /**
5
+ * Unique identifier for a token (interface name or class name).
6
+ */
7
+ type TokenId = string;
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
+ */
15
+ type RegistrationType = 'explicit' | 'autowire' | 'parent' | 'factory';
16
+ /**
17
+ * Represents a single service definition in the dependency graph.
18
+ */
19
+ interface ServiceDefinition {
20
+ /** Unique identifier for this service token. */
21
+ tokenId: TokenId;
22
+ /**
23
+ * The TypeScript symbol of the concrete class implementation.
24
+ * Undefined if the provider is a factory function.
25
+ */
26
+ implementationSymbol?: Symbol;
27
+ /**
28
+ * The TypeScript symbol of the token (if it is a Class/Value).
29
+ * Undefined if the token is a virtual interface ID.
30
+ */
31
+ tokenSymbol?: Symbol;
32
+ /** The source node where the registration happened (for error reporting). */
33
+ registrationNode: Node;
34
+ /** How this service was registered. */
35
+ type: RegistrationType;
36
+ /** Lifecycle of the service instance. */
37
+ lifecycle: 'singleton' | 'transient';
38
+ /** True if the token is an interface (requires string literal key). */
39
+ isInterfaceToken?: boolean;
40
+ /** True if the token is a value token for primitives. */
41
+ isValueToken?: boolean;
42
+ /** True if the provider is a factory function. */
43
+ isFactory?: boolean;
44
+ /** The raw source text of the factory function (for code generation). */
45
+ factorySource?: string;
46
+ /** True if this injection is scoped to the local container. */
47
+ isScoped?: boolean;
48
+ }
49
+ /**
50
+ * A node in the dependency graph representing a service and its dependencies.
51
+ */
52
+ interface DependencyNode {
53
+ /** The service definition. */
54
+ service: ServiceDefinition;
55
+ /** Token IDs of dependencies required by this service's constructor. */
56
+ dependencies: TokenId[];
57
+ }
58
+ /**
59
+ * Complete dependency graph for a container configuration.
60
+ */
61
+ interface DependencyGraph {
62
+ /** All service nodes indexed by their token ID. */
63
+ nodes: Map<TokenId, DependencyNode>;
64
+ /** Root services that are explicitly requested or exported. */
65
+ roots: TokenId[];
66
+ /** Arguments passed to the .build() method call (raw source text). */
67
+ buildArguments?: string[];
68
+ /** Optional container name for debugging. */
69
+ containerName?: string;
70
+ /** The exported variable name used for the container (e.g., 'appContainer'). */
71
+ exportedVariableName?: string;
72
+ /** Start position of the variable statement containing defineBuilderConfig (where to insert generated code). */
73
+ variableStatementStart?: number;
74
+ /** Start position of the defineBuilderConfig expression in the source file. */
75
+ defineBuilderConfigStart?: number;
76
+ /** End position of the defineBuilderConfig expression in the source file. */
77
+ defineBuilderConfigEnd?: number;
78
+ /** Legacy container variable names to delegate to. */
79
+ legacyContainers?: string[];
80
+ /** Tokens provided by the parent container (used for validation). */
81
+ parentProvidedTokens?: Set<TokenId>;
82
+ }
83
+ //#endregion
84
+ export { TokenId as a, ServiceDefinition as i, DependencyNode as n, RegistrationType as r, DependencyGraph as t };
@@ -0,0 +1,84 @@
1
+ import { Node, Symbol } from "typescript";
2
+
3
+ //#region src/analyzer/types.d.ts
4
+ /**
5
+ * Unique identifier for a token (interface name or class name).
6
+ */
7
+ type TokenId = string;
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
+ */
15
+ type RegistrationType = 'explicit' | 'autowire' | 'parent' | 'factory';
16
+ /**
17
+ * Represents a single service definition in the dependency graph.
18
+ */
19
+ interface ServiceDefinition {
20
+ /** Unique identifier for this service token. */
21
+ tokenId: TokenId;
22
+ /**
23
+ * The TypeScript symbol of the concrete class implementation.
24
+ * Undefined if the provider is a factory function.
25
+ */
26
+ implementationSymbol?: Symbol;
27
+ /**
28
+ * The TypeScript symbol of the token (if it is a Class/Value).
29
+ * Undefined if the token is a virtual interface ID.
30
+ */
31
+ tokenSymbol?: Symbol;
32
+ /** The source node where the registration happened (for error reporting). */
33
+ registrationNode: Node;
34
+ /** How this service was registered. */
35
+ type: RegistrationType;
36
+ /** Lifecycle of the service instance. */
37
+ lifecycle: 'singleton' | 'transient';
38
+ /** True if the token is an interface (requires string literal key). */
39
+ isInterfaceToken?: boolean;
40
+ /** True if the token is a value token for primitives. */
41
+ isValueToken?: boolean;
42
+ /** True if the provider is a factory function. */
43
+ isFactory?: boolean;
44
+ /** The raw source text of the factory function (for code generation). */
45
+ factorySource?: string;
46
+ /** True if this injection is scoped to the local container. */
47
+ isScoped?: boolean;
48
+ }
49
+ /**
50
+ * A node in the dependency graph representing a service and its dependencies.
51
+ */
52
+ interface DependencyNode {
53
+ /** The service definition. */
54
+ service: ServiceDefinition;
55
+ /** Token IDs of dependencies required by this service's constructor. */
56
+ dependencies: TokenId[];
57
+ }
58
+ /**
59
+ * Complete dependency graph for a container configuration.
60
+ */
61
+ interface DependencyGraph {
62
+ /** All service nodes indexed by their token ID. */
63
+ nodes: Map<TokenId, DependencyNode>;
64
+ /** Root services that are explicitly requested or exported. */
65
+ roots: TokenId[];
66
+ /** Arguments passed to the .build() method call (raw source text). */
67
+ buildArguments?: string[];
68
+ /** Optional container name for debugging. */
69
+ containerName?: string;
70
+ /** The exported variable name used for the container (e.g., 'appContainer'). */
71
+ exportedVariableName?: string;
72
+ /** Start position of the variable statement containing defineBuilderConfig (where to insert generated code). */
73
+ variableStatementStart?: number;
74
+ /** Start position of the defineBuilderConfig expression in the source file. */
75
+ defineBuilderConfigStart?: number;
76
+ /** End position of the defineBuilderConfig expression in the source file. */
77
+ defineBuilderConfigEnd?: number;
78
+ /** Legacy container variable names to delegate to. */
79
+ legacyContainers?: string[];
80
+ /** Tokens provided by the parent container (used for validation). */
81
+ parentProvidedTokens?: Set<TokenId>;
82
+ }
83
+ //#endregion
84
+ export { TokenId as a, ServiceDefinition as i, DependencyNode as n, RegistrationType as r, DependencyGraph as t };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@djodjonx/neosyringe-core",
3
+ "version": "0.1.0",
4
+ "description": "Core analysis and generation logic for NeoSyringe",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.mjs",
8
+ "types": "dist/index.d.mts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.mts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./analyzer": {
16
+ "types": "./dist/analyzer/index.d.mts",
17
+ "import": "./dist/analyzer/index.mjs",
18
+ "require": "./dist/analyzer/index.cjs"
19
+ },
20
+ "./generator": {
21
+ "types": "./dist/generator/index.d.mts",
22
+ "import": "./dist/generator/index.mjs",
23
+ "require": "./dist/generator/index.cjs"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "dependencies": {
33
+ "@djodjonx/neosyringe": "0.1.0"
34
+ },
35
+ "peerDependencies": {
36
+ "typescript": ">=5.0.0"
37
+ },
38
+ "devDependencies": {
39
+ "tsdown": "0.20.0-beta.3",
40
+ "typescript": "^5.9.3",
41
+ "vitest": "^4.0.17"
42
+ },
43
+ "scripts": {
44
+ "build": "tsdown",
45
+ "test": "vitest run"
46
+ }
47
+ }