@onroad/core 4.0.0-alpha.1 → 4.0.0-alpha.10
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 +444 -8
- package/dist/OnRoadExpress.d.ts.map +1 -1
- package/dist/OnRoadExpress.js +12 -3
- package/dist/OnRoadExpress.js.map +1 -1
- package/dist/container/Container.d.ts +1 -1
- package/dist/container/Container.d.ts.map +1 -1
- package/dist/container/Container.js +15 -6
- package/dist/container/Container.js.map +1 -1
- package/dist/core/AbstractService.d.ts +12 -0
- package/dist/core/AbstractService.d.ts.map +1 -1
- package/dist/core/AbstractService.js +14 -0
- package/dist/core/AbstractService.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/database/ConnectionManager.d.ts +1 -0
- package/dist/database/ConnectionManager.d.ts.map +1 -1
- package/dist/database/ConnectionManager.js +2 -0
- package/dist/database/ConnectionManager.js.map +1 -1
- package/dist/dev/DevServer.d.ts +51 -0
- package/dist/dev/DevServer.d.ts.map +1 -0
- package/dist/dev/DevServer.js +404 -0
- package/dist/dev/DevServer.js.map +1 -0
- package/dist/dev/MigrationCLI.d.ts +19 -0
- package/dist/dev/MigrationCLI.d.ts.map +1 -0
- package/dist/dev/MigrationCLI.js +140 -0
- package/dist/dev/MigrationCLI.js.map +1 -0
- package/dist/dev/index.d.ts +5 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/index.js +3 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/entity/EntityRegistry.d.ts +25 -0
- package/dist/entity/EntityRegistry.d.ts.map +1 -1
- package/dist/entity/EntityRegistry.js +130 -4
- package/dist/entity/EntityRegistry.js.map +1 -1
- package/dist/entity/decorators.d.ts +1 -0
- package/dist/entity/decorators.d.ts.map +1 -1
- package/dist/entity/decorators.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
|
@@ -88,8 +88,10 @@ export class OnRoadContainer {
|
|
|
88
88
|
if (this.singletons.has(key)) {
|
|
89
89
|
return this.singletons.get(key);
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
// Pre-register before wiring to allow circular service deps
|
|
92
|
+
const instance = new meta.target();
|
|
92
93
|
this.singletons.set(key, instance);
|
|
94
|
+
this.wire(meta, instance, scope);
|
|
93
95
|
return instance;
|
|
94
96
|
}
|
|
95
97
|
// Request scope cache
|
|
@@ -97,14 +99,17 @@ export class OnRoadContainer {
|
|
|
97
99
|
if (scope.instances.has(key)) {
|
|
98
100
|
return scope.instances.get(key);
|
|
99
101
|
}
|
|
100
|
-
|
|
102
|
+
// Pre-register before wiring to allow circular service deps
|
|
103
|
+
const instance = new meta.target();
|
|
101
104
|
scope.instances.set(key, instance);
|
|
105
|
+
this.wire(meta, instance, scope);
|
|
102
106
|
return instance;
|
|
103
107
|
}
|
|
104
|
-
return this.createAndWire(meta, scope);
|
|
105
|
-
}
|
|
106
|
-
createAndWire(meta, scope) {
|
|
107
108
|
const instance = new meta.target();
|
|
109
|
+
this.wire(meta, instance, scope);
|
|
110
|
+
return instance;
|
|
111
|
+
}
|
|
112
|
+
wire(meta, instance, scope) {
|
|
108
113
|
// Controller → Service (auto-inject)
|
|
109
114
|
if (meta.type === "controller" && hasMethod(instance, "getServiceClass")) {
|
|
110
115
|
const ServiceClass = instance.getServiceClass();
|
|
@@ -121,6 +126,11 @@ export class OnRoadContainer {
|
|
|
121
126
|
instance.setRepository(repo);
|
|
122
127
|
}
|
|
123
128
|
}
|
|
129
|
+
// Service → Service dependencies (auto-inject via configDependencies hook)
|
|
130
|
+
if (meta.type === "service" && hasMethod(instance, "configDependencies")) {
|
|
131
|
+
const resolver = (token) => this.resolve(token, scope);
|
|
132
|
+
instance.configDependencies(resolver);
|
|
133
|
+
}
|
|
124
134
|
// Repository → ConnectionManager + EntityClass (auto-bind)
|
|
125
135
|
if (meta.type === "repository") {
|
|
126
136
|
const repoOptions = Reflect.getMetadata(METADATA_KEY.REPOSITORY, meta.target);
|
|
@@ -146,7 +156,6 @@ export class OnRoadContainer {
|
|
|
146
156
|
instance.setTenant(scope.tenant);
|
|
147
157
|
}
|
|
148
158
|
}
|
|
149
|
-
return instance;
|
|
150
159
|
}
|
|
151
160
|
createScope(requestId, tenant) {
|
|
152
161
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Container.js","sourceRoot":"","sources":["../../src/container/Container.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Container.js","sourceRoot":"","sources":["../../src/container/Container.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAIhB,MAAM,CAAN,IAAY,KAIX;AAJD,WAAY,KAAK;IACf,gCAAuB,CAAA;IACvB,4BAAmB,CAAA;IACnB,gCAAuB,CAAA;AACzB,CAAC,EAJW,KAAK,KAAL,KAAK,QAIhB;AASD,wBAAwB;AAExB,MAAM,YAAY,GAAG;IACnB,UAAU,EAAE,MAAM,CAAC,qBAAqB,CAAC;IACzC,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC,qBAAqB,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC,kBAAkB,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC,qBAAqB,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC,iBAAiB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC,iBAAiB,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC;CACvB,CAAA;AAEV,OAAO,EAAE,YAAY,EAAE,CAAA;AAQvB,MAAM,UAAU,UAAU,CAAC,OAA2B;IACpD,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAC7D,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IACvF,CAAC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAC7D,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACjE,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;IACnE,CAAC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAC7D,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACjE,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;IAC5D,CAAC,CAAA;AACH,CAAC;AAMD,MAAM,UAAU,UAAU,CAAC,OAA0B;IACnD,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAC7D,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACjE,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;IAClE,CAAC,CAAA;AACH,CAAC;AAUD,MAAM,OAAO,eAAe;IAClB,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAA;IAC3C,UAAU,GAAG,IAAI,GAAG,EAAmB,CAAA;IACvC,kBAAkB,GAAG,IAAI,GAAG,EAAmB,CAAA;IAEvD,yBAAyB,CAAC,MAAc,EAAE,OAAgB;QACxD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9C,CAAC;IAED,IAAI,CAAC,OAAsB;QACzB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;YACtE,IAAI,CAAC,YAAY;gBAAE,SAAQ;YAE3B,MAAM,KAAK,GAAU,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,KAAK,CAAC,SAAS,CAAA;YACpF,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;YACxE,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;YAChE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;YACrE,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;YAChE,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;YAEhE,IAAI,IAAI,GAA0B,YAAY,CAAA;YAC9C,IAAI,cAAc,KAAK,SAAS;gBAAE,IAAI,GAAG,YAAY,CAAA;iBAChD,IAAI,SAAS;gBAAE,IAAI,GAAG,SAAS,CAAA;iBAC/B,IAAI,WAAW;gBAAE,IAAI,GAAG,YAAY,CAAA;iBACpC,IAAI,UAAU;gBAAE,IAAI,GAAG,QAAQ,CAAA;iBAC/B,IAAI,UAAU;gBAAE,IAAI,GAAG,QAAQ,CAAA;YAEpC,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAA;YAEtB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAC/D,CAAC;IACH,CAAC;IAED,OAAO,CAAI,KAAqB,EAAE,KAAoB;QACpD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAA;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAEnC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,yCAAyC,GAAG,+CAA+C,CAAC,CAAA;QAC9G,CAAC;QAED,kBAAkB;QAClB,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAM,CAAA;YACtC,CAAC;YACD,4DAA4D;YAC5D,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,MAAM,EAAO,CAAA;YACvC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;YAClC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;YAChC,OAAO,QAAQ,CAAA;QACjB,CAAC;QAED,sBAAsB;QACtB,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC;YAC1C,IAAI,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,OAAO,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAM,CAAA;YACtC,CAAC;YACD,4DAA4D;YAC5D,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,MAAM,EAAO,CAAA;YACvC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;YAClC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;YAChC,OAAO,QAAQ,CAAA;QACjB,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,MAAM,EAAO,CAAA;QACvC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;QAChC,OAAO,QAAQ,CAAA;IACjB,CAAC;IAEO,IAAI,CAAC,IAAmB,EAAE,QAAiB,EAAE,KAAoB;QACvE,qCAAqC;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,SAAS,CAAC,QAAQ,EAAE,iBAAiB,CAAC,EAAE,CAAC;YACzE,MAAM,YAAY,GAAI,QAA+C,CAAC,eAAe,EAAE,CAAA;YACvF,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAChD;gBAAC,QAA6C,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YACrE,CAAC;QACH,CAAC;QAED,qCAAqC;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,QAAQ,EAAE,oBAAoB,CAAC,EAAE,CAAC;YACzE,MAAM,SAAS,GAAI,QAAkD,CAAC,kBAAkB,EAAE,CAAA;YAC1F,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAC1C;gBAAC,QAAgD,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;YACxE,CAAC;QACH,CAAC;QAED,2EAA2E;QAC3E,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,QAAQ,EAAE,oBAAoB,CAAC,EAAE,CAAC;YACzE,MAAM,QAAQ,GAAG,CAAI,KAAqB,EAAK,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAC3E;YAAC,QAA6D,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAA;QAC9F,CAAC;QAED,2DAA2D;QAC3D,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAkC,OAAO,CAAC,WAAW,CACpE,YAAY,CAAC,UAAU,EACvB,IAAI,CAAC,MAAM,CACZ,CAAA;YAED,IAAI,WAAW,EAAE,MAAM,EAAE,CAAC;gBACxB,6CAA6C;gBAC7C,IAAI,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC,EAAE,CAAC;oBAC1C,CAAC;oBAAC,QAAqD,CAAC,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;gBAC5F,CAAC;gBAED,0CAA0C;gBAC1C,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;gBAC/E,IAAI,UAAU,EAAE,MAAM,IAAI,SAAS,CAAC,QAAQ,EAAE,sBAAsB,CAAC,EAAE,CAAC;oBACtE,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;oBAC9D,IAAI,OAAO,EAAE,CAAC;wBACZ,CAAC;wBAAC,QAAuD,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAA;oBACzF,CAAC;gBACH,CAAC;YACH,CAAC;YAED,wBAAwB;YACxB,IAAI,KAAK,EAAE,MAAM,IAAI,SAAS,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,CAAC;gBACtD,CAAC;gBAAC,QAA2C,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACvE,CAAC;QACH,CAAC;IACH,CAAC;IAED,WAAW,CAAC,SAAiB,EAAE,MAAe;QAC5C,OAAO;YACL,EAAE,EAAE,SAAS;YACb,MAAM;YACN,SAAS,EAAE,IAAI,GAAG,EAAE;SACrB,CAAA;IACH,CAAC;IAED,iBAAiB,CAAC,MAAmB;QACnC,OAAO,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;IAC7D,CAAC;IAED,SAAS,CAAC,IAA2B;QACnC,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;IACnE,CAAC;IAED,GAAG,CAAC,KAAa;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;QACrB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;IACzB,CAAC;CACF;AAED,SAAS,SAAS,CAAC,GAAY,EAAE,MAAc;IAC7C,OAAO,OAAQ,GAA+B,CAAC,MAAM,CAAC,KAAK,UAAU,CAAA;AACvE,CAAC"}
|
|
@@ -2,11 +2,23 @@ import type { Constructor } from "../container/Container.js";
|
|
|
2
2
|
export interface ServiceConfig<TRepository> {
|
|
3
3
|
repository: Constructor<TRepository>;
|
|
4
4
|
}
|
|
5
|
+
export type ServiceResolver = <T>(token: Constructor<T>) => T;
|
|
5
6
|
export declare abstract class AbstractService<TRepository = unknown> {
|
|
6
7
|
protected config: ServiceConfig<TRepository>;
|
|
7
8
|
protected repository: TRepository;
|
|
8
9
|
constructor(config: ServiceConfig<TRepository>);
|
|
9
10
|
setRepository(repository: TRepository): void;
|
|
10
11
|
getRepositoryClass(): Constructor<TRepository>;
|
|
12
|
+
/**
|
|
13
|
+
* Called by the container after the instance is created and the repository is injected.
|
|
14
|
+
* Override this method to declare service-to-service dependencies via the resolver.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* configDependencies(resolve: ServiceResolver): void {
|
|
18
|
+
* this.companySVC = resolve(CompanyService)
|
|
19
|
+
* this.roleSVC = resolve(RoleService)
|
|
20
|
+
* }
|
|
21
|
+
*/
|
|
22
|
+
configDependencies(_resolve: ServiceResolver): void;
|
|
11
23
|
}
|
|
12
24
|
//# sourceMappingURL=AbstractService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractService.d.ts","sourceRoot":"","sources":["../../src/core/AbstractService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D,MAAM,WAAW,aAAa,CAAC,WAAW;IACxC,UAAU,EAAE,WAAW,CAAC,WAAW,CAAC,CAAA;CACrC;AAED,8BAAsB,eAAe,CAAC,WAAW,GAAG,OAAO;IAG7C,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC;IAFxD,SAAS,CAAC,UAAU,EAAG,WAAW,CAAA;gBAEZ,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC;IAExD,aAAa,CAAC,UAAU,EAAE,WAAW,GAAG,IAAI;IAI5C,kBAAkB,IAAI,WAAW,CAAC,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"AbstractService.d.ts","sourceRoot":"","sources":["../../src/core/AbstractService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D,MAAM,WAAW,aAAa,CAAC,WAAW;IACxC,UAAU,EAAE,WAAW,CAAC,WAAW,CAAC,CAAA;CACrC;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;AAE7D,8BAAsB,eAAe,CAAC,WAAW,GAAG,OAAO;IAG7C,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC;IAFxD,SAAS,CAAC,UAAU,EAAG,WAAW,CAAA;gBAEZ,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC;IAExD,aAAa,CAAC,UAAU,EAAE,WAAW,GAAG,IAAI;IAI5C,kBAAkB,IAAI,WAAW,CAAC,WAAW,CAAC;IAI9C;;;;;;;;;OASG;IAEH,kBAAkB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;CAGpD"}
|
|
@@ -10,5 +10,19 @@ export class AbstractService {
|
|
|
10
10
|
getRepositoryClass() {
|
|
11
11
|
return this.config.repository;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Called by the container after the instance is created and the repository is injected.
|
|
15
|
+
* Override this method to declare service-to-service dependencies via the resolver.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* configDependencies(resolve: ServiceResolver): void {
|
|
19
|
+
* this.companySVC = resolve(CompanyService)
|
|
20
|
+
* this.roleSVC = resolve(RoleService)
|
|
21
|
+
* }
|
|
22
|
+
*/
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
24
|
+
configDependencies(_resolve) {
|
|
25
|
+
// Default no-op — override in concrete services
|
|
26
|
+
}
|
|
13
27
|
}
|
|
14
28
|
//# sourceMappingURL=AbstractService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractService.js","sourceRoot":"","sources":["../../src/core/AbstractService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AbstractService.js","sourceRoot":"","sources":["../../src/core/AbstractService.ts"],"names":[],"mappings":"AAQA,MAAM,OAAgB,eAAe;IAGb;IAFZ,UAAU,CAAc;IAElC,YAAsB,MAAkC;QAAlC,WAAM,GAAN,MAAM,CAA4B;IAAG,CAAC;IAE5D,aAAa,CAAC,UAAuB;QACnC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAA;IAC/B,CAAC;IAED;;;;;;;;;OASG;IACH,6DAA6D;IAC7D,kBAAkB,CAAC,QAAyB;QAC1C,gDAAgD;IAClD,CAAC;CACF"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { AbstractController } from "./AbstractController.js";
|
|
2
2
|
export type { RouteConfig, ControllerConfig } from "./AbstractController.js";
|
|
3
3
|
export { AbstractService } from "./AbstractService.js";
|
|
4
|
-
export type { ServiceConfig } from "./AbstractService.js";
|
|
4
|
+
export type { ServiceConfig, ServiceResolver } from "./AbstractService.js";
|
|
5
5
|
export { AbstractRepository } from "./AbstractRepository.js";
|
|
6
6
|
export { SequelizeRepository } from "./SequelizeRepository.js";
|
|
7
7
|
export { MongooseRepository } from "./MongooseRepository.js";
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE5E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE5E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConnectionManager.d.ts","sourceRoot":"","sources":["../../src/database/ConnectionManager.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE;QACL,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,8BAAsB,iBAAiB,CAAC,WAAW;IACjD,SAAS,CAAC,WAAW,2BAAiC;IACtD,SAAS,CAAC,MAAM,EAAE,cAAc,CAAA;gBAEpB,MAAM,EAAE,cAAc;IAIlC,QAAQ,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAEjF,QAAQ,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAElC,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAEpD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM;IAI/D,SAAS,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"ConnectionManager.d.ts","sourceRoot":"","sources":["../../src/database/ConnectionManager.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE;QACL,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,8BAAsB,iBAAiB,CAAC,WAAW;IACjD,SAAS,CAAC,WAAW,2BAAiC;IACtD,SAAS,CAAC,MAAM,EAAE,cAAc,CAAA;gBAEpB,MAAM,EAAE,cAAc;IAIlC,QAAQ,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAEjF,QAAQ,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAElC,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAEpD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM;IAI/D,SAAS,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM;CAI3E"}
|
|
@@ -11,6 +11,8 @@ export class ConnectionManager {
|
|
|
11
11
|
return dataSource ? `${tenant}:${dataSource}` : tenant;
|
|
12
12
|
}
|
|
13
13
|
resolveDatabaseName(tenant, dataSource) {
|
|
14
|
+
if (this.config.database)
|
|
15
|
+
return this.config.database;
|
|
14
16
|
return dataSource ?? `${this.config.prefix}_${tenant}`;
|
|
15
17
|
}
|
|
16
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConnectionManager.js","sourceRoot":"","sources":["../../src/database/ConnectionManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ConnectionManager.js","sourceRoot":"","sources":["../../src/database/ConnectionManager.ts"],"names":[],"mappings":"AAgBA,MAAM,OAAgB,iBAAiB;IAC3B,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAA;IAC5C,MAAM,CAAgB;IAEhC,YAAY,MAAsB;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAQD,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAA;IAC9B,CAAC;IAES,QAAQ,CAAC,MAAc,EAAE,UAAmB;QACpD,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;IACxD,CAAC;IAES,mBAAmB,CAAC,MAAc,EAAE,UAAmB;QAC/D,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAA;QACrD,OAAO,UAAU,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,EAAE,CAAA;IACxD,CAAC;CACF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { OnRoadExpress, BuildServerConfig } from "../OnRoadExpress.js";
|
|
2
|
+
export interface DevDatabaseConfig {
|
|
3
|
+
engine: "postgres" | "mysql";
|
|
4
|
+
port?: number;
|
|
5
|
+
user?: string;
|
|
6
|
+
password?: string;
|
|
7
|
+
database?: string;
|
|
8
|
+
image?: string;
|
|
9
|
+
containerName?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface DevServerConfig {
|
|
12
|
+
app: OnRoadExpress;
|
|
13
|
+
databases?: DevDatabaseConfig[];
|
|
14
|
+
frontendVars?: Record<string, string>;
|
|
15
|
+
migrationsPath?: string;
|
|
16
|
+
projectRoot?: string;
|
|
17
|
+
autoMigrate?: boolean;
|
|
18
|
+
composeFile?: string;
|
|
19
|
+
tenants?: string[];
|
|
20
|
+
}
|
|
21
|
+
export declare class DevServer {
|
|
22
|
+
private readonly app;
|
|
23
|
+
private readonly logger;
|
|
24
|
+
private readonly databases;
|
|
25
|
+
private readonly frontendVars;
|
|
26
|
+
private readonly migrationsPath?;
|
|
27
|
+
private readonly projectRoot;
|
|
28
|
+
private readonly autoMigrate;
|
|
29
|
+
private readonly composeFile;
|
|
30
|
+
private readonly tenants;
|
|
31
|
+
private containers;
|
|
32
|
+
private composeCmd;
|
|
33
|
+
constructor(config: DevServerConfig);
|
|
34
|
+
start(buildConfig?: BuildServerConfig): Promise<void>;
|
|
35
|
+
stop(): Promise<void>;
|
|
36
|
+
private ensureComposeFile;
|
|
37
|
+
private generateComposeContent;
|
|
38
|
+
private getComposeCommand;
|
|
39
|
+
private startContainers;
|
|
40
|
+
private stopContainers;
|
|
41
|
+
private isDockerAvailable;
|
|
42
|
+
private waitForDatabases;
|
|
43
|
+
private waitForContainer;
|
|
44
|
+
private populateContainersFromConfig;
|
|
45
|
+
private waitForSequelizeConnection;
|
|
46
|
+
private runMigrations;
|
|
47
|
+
private printFrontendEnvVars;
|
|
48
|
+
private printBanner;
|
|
49
|
+
private printSummary;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=DevServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevServer.d.ts","sourceRoot":"","sources":["../../src/dev/DevServer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAM3E,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAA;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,aAAa,CAAA;IAClB,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAcD,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwB;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,UAAU,CAAsB;gBAE5B,MAAM,EAAE,eAAe;IAc7B,KAAK,CAAC,WAAW,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BzD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,sBAAsB;IA+E9B,OAAO,CAAC,iBAAiB;YAyBX,eAAe;IAiC7B,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,iBAAiB;YAWX,gBAAgB;YAahB,gBAAgB;IA0B9B,OAAO,CAAC,4BAA4B;YAiBtB,0BAA0B;YAsB1B,aAAa;IAmC3B,OAAO,CAAC,oBAAoB;IAmD5B,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,YAAY;CAqBrB"}
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import { existsSync, writeFileSync } from "fs";
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
// --- Main Class ---
|
|
5
|
+
export class DevServer {
|
|
6
|
+
app;
|
|
7
|
+
logger;
|
|
8
|
+
databases;
|
|
9
|
+
frontendVars;
|
|
10
|
+
migrationsPath;
|
|
11
|
+
projectRoot;
|
|
12
|
+
autoMigrate;
|
|
13
|
+
composeFile;
|
|
14
|
+
tenants;
|
|
15
|
+
containers = [];
|
|
16
|
+
composeCmd = null;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.app = config.app;
|
|
19
|
+
this.logger = config.app.logger;
|
|
20
|
+
this.databases = config.databases ?? [{ engine: "postgres" }];
|
|
21
|
+
this.frontendVars = config.frontendVars ?? {};
|
|
22
|
+
this.migrationsPath = config.migrationsPath;
|
|
23
|
+
this.projectRoot = config.projectRoot ?? process.cwd();
|
|
24
|
+
this.autoMigrate = config.autoMigrate ?? true;
|
|
25
|
+
this.composeFile = config.composeFile ?? "docker-compose.dev.yml";
|
|
26
|
+
this.tenants = config.tenants ?? ["default"];
|
|
27
|
+
}
|
|
28
|
+
// --- Public API ---
|
|
29
|
+
async start(buildConfig = {}) {
|
|
30
|
+
this.printBanner();
|
|
31
|
+
// 1. Generate docker-compose if not exists
|
|
32
|
+
this.ensureComposeFile();
|
|
33
|
+
// 2. Start database containers
|
|
34
|
+
await this.startContainers();
|
|
35
|
+
// 3. Wait for database readiness
|
|
36
|
+
await this.waitForDatabases();
|
|
37
|
+
// 4. Run migrations (if configured)
|
|
38
|
+
if (this.autoMigrate && this.migrationsPath) {
|
|
39
|
+
await this.runMigrations();
|
|
40
|
+
}
|
|
41
|
+
// 5. Build and start the OnRoadExpress server
|
|
42
|
+
const port = buildConfig.port ?? 3000;
|
|
43
|
+
await this.app.buildServer({
|
|
44
|
+
...buildConfig,
|
|
45
|
+
port,
|
|
46
|
+
});
|
|
47
|
+
// 6. Log frontend env vars
|
|
48
|
+
this.printFrontendEnvVars(port);
|
|
49
|
+
// 7. Log summary
|
|
50
|
+
this.printSummary(port);
|
|
51
|
+
}
|
|
52
|
+
async stop() {
|
|
53
|
+
this.logger.info("Stopping DevServer...");
|
|
54
|
+
await this.app.shutdown();
|
|
55
|
+
this.stopContainers();
|
|
56
|
+
this.logger.info("DevServer stopped");
|
|
57
|
+
}
|
|
58
|
+
// --- Docker Compose ---
|
|
59
|
+
ensureComposeFile() {
|
|
60
|
+
const composePath = resolve(this.projectRoot, this.composeFile);
|
|
61
|
+
if (existsSync(composePath)) {
|
|
62
|
+
this.logger.debug("Docker Compose file already exists", { path: composePath });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const content = this.generateComposeContent();
|
|
66
|
+
writeFileSync(composePath, content, "utf-8");
|
|
67
|
+
this.logger.info("Generated docker-compose.dev.yml", { path: composePath });
|
|
68
|
+
}
|
|
69
|
+
generateComposeContent() {
|
|
70
|
+
const services = [];
|
|
71
|
+
const volumes = [];
|
|
72
|
+
for (const db of this.databases) {
|
|
73
|
+
const defaults = DB_DEFAULTS[db.engine];
|
|
74
|
+
const containerName = db.containerName ?? `typeroad-dev-${db.engine}`;
|
|
75
|
+
const port = db.port ?? defaults.port;
|
|
76
|
+
const user = db.user ?? defaults.user;
|
|
77
|
+
const password = db.password ?? defaults.password;
|
|
78
|
+
const database = db.database ?? defaults.database;
|
|
79
|
+
const image = db.image ?? defaults.image;
|
|
80
|
+
const volumeName = `${containerName}-data`;
|
|
81
|
+
this.containers.push({
|
|
82
|
+
name: containerName,
|
|
83
|
+
port,
|
|
84
|
+
engine: db.engine,
|
|
85
|
+
host: "localhost",
|
|
86
|
+
user,
|
|
87
|
+
password,
|
|
88
|
+
database,
|
|
89
|
+
});
|
|
90
|
+
if (db.engine === "postgres") {
|
|
91
|
+
services.push(` ${containerName}:
|
|
92
|
+
image: ${image}
|
|
93
|
+
container_name: ${containerName}
|
|
94
|
+
restart: unless-stopped
|
|
95
|
+
ports:
|
|
96
|
+
- "${port}:5432"
|
|
97
|
+
environment:
|
|
98
|
+
POSTGRES_USER: ${user}
|
|
99
|
+
POSTGRES_PASSWORD: ${password}
|
|
100
|
+
POSTGRES_DB: ${database}
|
|
101
|
+
volumes:
|
|
102
|
+
- ${volumeName}:/var/lib/postgresql/data
|
|
103
|
+
healthcheck:
|
|
104
|
+
test: ["CMD-SHELL", "pg_isready -U ${user} -d ${database}"]
|
|
105
|
+
interval: 2s
|
|
106
|
+
timeout: 5s
|
|
107
|
+
retries: 15`);
|
|
108
|
+
}
|
|
109
|
+
else if (db.engine === "mysql") {
|
|
110
|
+
services.push(` ${containerName}:
|
|
111
|
+
image: ${image}
|
|
112
|
+
container_name: ${containerName}
|
|
113
|
+
restart: unless-stopped
|
|
114
|
+
ports:
|
|
115
|
+
- "${port}:3306"
|
|
116
|
+
environment:
|
|
117
|
+
MYSQL_ROOT_PASSWORD: ${password}
|
|
118
|
+
MYSQL_USER: ${user}
|
|
119
|
+
MYSQL_PASSWORD: ${password}
|
|
120
|
+
MYSQL_DATABASE: ${database}
|
|
121
|
+
volumes:
|
|
122
|
+
- ${volumeName}:/var/lib/mysql
|
|
123
|
+
healthcheck:
|
|
124
|
+
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "${user}", "-p${password}"]
|
|
125
|
+
interval: 2s
|
|
126
|
+
timeout: 5s
|
|
127
|
+
retries: 15`);
|
|
128
|
+
}
|
|
129
|
+
volumes.push(` ${volumeName}:`);
|
|
130
|
+
}
|
|
131
|
+
return `# Auto-generated by TypeRoad DevServer
|
|
132
|
+
# Do not commit — add to .gitignore
|
|
133
|
+
|
|
134
|
+
services:
|
|
135
|
+
${services.join("\n\n")}
|
|
136
|
+
|
|
137
|
+
volumes:
|
|
138
|
+
${volumes.join("\n")}
|
|
139
|
+
`;
|
|
140
|
+
}
|
|
141
|
+
// --- Container Management ---
|
|
142
|
+
getComposeCommand() {
|
|
143
|
+
if (this.composeCmd)
|
|
144
|
+
return this.composeCmd;
|
|
145
|
+
// Try docker compose v2 (plugin) first, then docker-compose v1 (standalone)
|
|
146
|
+
try {
|
|
147
|
+
execSync("docker compose version", { stdio: "pipe" });
|
|
148
|
+
this.composeCmd = "docker compose";
|
|
149
|
+
return this.composeCmd;
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// v2 not available
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
execSync("docker-compose --version", { stdio: "pipe" });
|
|
156
|
+
this.composeCmd = "docker-compose";
|
|
157
|
+
return this.composeCmd;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// v1 not available
|
|
161
|
+
}
|
|
162
|
+
throw new Error("[TypeRoad DevServer] Neither 'docker compose' (v2) nor 'docker-compose' (v1) found. Install Docker Desktop or Docker Compose.");
|
|
163
|
+
}
|
|
164
|
+
async startContainers() {
|
|
165
|
+
const composePath = resolve(this.projectRoot, this.composeFile);
|
|
166
|
+
if (!this.isDockerAvailable()) {
|
|
167
|
+
throw new Error("[TypeRoad DevServer] Docker is not available. Install Docker Desktop or Docker Engine to use DevServer.");
|
|
168
|
+
}
|
|
169
|
+
const cmd = this.getComposeCommand();
|
|
170
|
+
this.logger.info(`Starting database containers... (using: ${cmd})`);
|
|
171
|
+
const maxRetries = 3;
|
|
172
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
173
|
+
try {
|
|
174
|
+
execSync(`${cmd} -f "${composePath}" up -d`, {
|
|
175
|
+
cwd: this.projectRoot,
|
|
176
|
+
stdio: "pipe",
|
|
177
|
+
});
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
182
|
+
// Transient Docker errors (closed pipe, daemon restart) — retry
|
|
183
|
+
if (attempt < maxRetries && (msg.includes("closed pipe") || msg.includes("connection refused"))) {
|
|
184
|
+
this.logger.warn(`Docker transient error (attempt ${attempt}/${maxRetries}), retrying in 3s...`);
|
|
185
|
+
execSync("sleep 3");
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
throw new Error(`[TypeRoad DevServer] Failed to start containers: ${msg}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
stopContainers() {
|
|
193
|
+
const composePath = resolve(this.projectRoot, this.composeFile);
|
|
194
|
+
try {
|
|
195
|
+
const cmd = this.getComposeCommand();
|
|
196
|
+
execSync(`${cmd} -f "${composePath}" down`, {
|
|
197
|
+
cwd: this.projectRoot,
|
|
198
|
+
stdio: "pipe",
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
this.logger.warn("Failed to stop containers — stop them manually");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
isDockerAvailable() {
|
|
206
|
+
try {
|
|
207
|
+
execSync("docker info", { stdio: "pipe" });
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// --- DB Readiness ---
|
|
215
|
+
async waitForDatabases() {
|
|
216
|
+
// Re-read containers info from compose if not already populated
|
|
217
|
+
if (this.containers.length === 0) {
|
|
218
|
+
this.populateContainersFromConfig();
|
|
219
|
+
}
|
|
220
|
+
for (const container of this.containers) {
|
|
221
|
+
this.logger.info(`Waiting for ${container.engine} (${container.name}) to be ready...`);
|
|
222
|
+
await this.waitForContainer(container);
|
|
223
|
+
this.logger.info(`${container.engine} (${container.name}) is ready`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async waitForContainer(container, maxRetries = 30) {
|
|
227
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
228
|
+
try {
|
|
229
|
+
if (container.engine === "postgres") {
|
|
230
|
+
execSync(`docker exec ${container.name} pg_isready -U ${container.user} -d ${container.database}`, { stdio: "pipe" });
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
else if (container.engine === "mysql") {
|
|
234
|
+
execSync(`docker exec ${container.name} mysqladmin ping -h localhost -u ${container.user} -p${container.password}`, { stdio: "pipe" });
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Not ready yet
|
|
240
|
+
}
|
|
241
|
+
await sleep(1000);
|
|
242
|
+
}
|
|
243
|
+
throw new Error(`[TypeRoad DevServer] Database ${container.name} failed to start within ${maxRetries}s`);
|
|
244
|
+
}
|
|
245
|
+
populateContainersFromConfig() {
|
|
246
|
+
for (const db of this.databases) {
|
|
247
|
+
const defaults = DB_DEFAULTS[db.engine];
|
|
248
|
+
this.containers.push({
|
|
249
|
+
name: db.containerName ?? `typeroad-dev-${db.engine}`,
|
|
250
|
+
port: db.port ?? defaults.port,
|
|
251
|
+
engine: db.engine,
|
|
252
|
+
host: "localhost",
|
|
253
|
+
user: db.user ?? defaults.user,
|
|
254
|
+
password: db.password ?? defaults.password,
|
|
255
|
+
database: db.database ?? defaults.database,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// --- Migrations ---
|
|
260
|
+
async waitForSequelizeConnection(maxRetries = 15) {
|
|
261
|
+
const connections = this.app.getConnections();
|
|
262
|
+
for (const conn of connections) {
|
|
263
|
+
if (conn.engine !== "sequelize")
|
|
264
|
+
continue;
|
|
265
|
+
const seqConn = conn;
|
|
266
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
267
|
+
try {
|
|
268
|
+
const sequelize = await seqConn.getConnection(this.tenants[0] ?? "default");
|
|
269
|
+
await sequelize.authenticate();
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
if (i < maxRetries - 1) {
|
|
274
|
+
await sleep(2000);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
this.logger.warn("Could not verify Sequelize connection — proceeding anyway");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async runMigrations() {
|
|
282
|
+
// Wait for the actual Sequelize connection to be stable
|
|
283
|
+
await this.waitForSequelizeConnection();
|
|
284
|
+
this.logger.info("Running database migrations...");
|
|
285
|
+
const connections = this.app.getConnections();
|
|
286
|
+
for (const conn of connections) {
|
|
287
|
+
if (conn.engine !== "sequelize")
|
|
288
|
+
continue;
|
|
289
|
+
const seqConn = conn;
|
|
290
|
+
for (const tenant of this.tenants) {
|
|
291
|
+
try {
|
|
292
|
+
const runner = await seqConn.getMigrationRunner(tenant);
|
|
293
|
+
const applied = await runner.up();
|
|
294
|
+
if (applied.length > 0) {
|
|
295
|
+
this.logger.info(`Migrations applied for tenant "${tenant}"`, {
|
|
296
|
+
count: applied.length,
|
|
297
|
+
migrations: applied,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
this.logger.info(`No pending migrations for tenant "${tenant}"`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
catch (err) {
|
|
305
|
+
this.logger.warn(`Migration failed for tenant "${tenant}" — continuing`, {
|
|
306
|
+
error: err instanceof Error ? err.message : String(err),
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// --- Frontend Env Var Logging ---
|
|
313
|
+
printFrontendEnvVars(port) {
|
|
314
|
+
const baseUrl = `http://localhost:${port}`;
|
|
315
|
+
const vars = {
|
|
316
|
+
REACT_APP_API_URL: baseUrl,
|
|
317
|
+
NEXT_PUBLIC_API_URL: baseUrl,
|
|
318
|
+
VITE_API_URL: baseUrl,
|
|
319
|
+
API_BASE_URL: baseUrl,
|
|
320
|
+
...this.frontendVars,
|
|
321
|
+
};
|
|
322
|
+
// Add database connection vars
|
|
323
|
+
for (const container of this.containers) {
|
|
324
|
+
const prefix = container.engine.toUpperCase();
|
|
325
|
+
vars[`${prefix}_HOST`] = container.host;
|
|
326
|
+
vars[`${prefix}_PORT`] = String(container.port);
|
|
327
|
+
vars[`${prefix}_USER`] = container.user;
|
|
328
|
+
vars[`${prefix}_PASSWORD`] = container.password;
|
|
329
|
+
vars[`${prefix}_DATABASE`] = container.database;
|
|
330
|
+
if (container.engine === "postgres") {
|
|
331
|
+
vars.DATABASE_URL = `postgresql://${container.user}:${container.password}@${container.host}:${container.port}/${container.database}`;
|
|
332
|
+
}
|
|
333
|
+
else if (container.engine === "mysql") {
|
|
334
|
+
vars.DATABASE_URL = `mysql://${container.user}:${container.password}@${container.host}:${container.port}/${container.database}`;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
console.log("");
|
|
338
|
+
console.log("┌──────────────────────────────────────────────────────────────┐");
|
|
339
|
+
console.log("│ FRONTEND ENVIRONMENT VARIABLES │");
|
|
340
|
+
console.log("├──────────────────────────────────────────────────────────────┤");
|
|
341
|
+
const envFileLines = [];
|
|
342
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
343
|
+
console.log(`│ ${key}=${value}`);
|
|
344
|
+
envFileLines.push(`${key}=${value}`);
|
|
345
|
+
}
|
|
346
|
+
console.log("├──────────────────────────────────────────────────────────────┤");
|
|
347
|
+
console.log("│ Copy the above to your frontend .env file │");
|
|
348
|
+
console.log("└──────────────────────────────────────────────────────────────┘");
|
|
349
|
+
console.log("");
|
|
350
|
+
// Write .env.local for convenience
|
|
351
|
+
const envPath = resolve(this.projectRoot, ".env.dev");
|
|
352
|
+
writeFileSync(envPath, envFileLines.join("\n") + "\n", "utf-8");
|
|
353
|
+
this.logger.info("Environment variables written to .env.dev", { path: envPath });
|
|
354
|
+
}
|
|
355
|
+
// --- Banner & Summary ---
|
|
356
|
+
printBanner() {
|
|
357
|
+
console.log("");
|
|
358
|
+
console.log(" ╔══════════════════════════════════════╗");
|
|
359
|
+
console.log(" ║ TypeRoad DevServer v1.0 ║");
|
|
360
|
+
console.log(" ║ Local Development Environment ║");
|
|
361
|
+
console.log(" ╚══════════════════════════════════════╝");
|
|
362
|
+
console.log("");
|
|
363
|
+
}
|
|
364
|
+
printSummary(port) {
|
|
365
|
+
console.log("");
|
|
366
|
+
console.log("┌──────────────────────────────────────────────────────────────┐");
|
|
367
|
+
console.log("│ SERVER READY │");
|
|
368
|
+
console.log("├──────────────────────────────────────────────────────────────┤");
|
|
369
|
+
console.log(`│ API: http://localhost:${port}`);
|
|
370
|
+
console.log(`│ Health: http://localhost:${port}/health`);
|
|
371
|
+
for (const container of this.containers) {
|
|
372
|
+
console.log(`│ ${container.engine.toUpperCase()}: ${container.host}:${container.port} (${container.name})`);
|
|
373
|
+
}
|
|
374
|
+
if (this.migrationsPath) {
|
|
375
|
+
console.log(`│ Migrations: ${this.migrationsPath}`);
|
|
376
|
+
}
|
|
377
|
+
console.log("├──────────────────────────────────────────────────────────────┤");
|
|
378
|
+
console.log("│ Press Ctrl+C to stop │");
|
|
379
|
+
console.log("└──────────────────────────────────────────────────────────────┘");
|
|
380
|
+
console.log("");
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
// --- Defaults ---
|
|
384
|
+
const DB_DEFAULTS = {
|
|
385
|
+
postgres: {
|
|
386
|
+
port: 5432,
|
|
387
|
+
user: "typeroad",
|
|
388
|
+
password: "typeroad_dev",
|
|
389
|
+
database: "typeroad_dev",
|
|
390
|
+
image: "postgres:16-alpine",
|
|
391
|
+
},
|
|
392
|
+
mysql: {
|
|
393
|
+
port: 3306,
|
|
394
|
+
user: "typeroad",
|
|
395
|
+
password: "typeroad_dev",
|
|
396
|
+
database: "typeroad_dev",
|
|
397
|
+
image: "mysql:8.0",
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
// --- Helpers ---
|
|
401
|
+
function sleep(ms) {
|
|
402
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
403
|
+
}
|
|
404
|
+
//# sourceMappingURL=DevServer.js.map
|