@orchestr-sh/orchestr 1.2.1 → 1.3.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.
package/README.md CHANGED
@@ -26,6 +26,11 @@ npm install @orchestr-sh/orchestr reflect-metadata
26
26
 
27
27
  **Note**: `reflect-metadata` is required for dependency injection to work.
28
28
 
29
+ ## Documentation
30
+
31
+ - **[Dependency Injection Guide](./DEPENDENCY_INJECTION.md)** - Complete guide to using DI with troubleshooting
32
+ - **[DI Example](./examples/dependency-injection/)** - Working example with services and controllers
33
+
29
34
  ## Quick Start
30
35
 
31
36
  ```typescript
@@ -78,6 +83,45 @@ app.singleton('Database', () => new Database());
78
83
  const userService = app.make('UserService');
79
84
  ```
80
85
 
86
+ ### Dependency Injection
87
+
88
+ Orchestr supports automatic constructor-based dependency injection using TypeScript's reflection:
89
+
90
+ ```typescript
91
+ import { Injectable, Controller, Request, Response } from 'orchestr';
92
+
93
+ // Define a service
94
+ export class UserService {
95
+ getUsers() {
96
+ return [{ id: 1, name: 'John' }];
97
+ }
98
+ }
99
+
100
+ // Use @Injectable() decorator to enable DI
101
+ @Injectable()
102
+ export class UserController extends Controller {
103
+ // Dependencies are automatically injected
104
+ constructor(private userService: UserService) {
105
+ super();
106
+ }
107
+
108
+ async index(req: Request, res: Response) {
109
+ const users = this.userService.getUsers();
110
+ return res.json({ users });
111
+ }
112
+ }
113
+
114
+ // Register the service in a provider
115
+ class AppServiceProvider extends ServiceProvider {
116
+ register(): void {
117
+ // Bind the service to the container
118
+ this.app.singleton(UserService, () => new UserService());
119
+ }
120
+ }
121
+ ```
122
+
123
+ **Important**: The `@Injectable()` decorator is required for dependency injection to work. It triggers TypeScript to emit metadata about constructor parameters.
124
+
81
125
  ### Service Providers
82
126
 
83
127
  Organize service registration and bootstrapping:
@@ -211,19 +255,28 @@ Route.get('/profile', handler).addMiddleware(authMiddleware);
211
255
 
212
256
  ### Controllers
213
257
 
214
- MVC pattern with base controller:
258
+ MVC pattern with base controller and dependency injection:
215
259
 
216
260
  ```typescript
217
- import { Controller, Request, Response, Route } from 'orchestr';
261
+ import { Injectable, Controller, Request, Response, Route } from 'orchestr';
218
262
 
263
+ // Use @Injectable() when injecting dependencies
264
+ @Injectable()
219
265
  class UserController extends Controller {
266
+ // Services are automatically injected
267
+ constructor(private userService: UserService) {
268
+ super();
269
+ }
270
+
220
271
  async index(req: Request, res: Response) {
221
- return res.json({ users: [] });
272
+ const users = await this.userService.getAll();
273
+ return res.json({ users });
222
274
  }
223
275
 
224
276
  async show(req: Request, res: Response) {
225
277
  const id = req.routeParam('id');
226
- return res.json({ user: { id } });
278
+ const user = await this.userService.findById(id);
279
+ return res.json({ user });
227
280
  }
228
281
 
229
282
  async store(req: Request, res: Response) {
@@ -231,7 +284,8 @@ class UserController extends Controller {
231
284
  name: 'required',
232
285
  email: 'required|email',
233
286
  });
234
- return res.status(201).json({ user: validated });
287
+ const user = await this.userService.create(validated);
288
+ return res.status(201).json({ user });
235
289
  }
236
290
  }
237
291
 
@@ -241,6 +295,8 @@ Route.get('/users/:id', [UserController, 'show']);
241
295
  Route.post('/users', [UserController, 'store']);
242
296
  ```
243
297
 
298
+ **Note**: The `@Injectable()` decorator must be used on any class that needs constructor dependency injection. Without it, TypeScript won't emit the metadata needed for automatic resolution.
299
+
244
300
  ### Request
245
301
 
