@streetjs/container 1.0.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,78 @@
1
+ # Architecture — @streetjs/container
2
+
3
+ ## Purpose
4
+
5
+ `@streetjs/container` is the StreetJS inversion-of-control core: a small,
6
+ dependency-injection container that other framework layers (controllers,
7
+ services, repositories, CLI kernels) use to wire their dependency graphs. It has
8
+ a single runtime dependency, `reflect-metadata`, and no coupling to HTTP,
9
+ databases, or any other subsystem.
10
+
11
+ ## Design
12
+
13
+ ### A single process-wide singleton
14
+
15
+ `Container` has a private constructor and a static `instance`. Consumers reach
16
+ it via `Container.getInstance()` or the exported `container` binding. A single
17
+ registry means a resolved dependency is shared everywhere it is injected — the
18
+ framework's services are effectively singletons by default.
19
+
20
+ Internally the container keeps two maps/sets:
21
+
22
+ - `singletons: Map<Constructor, object>` — resolved (or pre-registered) instances.
23
+ - `resolving: Set<Constructor>` — the tokens currently on the resolution stack,
24
+ used for cycle detection.
25
+
26
+ ### Resolution algorithm
27
+
28
+ `resolve(token)`:
29
+
30
+ 1. Return the cached singleton if present.
31
+ 2. If `token` is already in `resolving`, throw a **circular dependency** error
32
+ annotated with the full resolution chain.
33
+ 3. Add `token` to `resolving`, then read its constructor parameter types from
34
+ the `design:paramtypes` metadata that `emitDecoratorMetadata` emits.
35
+ 4. Recursively `resolve` each parameter:
36
+ - A missing type or `Object` (interfaces, primitives, undecorated unions
37
+ erase to these) is unresolvable — throw a descriptive error naming the
38
+ chain and pointing at `emitDecoratorMetadata`/`@Injectable`.
39
+ - If a nested resolution throws, wrap the message with the chain — unless it
40
+ is already chain-annotated, in which case it is rethrown unchanged to avoid
41
+ double-wrapping.
42
+ 5. Construct the instance, cache it, and remove `token` from `resolving` in a
43
+ `finally` so a failed resolution never leaves stale state.
44
+
45
+ ### `@Injectable()`
46
+
47
+ The decorator writes a marker symbol via `Reflect.defineMetadata`. Its more
48
+ important side effect is enabling TypeScript to emit `design:paramtypes` for the
49
+ class — the metadata the resolver depends on.
50
+
51
+ ### The `Constructor` type
52
+
53
+ `Constructor<T> = new (...args: any[]) => T` is the token type used throughout.
54
+ It lives here and is re-exported by the `streetjs` framework's `core/types.ts`,
55
+ keeping a single definition (dependency inversion, matching how `IpcMessage` and
56
+ `TelemetrySample` are sourced from their own packages).
57
+
58
+ ## Relationship to core
59
+
60
+ The framework's `src/core/container.ts` re-exports this package verbatim, and
61
+ `src/core/types.ts` re-exports `Constructor` from it. Core's
62
+ `prebuild`/`prebuild:app` hooks compile this package before core, and the
63
+ Dockerfile builds it and dereferences the workspace symlink into the runtime
64
+ image.
65
+
66
+ ## Testing
67
+
68
+ The suite runs with no external services: singleton identity, constructor
69
+ injection with shared sub-dependencies, cycle detection (via explicit
70
+ `design:paramtypes` metadata to avoid forward-reference temporal-dead-zones),
71
+ unresolvable-interface errors, failed-construction wrapping, and `reset`
72
+ semantics. Branch coverage is ≥96%.
73
+
74
+ ## Non-goals
75
+
76
+ - No scopes/lifetimes beyond the process singleton (no request/transient scopes).
77
+ - No property or method injection — constructor injection only.
78
+ - No async factories or conditional bindings.
package/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@streetjs/container` are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0]
9
+
10
+ ### Added
11
+
12
+ - Initial standalone release of the StreetJS dependency injection container,
13
+ extracted verbatim from the `streetjs` core (`src/core/container.ts`).
14
+ - `Container` singleton with `resolve`, `register`, `has`, and `reset`, plus the
15
+ exported `container` instance and `Container.getInstance()`.
16
+ - Constructor-injection resolution driven by `design:paramtypes` metadata, with
17
+ singleton caching across the dependency graph.
18
+ - Circular-dependency detection reporting the full resolution chain.
19
+ - Descriptive errors for unresolvable (interface/primitive/undecorated)
20
+ dependencies, with chain-aware wrapping that avoids double annotation.
21
+ - `@Injectable()` class decorator.
22
+ - `Constructor<T>` type utility (also re-exported by the framework core).
23
+ - `reflect-metadata` as the sole runtime dependency; ESM.
24
+ - ≥96% branch coverage and a runnable integration example.
25
+
26
+ [1.0.0]: https://github.com/hassanmubiru/StreetJS/releases/tag/container-v1.0.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 street contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # @streetjs/container
2
+
3
+ The StreetJS dependency injection container: a process-wide singleton IoC
4
+ registry that resolves constructor-injected dependency trees, detects circular
5
+ dependencies, and exposes an `@Injectable()` class decorator. ESM,
6
+ strict-TypeScript, backed by `reflect-metadata`.
7
+
8
+ This is the standalone home of the container that also backs the `streetjs`
9
+ framework. The framework re-exports this package, so there is a single source of
10
+ truth.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install @streetjs/container reflect-metadata
16
+ ```
17
+
18
+ Import `reflect-metadata` **once** at your application entry point, and enable
19
+ decorator metadata in your `tsconfig.json`:
20
+
21
+ ```jsonc
22
+ {
23
+ "compilerOptions": {
24
+ "experimentalDecorators": true,
25
+ "emitDecoratorMetadata": true
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```ts
33
+ import 'reflect-metadata';
34
+ import { Injectable, container } from '@streetjs/container';
35
+
36
+ @Injectable()
37
+ class Database {
38
+ query(sql: string) { /* ... */ }
39
+ }
40
+
41
+ @Injectable()
42
+ class UserService {
43
+ constructor(private readonly db: Database) {}
44
+ }
45
+
46
+ // Database is constructed once and injected as a singleton.
47
+ const users = container.resolve(UserService);
48
+ ```
49
+
50
+ ## API
51
+
52
+ ### `@Injectable()`
53
+
54
+ Class decorator that marks a class as participating in DI. Applying it also
55
+ triggers TypeScript's `design:paramtypes` metadata emission, which the container
56
+ reads to discover constructor dependencies.
57
+
58
+ ### `container` / `Container`
59
+
60
+ A single shared `Container` instance is exported as `container`
61
+ (`Container.getInstance()` returns the same singleton).
62
+
63
+ | Method | Description |
64
+ | ------ | ----------- |
65
+ | `resolve(token)` | Return the singleton for `token`, constructing it and its dependency tree on first use. |
66
+ | `register(token, instance)` | Register a pre-built instance so `resolve(token)` returns it. |
67
+ | `has(token)` | `true` if the token has been resolved or registered. |
68
+ | `reset()` | Clear all instances — primarily for tests. |
69
+
70
+ ### Circular-dependency detection
71
+
72
+ If resolution re-enters a token already on the resolution stack, `resolve`
73
+ throws with the full chain (`A -> B -> A`) instead of overflowing the stack.
74
+
75
+ ### Unresolvable dependencies
76
+
77
+ A constructor parameter typed as an interface, a primitive, or an
78
+ un-`@Injectable` value erases to `Object`/undefined in emitted metadata. The
79
+ container throws a clear error naming the resolution chain and suggesting you
80
+ enable `emitDecoratorMetadata` and decorate the dependency.
81
+
82
+ ## Example
83
+
84
+ A complete runnable example lives in
85
+ [`src/examples/integration.ts`](./src/examples/integration.ts):
86
+
87
+ ```bash
88
+ npm run example -w packages/container
89
+ ```
90
+
91
+ ## License
92
+
93
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,23 @@
1
+ import 'reflect-metadata';
2
+ import type { Constructor } from './types.js';
3
+ /** Mark a class as injectable and register its dependencies */
4
+ export declare function Injectable(): ClassDecorator;
5
+ /** Container manages singleton instances and resolves dependency trees */
6
+ export declare class Container {
7
+ private static readonly instance;
8
+ private readonly singletons;
9
+ private readonly resolving;
10
+ private constructor();
11
+ static getInstance(): Container;
12
+ /** Register a pre-built instance */
13
+ register<T extends object>(token: Constructor<T>, instance: T): void;
14
+ /** Resolve a class, creating it if not already instantiated */
15
+ resolve<T extends object>(token: Constructor<T>): T;
16
+ /** Remove all registered instances (useful in tests) */
17
+ reset(): void;
18
+ /** Check if a token has been resolved or registered */
19
+ has(token: Constructor): boolean;
20
+ }
21
+ /** Global container singleton */
22
+ export declare const container: Container;
23
+ //# sourceMappingURL=container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAGA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,+DAA+D;AAC/D,wBAAgB,UAAU,IAAI,cAAc,CAI3C;AAED,0EAA0E;AAC1E,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAEnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkC;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IAEpD,OAAO;IAEP,MAAM,CAAC,WAAW,IAAI,SAAS;IAI/B,oCAAoC;IACpC,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI;IAIpE,+DAA+D;IAC/D,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC;IAkDnD,wDAAwD;IACxD,KAAK,IAAI,IAAI;IAKb,uDAAuD;IACvD,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO;CAGjC;AAED,iCAAiC;AACjC,eAAO,MAAM,SAAS,WAA0B,CAAC"}
@@ -0,0 +1,78 @@
1
+ // src/container.ts
2
+ // Dependency injection container with singleton registry and circular dep detection.
3
+ import 'reflect-metadata';
4
+ const INJECTABLE_META = Symbol('street:injectable');
5
+ /** Mark a class as injectable and register its dependencies */
6
+ export function Injectable() {
7
+ return (target) => {
8
+ Reflect.defineMetadata(INJECTABLE_META, true, target);
9
+ };
10
+ }
11
+ /** Container manages singleton instances and resolves dependency trees */
12
+ export class Container {
13
+ static instance = new Container();
14
+ singletons = new Map();
15
+ resolving = new Set();
16
+ constructor() { }
17
+ static getInstance() {
18
+ return Container.instance;
19
+ }
20
+ /** Register a pre-built instance */
21
+ register(token, instance) {
22
+ this.singletons.set(token, instance);
23
+ }
24
+ /** Resolve a class, creating it if not already instantiated */
25
+ resolve(token) {
26
+ const existing = this.singletons.get(token);
27
+ if (existing) {
28
+ return existing;
29
+ }
30
+ if (this.resolving.has(token)) {
31
+ throw new Error(`Circular dependency detected while resolving: ${token.name}. ` +
32
+ `Resolution chain: ${[...this.resolving].map((c) => c.name).join(' -> ')} -> ${token.name}`);
33
+ }
34
+ this.resolving.add(token);
35
+ try {
36
+ const paramTypes = Reflect.getMetadata('design:paramtypes', token) ?? [];
37
+ const deps = paramTypes.map((dep) => {
38
+ if (!dep || dep === Object) {
39
+ const chain = [...this.resolving].map((c) => c.name);
40
+ chain.push(token.name);
41
+ throw new Error(`Cannot resolve ${chain.join(' → ')}: got primitive or undefined type. ` +
42
+ `Ensure emitDecoratorMetadata is enabled and the dependency is decorated with @Injectable.`);
43
+ }
44
+ try {
45
+ return this.resolve(dep);
46
+ }
47
+ catch (inner) {
48
+ const chain = [...this.resolving].map((c) => c.name);
49
+ chain.push(dep.name);
50
+ const reason = inner instanceof Error ? inner.message : String(inner);
51
+ // Only wrap if the message doesn't already contain a chain annotation
52
+ if (reason.includes(' → ') || reason.startsWith('Cannot resolve ')) {
53
+ throw inner;
54
+ }
55
+ throw new Error(`Cannot resolve ${chain.join(' → ')}: ${reason}`);
56
+ }
57
+ });
58
+ const instance = new token(...deps);
59
+ this.singletons.set(token, instance);
60
+ return instance;
61
+ }
62
+ finally {
63
+ this.resolving.delete(token);
64
+ }
65
+ }
66
+ /** Remove all registered instances (useful in tests) */
67
+ reset() {
68
+ this.singletons.clear();
69
+ this.resolving.clear();
70
+ }
71
+ /** Check if a token has been resolved or registered */
72
+ has(token) {
73
+ return this.singletons.has(token);
74
+ }
75
+ }
76
+ /** Global container singleton */
77
+ export const container = Container.getInstance();
78
+ //# sourceMappingURL=container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @streetjs/container — the StreetJS dependency injection container.
3
+ *
4
+ * A process-wide singleton IoC registry that resolves constructor-injected
5
+ * dependency trees from `design:paramtypes` metadata, detects circular
6
+ * dependencies, and exposes an `@Injectable()` class decorator. Backed by
7
+ * `reflect-metadata`.
8
+ *
9
+ * ```ts
10
+ * import 'reflect-metadata';
11
+ * import { Injectable, container } from '@streetjs/container';
12
+ *
13
+ * @Injectable() class Db {}
14
+ * @Injectable() class UserService { constructor(readonly db: Db) {} }
15
+ *
16
+ * const svc = container.resolve(UserService); // db injected as a singleton
17
+ * ```
18
+ *
19
+ * > This is the standalone home of the container that also backs the `streetjs`
20
+ * > framework; the framework re-exports it, so there is a single implementation.
21
+ */
22
+ export { Container, Injectable, container } from './container.js';
23
+ export type { Constructor } from './types.js';
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @streetjs/container — the StreetJS dependency injection container.
3
+ *
4
+ * A process-wide singleton IoC registry that resolves constructor-injected
5
+ * dependency trees from `design:paramtypes` metadata, detects circular
6
+ * dependencies, and exposes an `@Injectable()` class decorator. Backed by
7
+ * `reflect-metadata`.
8
+ *
9
+ * ```ts
10
+ * import 'reflect-metadata';
11
+ * import { Injectable, container } from '@streetjs/container';
12
+ *
13
+ * @Injectable() class Db {}
14
+ * @Injectable() class UserService { constructor(readonly db: Db) {} }
15
+ *
16
+ * const svc = container.resolve(UserService); // db injected as a singleton
17
+ * ```
18
+ *
19
+ * > This is the standalone home of the container that also backs the `streetjs`
20
+ * > framework; the framework re-exports it, so there is a single implementation.
21
+ */
22
+ export { Container, Injectable, container } from './container.js';
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A newable class reference — the token type used throughout the container to
3
+ * register, resolve, and key singleton instances.
4
+ */
5
+ export type Constructor<T = object> = new (...args: any[]) => T;
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,MAAM,IAAI,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ // src/types.ts
2
+ // Shared type utilities for the DI container.
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,8CAA8C"}
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "@streetjs/container",
3
+ "version": "1.0.0",
4
+ "description": "StreetJS dependency injection container: a singleton IoC registry with constructor-injection resolution, circular-dependency detection, and an @Injectable decorator. Backed by reflect-metadata.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist/**/*.js",
16
+ "dist/**/*.js.map",
17
+ "dist/**/*.d.ts",
18
+ "dist/**/*.d.ts.map",
19
+ "!dist/**/*.test.js",
20
+ "!dist/**/*.test.js.map",
21
+ "!dist/**/*.test.d.ts",
22
+ "!dist/**/*.test.d.ts.map",
23
+ "!dist/tests/**",
24
+ "!dist/examples/**",
25
+ "README.md",
26
+ "ARCHITECTURE.md",
27
+ "CHANGELOG.md",
28
+ "LICENSE"
29
+ ],
30
+ "c8": {
31
+ "include": ["dist/**/*.js"],
32
+ "exclude": ["dist/tests/**", "dist/examples/**", "dist/types.js"],
33
+ "reporter": ["text", "lcov"],
34
+ "all": true,
35
+ "check-coverage": true,
36
+ "lines": 90,
37
+ "functions": 90,
38
+ "branches": 90,
39
+ "statements": 90
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "test": "node --test dist/tests/*.test.js",
44
+ "coverage": "c8 node --test dist/tests/*.test.js",
45
+ "example": "node dist/examples/integration.js",
46
+ "lint": "tsc --noEmit",
47
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
48
+ },
49
+ "keywords": [
50
+ "streetjs",
51
+ "street-framework",
52
+ "dependency-injection",
53
+ "di",
54
+ "ioc",
55
+ "container",
56
+ "inversion-of-control",
57
+ "injectable",
58
+ "reflect-metadata",
59
+ "typescript",
60
+ "esm"
61
+ ],
62
+ "author": "street contributors",
63
+ "license": "MIT",
64
+ "homepage": "https://hassanmubiru.github.io/StreetJS/",
65
+ "repository": {
66
+ "type": "git",
67
+ "url": "git+https://github.com/hassanmubiru/StreetJS.git"
68
+ },
69
+ "bugs": {
70
+ "url": "https://github.com/hassanmubiru/StreetJS/issues"
71
+ },
72
+ "dependencies": {
73
+ "reflect-metadata": "^0.2.2"
74
+ },
75
+ "devDependencies": {
76
+ "@types/node": "^26.1.0",
77
+ "c8": "^11.0.0",
78
+ "typescript": "^6.0.3"
79
+ },
80
+ "peerDependencies": {
81
+ "typescript": ">=5.0.0"
82
+ },
83
+ "engines": {
84
+ "node": ">=22.0.0"
85
+ },
86
+ "publishConfig": {
87
+ "access": "public"
88
+ }
89
+ }