@praxisjs/di 0.2.2 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,19 @@
1
1
  import { type Container, Token, type Constructor, type InjectableOptions } from "./container";
2
2
  export declare function Injectable(options?: InjectableOptions): (value: Constructor, _context: ClassDecoratorContext) => void;
3
- export declare function Inject<T>(dep: Constructor<T> | Token<T>): (_value: undefined, context: ClassFieldDecoratorContext) => void;
4
- export declare function InjectContainer(): (_value: undefined, context: ClassFieldDecoratorContext) => void;
5
- export declare function useService<T>(dep: Constructor<T> | Token<T>): T;
6
- export declare function createScope(configure?: (c: Container) => void): Container;
3
+ /**
4
+ * Creates a child DI container scoped to each instance of the decorated class.
5
+ * Services registered in the configure callback are available within the scope,
6
+ * and @Inject / @InjectContainer will resolve from it automatically.
7
+ *
8
+ * @Scope((c) => {
9
+ * c.register(UserRepository);
10
+ * c.registerValue(AuthToken, 'abc');
11
+ * })
12
+ * class UserModule extends StatefulComponent {
13
+ * @Inject(UserRepository) repo!: UserRepository;
14
+ * }
15
+ */
16
+ export declare function Scope(configure?: (c: Container) => void): (cls: new (...args: any[]) => any, _ctx: ClassDecoratorContext) => any;
17
+ export declare function Inject<T>(dep: Constructor<T> | Token<T>): (_value: undefined, context: ClassFieldDecoratorContext<any>) => void;
18
+ export declare function InjectContainer(): (_value: undefined, context: ClassFieldDecoratorContext<any>) => void;
7
19
  //# sourceMappingURL=decorators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,SAAS,EAAE,KAAK,EAAE,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAG,MAAM,aAAa,CAAC;AAE1G,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,IACvC,OAAO,WAAW,EAAE,UAAU,qBAAqB,KAAG,IAAI,CAG5E;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IACrC,QAAQ,SAAS,EAAE,SAAS,0BAA0B,KAAG,IAAI,CAsC/E;AAED,wBAAgB,eAAe,KACZ,QAAQ,SAAS,EAAE,SAAS,0BAA0B,KAAG,IAAI,CAW/E;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAE/D;AAED,wBAAgB,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,GAAG,SAAS,CAIzE"}
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,SAAS,EAAE,KAAK,EAAE,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAWzG,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,IACvC,OAAO,WAAW,EAAE,UAAU,qBAAqB,KAAG,IAAI,CAG5E;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,IAEtC,KAAK,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,qBAAqB,KAAG,GAAG,CAapF;AAID,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAsCrC,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,CAAC,GAAG,CAAC,KAAK,IAAI,CACvF;AAID,wBAAgB,eAAe,IAaZ,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,CAAC,GAAG,CAAC,KAAK,IAAI,CACvF"}
@@ -1,60 +1,94 @@
1
+ import { createFieldDecorator } from "@praxisjs/decorators";
1
2
  import { container, Token } from "./container";
3
+ // Maps instances to their scoped child containers (set by @Scope).
4
+ const scopedContainers = new WeakMap();
5
+ function resolveFrom(instance) {
6
+ return scopedContainers.get(instance) ?? container;
7
+ }
8
+ // ── @Injectable ───────────────────────────────────────────────────────────────
2
9
  export function Injectable(options = {}) {
3
10
  return function (value, _context) {
4
11
  container.register(value, options);
5
12
  };
6
13
  }