246
302
  Powerful request helper methods:
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Injectable Decorator
3
+ *
4
+ * Marks a class as injectable, enabling TypeScript to emit decorator metadata
5
+ * required for automatic dependency injection via reflect-metadata.
6
+ *
7
+ * This decorator does nothing at runtime - it only triggers TypeScript's
8
+ * emitDecoratorMetadata feature to include parameter type information.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * @Injectable()
13
+ * export class UserController extends Controller {
14
+ * constructor(private userService: UserService) {
15
+ * super();
16
+ * }
17
+ * }
18
+ * ```
19
+ */
20
+ export declare function Injectable(): ClassDecorator;
21
+ //# sourceMappingURL=Injectable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Injectable.d.ts","sourceRoot":"","sources":["../../src/Support/Injectable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,IAAI,cAAc,CAM3C"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Injectable = Injectable;
4
+ /**
5
+ * Injectable Decorator
6
+ *
7
+ * Marks a class as injectable, enabling TypeScript to emit decorator metadata
8
+ * required for automatic dependency injection via reflect-metadata.
9
+ *
10
+ * This decorator does nothing at runtime - it only triggers TypeScript's
11
+ * emitDecoratorMetadata feature to include parameter type information.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * @Injectable()
16
+ * export class UserController extends Controller {
17
+ * constructor(private userService: UserService) {
18
+ * super();
19
+ * }
20
+ * }
21
+ * ```
22
+ */
23
+ function Injectable() {
24
+ return (target) => {
25
+ // This decorator is intentionally empty.
26
+ // Its sole purpose is to trigger TypeScript's emitDecoratorMetadata
27
+ // feature, which adds reflection metadata to the class constructor.
28
+ };
29
+ }
30
+ //# sourceMappingURL=Injectable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Injectable.js","sourceRoot":"","sources":["../../src/Support/Injectable.ts"],"names":[],"mappings":";;AAmBA,gCAMC;AAzBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,UAAU;IACxB,OAAO,CAAC,MAAgB,EAAE,EAAE;QAC1B,yCAAyC;QACzC,oEAAoE;QACpE,oEAAoE;IACtE,CAAC,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -14,6 +14,7 @@ export { Controller } from './Routing/Controller';
14
14
  export { Facade } from './Support/Facade';
15
15
  export { Route } from './Facades/Route';
16
16
  export { loadRoutes, base_path, routes_path } from './Support/helpers';
17
+ export { Injectable } from './Support/Injectable';
17
18
  export { RouteServiceProvider } from './Providers/RouteServiceProvider';
18
19
  export { DatabaseServiceProvider } from './Database/DatabaseServiceProvider';
19
20
  export { DatabaseManager } from './Database/DatabaseManager';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAGxC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAG7E,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGpE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAGlC,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAG9D,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAC/H,YAAY,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAChF,YAAY,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAGnE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACzG,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,QAAQ,EACR,WAAW,EACX,UAAU,EACV,aAAa,GACd,MAAM,4CAA4C,CAAC;AACpD,YAAY,EACV,MAAM,EACN,SAAS,EACT,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC3E,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACzE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAGxC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGvE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAG7E,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGpE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAGlC,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAG9D,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAC/H,YAAY,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAChF,YAAY,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAGnE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACzG,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,QAAQ,EACR,WAAW,EACX,UAAU,EACV,aAAa,GACd,MAAM,4CAA4C,CAAC;AACpD,YAAY,EACV,MAAM,EACN,SAAS,EACT,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC3E,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACzE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Main exports
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.softDeletes = exports.EnsembleCollection = exports.EnsembleBuilder = exports.Ensemble = exports.DB = exports.DrizzleAdapter = exports.raw = exports.Expression = exports.QueryBuilder = exports.Connection = exports.DatabaseManager = exports.DatabaseServiceProvider = exports.RouteServiceProvider = exports.routes_path = exports.base_path = exports.loadRoutes = exports.Route = exports.Facade = exports.Controller = exports.Response = exports.Request = exports.RouteClass = exports.Router = exports.Container = exports.Kernel = exports.ServiceProvider = exports.Application = void 0;
7
+ exports.softDeletes = exports.EnsembleCollection = exports.EnsembleBuilder = exports.Ensemble = exports.DB = exports.DrizzleAdapter = exports.raw = exports.Expression = exports.QueryBuilder = exports.Connection = exports.DatabaseManager = exports.DatabaseServiceProvider = exports.RouteServiceProvider = exports.Injectable = exports.routes_path = exports.base_path = exports.loadRoutes = exports.Route = exports.Facade = exports.Controller = exports.Response = exports.Request = exports.RouteClass = exports.Router = exports.Container = exports.Kernel = exports.ServiceProvider = exports.Application = void 0;
8
8
  // Foundation
9
9
  var Application_1 = require("./Foundation/Application");
10
10
  Object.defineProperty(exports, "Application", { enumerable: true, get: function () { return Application_1.Application; } });
@@ -36,6 +36,9 @@ var helpers_1 = require("./Support/helpers");
36
36
  Object.defineProperty(exports, "loadRoutes", { enumerable: true, get: function () { return helpers_1.loadRoutes; } });
37
37
  Object.defineProperty(exports, "base_path", { enumerable: true, get: function () { return helpers_1.base_path; } });
38
38
  Object.defineProperty(exports, "routes_path", { enumerable: true, get: function () { return helpers_1.routes_path; } });
39
+ // Decorators
40
+ var Injectable_1 = require("./Support/Injectable");
41
+ Object.defineProperty(exports, "Injectable", { enumerable: true, get: function () { return Injectable_1.Injectable; } });
39
42
  // Providers
40
43
  var RouteServiceProvider_1 = require("./Providers/RouteServiceProvider");