14
+ // ── @Scope ────────────────────────────────────────────────────────────────────
15
+ /**
16
+ * Creates a child DI container scoped to each instance of the decorated class.
17
+ * Services registered in the configure callback are available within the scope,
18
+ * and @Inject / @InjectContainer will resolve from it automatically.
19
+ *
20
+ * @Scope((c) => {
21
+ * c.register(UserRepository);
22
+ * c.registerValue(AuthToken, 'abc');
23
+ * })
24
+ * class UserModule extends StatefulComponent {
25
+ * @Inject(UserRepository) repo!: UserRepository;
26
+ * }
27
+ */
28
+ export function Scope(configure) {
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ return function (cls, _ctx) {
31
+ return class extends cls {
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
+ constructor(...args) {
34
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
35
+ super(...args);
36
+ const child = container.createChild();
37
+ configure?.(child);
38
+ scopedContainers.set(this, child);
39
+ }
40
+ };
41
+ };
42
+ }
43
+ // ── @Inject ───────────────────────────────────────────────────────────────────
7
44
  export function Inject(dep) {
8
- return function (_value, context) {
9
- const cache = new WeakMap();
10
- const propertyKey = String(context.name);
11
- context.addInitializer(function () {
12
- Object.defineProperty(this, context.name, {
13
- get() {
14
- if (!cache.has(this)) {
15
- let resolved;
16
- try {
17
- resolved = container.resolve(dep);
45
+ const cache = new WeakMap();
46
+ return createFieldDecorator({
47
+ bind(_instance, name, _initialValue) {
48
+ return {
49
+ descriptor: {
50
+ get() {
51
+ if (!cache.has(this)) {
52
+ const c = resolveFrom(this);
53
+ let resolved;
54
+ try {
55
+ resolved = c.resolve(dep);
56
+ }
57
+ catch (err) {
58
+ throw new Error(`[Inject] Failed to resolve "${dep instanceof Token
59
+ ? dep.toString()
60
+ : dep.name}" in "${this.constructor.name}.${name}": ${err.message}`);
61
+ }
62
+ cache.set(this, resolved);
18
63
  }
19
- catch (err) {
20
- throw new Error(`[Inject] Failed to resolve "${dep instanceof Token
21
- ? dep.toString()
22
- : dep.name}" in "${this.constructor.name}.${propertyKey}": ${err.message}`);
64
+ return cache.get(this);
65
+ },
66
+ set(_value) {
67
+ if (process.env.NODE_ENV !== "production") {
68
+ console.warn(`[Inject] "${name}" is managed by the DI container and cannot be assigned directly.`);
23
69
  }
24
- cache.set(this, resolved);
25
- }
26
- return cache.get(this);
27
- },
28
- set(_value) {
29
- if (process.env.NODE_ENV !== "production") {
30
- console.warn(`[Inject] "${propertyKey}" is managed by the DI container and cannot be assigned directly.`);
31
- }
70
+ },
32
71
  },
33
- enumerable: true,
34
- configurable: true,
35
- });
36
- });
37
- };
72
+ };
73
+ },
74
+ // DI decorators work on any class, not just StatefulComponent
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
+ });
38
77
  }
78
+ // ── @InjectContainer ──────────────────────────────────────────────────────────
39
79
  export function InjectContainer() {
40
- return function (_value, context) {
41
- context.addInitializer(function () {
42
- Object.defineProperty(this, context.name, {
43
- get() {
44
- return container;
80
+ return createFieldDecorator({
81
+ bind(_instance, _name, _initialValue) {
82
+ return {
83
+ descriptor: {
84
+ get() {
85
+ return resolveFrom(this);
86
+ },
45
87
  },
46
- enumerable: true,
47
- configurable: true,
48
- });
49
- });
50
- };
51
- }
52
- export function useService(dep) {
53
- return container.resolve(dep);
54
- }
55
- export function createScope(configure) {
56
- const child = container.createChild();
57
- configure?.(child);
58
- return child;
88
+ };
89
+ },
90
+ // DI decorators work on any class, not just StatefulComponent
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ });
59
93
  }
60
94
  //# sourceMappingURL=decorators.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAkB,KAAK,EAA6C,MAAM,aAAa,CAAC;AAE1G,MAAM,UAAU,UAAU,CAAC,UAA6B,EAAE;IACxD,OAAO,UAAU,KAAkB,EAAE,QAA+B;QAClE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,MAAM,CAAI,GAA8B;IACtD,OAAO,UAAU,MAAiB,EAAE,OAAmC;QACrE,MAAM,KAAK,GAAG,IAAI,OAAO,EAAa,CAAC;QACvC,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEzC,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;gBACxC,GAAG;oBACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;wBACrB,IAAI,QAAW,CAAC;wBAChB,IAAI,CAAC;4BACH,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,GAAqB,CAAC,CAAC;wBACtD,CAAC;wBAAC,OAAO,GAAG,EAAE,CAAC;4BACb,MAAM,IAAI,KAAK,CACb,+BACE,GAAG,YAAY,KAAK;gCAClB,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;gCAChB,CAAC,CAAE,GAAmB,CAAC,IAC3B,SAAU,IAA0C,CAAC,WAAW,CAAC,IAAI,IAAI,WAAW,MAAO,GAAa,CAAC,OAAO,EAAE,CACnH,CAAC;wBACJ,CAAC;wBACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;oBAC5B,CAAC;oBACD,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAM,CAAC;gBAC9B,CAAC;gBAED,GAAG,CAAC,MAAe;oBACjB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;wBAC1C,OAAO,CAAC,IAAI,CACV,aAAa,WAAW,mEAAmE,CAC5F,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAED,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,UAAU,MAAiB,EAAE,OAAmC;QACrE,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;gBACxC,GAAG;oBACD,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAI,GAA8B;IAC1D,OAAO,SAAS,CAAC,OAAO,CAAC,GAAqB,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAkC;IAC5D,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IACtC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;IACnB,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import "reflect-metadata";
2
- export { Injectable, Inject, InjectContainer, useService, createScope, } from "./decorators";
2
+ export { Injectable, Inject, InjectContainer, Scope, } from "./decorators";
3
3
  export { Container, container, Token, token } from "./container";
4
- export type { Scope, InjectableOptions, Constructor, ServiceDescriptor, } from "./container";
4
+ export type { Scope as ScopeType, InjectableOptions, Constructor, ServiceDescriptor, } from "./container";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EACL,UAAU,EACV,MAAM,EACN,eAAe,EACf,UAAU,EACV,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACjE,YAAY,EACV,KAAK,EACL,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EACL,UAAU,EACV,MAAM,EACN,eAAe,EACf,KAAK,GACN,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACjE,YAAY,EACV,KAAK,IAAI,SAAS,EAClB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "reflect-metadata";
2
- export { Injectable, Inject, InjectContainer, useService, createScope, } from "./decorators";
2
+ export { Injectable, Inject, InjectContainer, Scope, } from "./decorators";
3
3
  export { Container, container, Token, token } from "./container";
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EACL,UAAU,EACV,MAAM,EACN,eAAe,EACf,UAAU,EACV,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EACL,UAAU,EACV,MAAM,EACN,eAAe,EACf,KAAK,GACN,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisjs/di",
3
- "version": "0.2.2",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -12,7 +12,8 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "reflect-metadata": "^0.2.2",
15
- "@praxisjs/core": "0.4.1"
15
+ "@praxisjs/core": "1.0.0",
16
+ "@praxisjs/decorators": "0.5.0"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@types/node": "^25.3.0",
@@ -93,4 +93,80 @@ describe("Container", () => {
93
93
  const c = new Container();
94
94
  expect(c.register(A).register(B)).toBe(c);
95
95
  });
96
+
97
+ it("resolves prop injections from di:props metadata", () => {
98
+ class Logger {}
99
+ class Service {
100
+ logger!: Logger;
101
+ }
102
+
103
+ const c = new Container();
104
+ c.register(Logger);
105
+ c.register(Service);
106
+
107
+ // Simulate what the @Inject decorator does — set di:props metadata
108
+ const propsMap = new Map<string, unknown>();
109
+ propsMap.set("logger", Logger);
110
+ Reflect.defineMetadata("di:props", propsMap, Service.prototype);
111
+
112
+ const instance = c.resolve(Service);
113
+ expect(instance.logger).toBeInstanceOf(Logger);
114
+
115
+ // Cleanup
116
+ Reflect.deleteMetadata("di:props", Service.prototype);
117
+ });
118
+
119
+ it("child container falls back to parent for unregistered service", () => {
120
+ class MyDep {}
121
+ const parent = new Container();
122
+ parent.register(MyDep);
123
+ const child = parent.createChild();
124
+ expect(child.resolve(MyDep)).toBeInstanceOf(MyDep);
125
+ });
126
+
127
+ it("grandchild resolves from grandparent (three-level chain)", () => {
128
+ const URL_TOKEN = token<string>("GRANDPARENT_URL");
129
+ const grandparent = new Container();
130
+ grandparent.registerValue(URL_TOKEN, "https://grandparent.com");
131
+ const child = grandparent.createChild();
132
+ const grandchild = child.createChild();
133
+ expect(grandchild.resolve(URL_TOKEN)).toBe("https://grandparent.com");
134
+ });
135
+
136
+ it("resolves constructor injection from di:inject metadata", () => {
137
+ class Engine {}
138
+ class Car {
139
+ constructor(public engine: Engine) {}
140
+ }
141
+
142
+ const c = new Container();
143
+ c.register(Engine);
144
+ c.register(Car);
145
+
146
+ // Simulate what a @Inject constructor param decorator would set
147
+ Reflect.defineMetadata("di:inject", [Engine], Car);
148
+
149
+ const car = c.resolve(Car);
150
+ expect(car).toBeInstanceOf(Car);
151
+ expect(car.engine).toBeInstanceOf(Engine);
152
+
153
+ Reflect.deleteMetadata("di:inject", Car);
154
+ });
155
+
156
+ it("registering the same class twice replaces the previous registration", () => {
157
+ class Counter {
158
+ value = Math.random();
159
+ }
160
+ const c = new Container();
161
+ c.register(Counter, { scope: "singleton" });
162
+ const first = c.resolve(Counter);
163
+
164
+ // Re-register resets the descriptor (no cached instance)
165
+ c.register(Counter, { scope: "singleton" });
166
+ const second = c.resolve(Counter);
167
+
168
+ // After re-registration, a new singleton is created
169
+ expect(second).toBeInstanceOf(Counter);
170
+ expect(second).not.toBe(first);
171
+ });
96
172
  });