41
44
  Object.defineProperty(exports, "RouteServiceProvider", { enumerable: true, get: function () { return RouteServiceProvider_1.RouteServiceProvider; } });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,aAAa;AACb,wDAAuD;AAA9C,0GAAA,WAAW,OAAA;AACpB,gEAA+D;AAAtD,kHAAA,eAAe,OAAA;AACxB,mDAAkD;AAAzC,gGAAA,MAAM,OAAA;AAEf,YAAY;AACZ,mDAAkD;AAAzC,sGAAA,SAAS,OAAA;AAElB,UAAU;AACV,2CAA0C;AAAjC,gGAAA,MAAM,OAAA;AACf,yCAAsD;AAA7C,mGAAA,KAAK,OAAc;AAC5B,6CAA4C;AAAnC,kGAAA,OAAO,OAAA;AAChB,+CAA8C;AAArC,oGAAA,QAAQ,OAAA;AACjB,mDAAkD;AAAzC,wGAAA,UAAU,OAAA;AAEnB,UAAU;AACV,2CAA0C;AAAjC,gGAAA,MAAM,OAAA;AACf,yCAAwC;AAA/B,8FAAA,KAAK,OAAA;AAEd,UAAU;AACV,6CAAuE;AAA9D,qGAAA,UAAU,OAAA;AAAE,oGAAA,SAAS,OAAA;AAAE,sGAAA,WAAW,OAAA;AAE3C,YAAY;AACZ,yEAAwE;AAA/D,4HAAA,oBAAoB,OAAA;AAC7B,8EAA6E;AAApE,kIAAA,uBAAuB,OAAA;AAEhC,WAAW;AACX,8DAA6D;AAApD,kHAAA,eAAe,OAAA;AACxB,oDAAmD;AAA1C,wGAAA,UAAU,OAAA;AACnB,oDAAmE;AAA1D,uGAAA,OAAO,OAAgB;AAChC,0DAA8D;AAArD,wGAAA,UAAU,OAAA;AAAE,iGAAA,GAAG,OAAA;AACxB,qEAAoE;AAA3D,gHAAA,cAAc,OAAA;AAEvB,mBAAmB;AACnB,mCAAkC;AAAzB,wFAAA,EAAE,OAAA;AAEX,eAAe;AACf,yDAAwD;AAA/C,oGAAA,QAAQ,OAAA;AACjB,uEAAsE;AAA7D,kHAAA,eAAe,OAAA;AACxB,6EAA4E;AAAnE,wHAAA,kBAAkB,OAAA;AAC3B,+DAA8D;AAArD,0GAAA,WAAW,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,aAAa;AACb,wDAAuD;AAA9C,0GAAA,WAAW,OAAA;AACpB,gEAA+D;AAAtD,kHAAA,eAAe,OAAA;AACxB,mDAAkD;AAAzC,gGAAA,MAAM,OAAA;AAEf,YAAY;AACZ,mDAAkD;AAAzC,sGAAA,SAAS,OAAA;AAElB,UAAU;AACV,2CAA0C;AAAjC,gGAAA,MAAM,OAAA;AACf,yCAAsD;AAA7C,mGAAA,KAAK,OAAc;AAC5B,6CAA4C;AAAnC,kGAAA,OAAO,OAAA;AAChB,+CAA8C;AAArC,oGAAA,QAAQ,OAAA;AACjB,mDAAkD;AAAzC,wGAAA,UAAU,OAAA;AAEnB,UAAU;AACV,2CAA0C;AAAjC,gGAAA,MAAM,OAAA;AACf,yCAAwC;AAA/B,8FAAA,KAAK,OAAA;AAEd,UAAU;AACV,6CAAuE;AAA9D,qGAAA,UAAU,OAAA;AAAE,oGAAA,SAAS,OAAA;AAAE,sGAAA,WAAW,OAAA;AAE3C,aAAa;AACb,mDAAkD;AAAzC,wGAAA,UAAU,OAAA;AAEnB,YAAY;AACZ,yEAAwE;AAA/D,4HAAA,oBAAoB,OAAA;AAC7B,8EAA6E;AAApE,kIAAA,uBAAuB,OAAA;AAEhC,WAAW;AACX,8DAA6D;AAApD,kHAAA,eAAe,OAAA;AACxB,oDAAmD;AAA1C,wGAAA,UAAU,OAAA;AACnB,oDAAmE;AAA1D,uGAAA,OAAO,OAAgB;AAChC,0DAA8D;AAArD,wGAAA,UAAU,OAAA;AAAE,iGAAA,GAAG,OAAA;AACxB,qEAAoE;AAA3D,gHAAA,cAAc,OAAA;AAEvB,mBAAmB;AACnB,mCAAkC;AAAzB,wFAAA,EAAE,OAAA;AAEX,eAAe;AACf,yDAAwD;AAA/C,oGAAA,QAAQ,OAAA;AACjB,uEAAsE;AAA7D,kHAAA,eAAe,OAAA;AACxB,6EAA4E;AAAnE,wHAAA,kBAAkB,OAAA;AAC3B,+DAA8D;AAArD,0GAAA,WAAW,OAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestr-sh/orchestr",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "A 1:1 Laravel replica in TypeScript - Brings Laravel's elegant syntax and architecture to Node.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",