@onroad/core 4.0.0-alpha.6 → 4.0.0-alpha.8

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
@@ -25,6 +25,8 @@
25
25
  - [Storage](#storage)
26
26
  - [Health Endpoint](#health-endpoint)
27
27
  - [Graceful Shutdown](#graceful-shutdown)
28
+ - [Local Development (DevServer)](#local-development-devserver)
29
+ - [Migration CLI](#migration-cli)
28
30
  - [Testing](#testing)
29
31
  - [Subpath Exports](#subpath-exports)
30
32
  - [Known Pitfalls](#known-pitfalls)
@@ -601,7 +603,7 @@ await app.shutdown()
601
603
 
602
604
  ## Testing
603
605
 
604
- TypeRoad uses [Vitest](https://vitest.dev/) with **223 tests** across 9 test files:
606
+ TypeRoad uses [Vitest](https://vitest.dev/) with **242 tests** across 10 test files:
605
607
 
606
608
  ```bash
607
609
  npm test # Run all tests
@@ -611,7 +613,7 @@ npm run test:coverage # Coverage report
611
613
 
612
614
  | Test File | Tests | Covers |
613
615
  |-----------|-------|--------|
614
- | `container.test.ts` | 16 | DI Container, decorators, scopes |
616
+ | `container.test.ts` | 19 | DI Container, decorators, scopes |
615
617
  | `entity.test.ts` | 14 | Entity, Column, associations |
616
618
  | `database.test.ts` | 13 | ConnectionManagers |
617
619
  | `filters.test.ts` | 33 | FilterChain, all 5 built-in filters |
@@ -620,6 +622,7 @@ npm run test:coverage # Coverage report
620
622
  | `logging.test.ts` | 20 | PinoLogger, OnRoadLogger |
621
623
  | `providers.test.ts` | 41 | All 4 providers, graceful-fail, shutdown |
622
624
  | `transport.test.ts` | 25 | HttpTransport, MessagingTransport, TransportFactory, RequestContext |
625
+ | `dev.test.ts` | 16 | DevServer, MigrationCLI |
623
626
 
624
627
  ---
625
628
 
@@ -632,21 +635,184 @@ src/
632
635
  ├── container/ # DI Container + decorators
633
636
  ├── context/ # RequestContext (AsyncLocalStorage)
634
637
  ├── core/ # AbstractController/Service/Repository, Sentinel, EventBus
638
+ ├── database/ # ConnectionManager abstract + Sequelize/Mongo implementations
639
+ │ └── migrations/ # MigrationRunner (Umzug)
640
+ ├── dev/ # DevServer, MigrationCLI — local dev tools
635
641
  ├── entity/ # @Entity, @Column, @Field, associations
636
642
  ├── filters/ # FilterChain, @Filter, built-in filters (Cors, JWT, Tenant, Role, RequestContext)
637
- ├── security/ # @Roles, @Public
638
- ├── database/ # ConnectionManager abstract + Sequelize/Mongo implementations
639
- ├── transport/ # InterServiceTransport, HttpTransport, MessagingTransport, TransportFactory
640
- ├── messaging/ # MatchingObject
641
- ├── providers/ # MessagingProvider, RealtimeProvider, TaskSchedulerProvider, SocketProvider
642
643
  ├── logging/ # OnRoadLogger interface + PinoLogger
644
+ ├── messaging/ # MatchingObject
643
645
  ├── plugins/ # OnRoadPlugin interface
646
+ ├── providers/ # MessagingProvider, RealtimeProvider, TaskSchedulerProvider, SocketProvider
647
+ ├── security/ # @Roles, @Public
644
648
  ├── storage/ # StorageProvider abstract
649
+ ├── transport/ # InterServiceTransport, HttpTransport, MessagingTransport, TransportFactory
645
650
  └── types/ # Express Request augmentation
646
651
  ```
647
652
 
648
653
  ---
649
654
 
655
+ ## Local Development (DevServer)
656
+
657
+ TypeRoad includes a `DevServer` that makes local development self-sufficient — it starts database containers, runs migrations, and logs all environment variables your frontend needs.
658
+
659
+ ### Quick Start
660
+
661
+ ```ts
662
+ import "reflect-metadata"
663
+ import { OnRoadExpress } from "@onroad/core"
664
+ import { SequelizeConnectionManager } from "@onroad/core/database"
665
+ import { DevServer } from "@onroad/core/dev"
666
+
667
+ const app = new OnRoadExpress({
668
+ connections: [
669
+ new SequelizeConnectionManager({
670
+ dialect: "postgres",
671
+ host: "localhost",
672
+ port: 5432,
673
+ user: "typeroad",
674
+ password: "typeroad_dev",
675
+ database: "typeroad_dev",
676
+ migrations: {
677
+ path: "./src/migrations",
678
+ runOnConnect: true,
679
+ },
680
+ }),
681
+ ],
682
+ })
683
+
684
+ // Register your controllers, services, repositories...
685
+ app.register([/* ... */])
686
+
687
+ const devServer = new DevServer({
688
+ app,
689
+ databases: [{ engine: "postgres", port: 5432 }],
690
+ migrationsPath: "./src/migrations",
691
+ tenants: ["default"],
692
+ frontendVars: {
693
+ REACT_APP_TENANT: "default",
694
+ REACT_APP_WS_URL: "ws://localhost:3000",
695
+ },
696
+ })
697
+
698
+ await devServer.start({ port: 3000 })
699
+ // Press Ctrl+C to stop
700
+ ```
701
+
702
+ ### What DevServer Does
703
+
704
+ 1. **Generates `docker-compose.dev.yml`** — PostgreSQL (or MySQL) container with healthcheck, volumes, and sensible defaults
705
+ 2. **Starts the container** — `docker compose up -d` automatically
706
+ 3. **Waits for readiness** — polls `pg_isready` / `mysqladmin ping` until the DB accepts connections
707
+ 4. **Runs migrations** — applies all pending Umzug migrations from your configured path
708
+ 5. **Starts the API server** — calls `app.buildServer()` as usual
709
+ 6. **Logs frontend env vars** — prints a copy-pasteable block and writes `.env.dev`:
710
+
711
+ ```
712
+ ┌──────────────────────────────────────────────────────────────┐
713
+ │ FRONTEND ENVIRONMENT VARIABLES │
714
+ ├──────────────────────────────────────────────────────────────┤
715
+ │ REACT_APP_API_URL=http://localhost:3000
716
+ │ NEXT_PUBLIC_API_URL=http://localhost:3000
717
+ │ VITE_API_URL=http://localhost:3000
718
+ │ DATABASE_URL=postgresql://typeroad:typeroad_dev@localhost:5432/typeroad_dev
719
+ │ REACT_APP_TENANT=default
720
+ └──────────────────────────────────────────────────────────────┘
721
+ ```
722
+
723
+ ### DevServer Config
724
+
725
+ | Option | Type | Default | Description |
726
+ |--------|------|---------|-------------|
727
+ | `app` | `OnRoadExpress` | required | The app instance |
728
+ | `databases` | `DevDatabaseConfig[]` | `[{ engine: "postgres" }]` | Database containers to start |
729
+ | `frontendVars` | `Record<string, string>` | `{}` | Extra vars to log for frontend |
730
+ | `migrationsPath` | `string` | — | Path to migration files |
731
+ | `autoMigrate` | `boolean` | `true` | Run migrations on start |
732
+ | `tenants` | `string[]` | `["default"]` | Tenants to run migrations for |
733
+ | `composeFile` | `string` | `"docker-compose.dev.yml"` | Docker compose filename |
734
+
735
+ ### Database Defaults
736
+
737
+ | Engine | Image | Port | User | Password | Database |
738
+ |--------|-------|------|------|----------|----------|
739
+ | `postgres` | `postgres:16-alpine` | `5432` | `typeroad` | `typeroad_dev` | `typeroad_dev` |
740
+ | `mysql` | `mysql:8.0` | `3306` | `typeroad` | `typeroad_dev` | `typeroad_dev` |
741
+
742
+ ---
743
+
744
+ ## Migration CLI
745
+
746
+ The `MigrationCLI` class provides a programmatic API for managing database migrations.
747
+
748
+ ### Usage
749
+
750
+ ```ts
751
+ import { MigrationCLI } from "@onroad/core/dev"
752
+ import { SequelizeConnectionManager } from "@onroad/core/database"
753
+
754
+ const connection = new SequelizeConnectionManager({
755
+ dialect: "postgres",
756
+ host: "localhost",
757
+ user: "typeroad",
758
+ password: "typeroad_dev",
759
+ database: "typeroad_dev",
760
+ migrations: { path: "./src/migrations" },
761
+ })
762
+
763
+ const cli = new MigrationCLI({
764
+ migrationsPath: "./src/migrations",
765
+ connection,
766
+ tenant: "default",
767
+ })
768
+
769
+ // Run from CLI args
770
+ await cli.run() // reads process.argv
771
+
772
+ // Or call directly
773
+ cli.create("add-users-table") // creates timestamped migration file
774
+ await cli.up() // apply all pending
775
+ await cli.up(1) // apply 1 step
776
+ await cli.down() // revert last migration
777
+ await cli.status() // show status table
778
+ ```
779
+
780
+ ### CLI Commands
781
+
782
+ | Command | Description | Example |
783
+ |---------|-------------|---------|
784
+ | `create <name>` | Create a new migration file | `cli.run(["create", "add-orders"])` |
785
+ | `up [steps]` | Apply pending migrations | `cli.run(["up"])` or `cli.run(["up", "3"])` |
786
+ | `down [steps]` | Revert migrations (default: 1) | `cli.run(["down", "2"])` |
787
+ | `status` | Show applied/pending status | `cli.run(["status"])` |
788
+
789
+ ### Migration File Format
790
+
791
+ Generated `.ts` files follow the Umzug/Sequelize pattern:
792
+
793
+ ```ts
794
+ import type { QueryInterface, Sequelize } from "sequelize"
795
+
796
+ export default {
797
+ async up(queryInterface: QueryInterface, sequelize: Sequelize): Promise<void> {
798
+ await queryInterface.createTable("ordens", {
799
+ id: { type: sequelize.constructor["DataTypes"].UUID, primaryKey: true },
800
+ descricao: { type: sequelize.constructor["DataTypes"].STRING, allowNull: false },
801
+ createdAt: sequelize.constructor["DataTypes"].DATE,
802
+ updatedAt: sequelize.constructor["DataTypes"].DATE,
803
+ })
804
+ },
805
+
806
+ async down(queryInterface: QueryInterface): Promise<void> {
807
+ await queryInterface.dropTable("ordens")
808
+ },
809
+ }
810
+ ```
811
+
812
+ Migration state is tracked in the `__typeroad_migrations` table (configurable via `tableName` in `MigrationConfig`).
813
+
814
+ ---
815
+
650
816
  ## Subpath Exports
651
817
 
652
818
  Import only what you need:
@@ -662,6 +828,7 @@ import { HttpTransport, TransportFactory } from "@onroad/core/transport" // Tran
662
828
  import { MatchingObject } from "@onroad/core/messaging" // Messaging
663
829
  import { PinoLogger } from "@onroad/core/logging" // Logging
664
830
  import { StorageProvider } from "@onroad/core/storage" // Storage
831
+ import { DevServer, MigrationCLI } from "@onroad/core/dev" // Dev Tools
665
832
  ```
666
833
 
667
834
  ---
@@ -0,0 +1,50 @@
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 runMigrations;
46
+ private printFrontendEnvVars;
47
+ private printBanner;
48
+ private printSummary;
49
+ }
50
+ //# 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;IAgF9B,OAAO,CAAC,iBAAiB;YAyBX,eAAe;IAwB7B,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,iBAAiB;YAWX,gBAAgB;YAahB,gBAAgB;IA0B9B,OAAO,CAAC,4BAA4B;YAiBtB,aAAa;IAgC3B,OAAO,CAAC,oBAAoB;IAmD5B,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,YAAY;CAqBrB"}
@@ -0,0 +1,371 @@
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
+ version: "3.8"
134
+
135
+ services:
136
+ ${services.join("\n\n")}
137
+
138
+ volumes:
139
+ ${volumes.join("\n")}
140
+ `;
141
+ }
142
+ // --- Container Management ---
143
+ getComposeCommand() {
144
+ if (this.composeCmd)
145
+ return this.composeCmd;
146
+ // Try docker compose v2 (plugin) first, then docker-compose v1 (standalone)
147
+ try {
148
+ execSync("docker compose version", { stdio: "pipe" });
149
+ this.composeCmd = "docker compose";
150
+ return this.composeCmd;
151
+ }
152
+ catch {
153
+ // v2 not available
154
+ }
155
+ try {
156
+ execSync("docker-compose --version", { stdio: "pipe" });
157
+ this.composeCmd = "docker-compose";
158
+ return this.composeCmd;
159
+ }
160
+ catch {
161
+ // v1 not available
162
+ }
163
+ throw new Error("[TypeRoad DevServer] Neither 'docker compose' (v2) nor 'docker-compose' (v1) found. Install Docker Desktop or Docker Compose.");
164
+ }
165
+ async startContainers() {
166
+ const composePath = resolve(this.projectRoot, this.composeFile);
167
+ if (!this.isDockerAvailable()) {
168
+ throw new Error("[TypeRoad DevServer] Docker is not available. Install Docker Desktop or Docker Engine to use DevServer.");
169
+ }
170
+ const cmd = this.getComposeCommand();
171
+ this.logger.info(`Starting database containers... (using: ${cmd})`);
172
+ try {
173
+ execSync(`${cmd} -f "${composePath}" up -d`, {
174
+ cwd: this.projectRoot,
175
+ stdio: "pipe",
176
+ });
177
+ }
178
+ catch (err) {
179
+ throw new Error(`[TypeRoad DevServer] Failed to start containers: ${err instanceof Error ? err.message : String(err)}`);
180
+ }
181
+ }
182
+ stopContainers() {
183
+ const composePath = resolve(this.projectRoot, this.composeFile);
184
+ try {
185
+ const cmd = this.getComposeCommand();
186
+ execSync(`${cmd} -f "${composePath}" down`, {
187
+ cwd: this.projectRoot,
188
+ stdio: "pipe",
189
+ });
190
+ }
191
+ catch {
192
+ this.logger.warn("Failed to stop containers — stop them manually");
193
+ }
194
+ }
195
+ isDockerAvailable() {
196
+ try {
197
+ execSync("docker info", { stdio: "pipe" });
198
+ return true;
199
+ }
200
+ catch {
201
+ return false;
202
+ }
203
+ }
204
+ // --- DB Readiness ---
205
+ async waitForDatabases() {
206
+ // Re-read containers info from compose if not already populated
207
+ if (this.containers.length === 0) {
208
+ this.populateContainersFromConfig();
209
+ }
210
+ for (const container of this.containers) {
211
+ this.logger.info(`Waiting for ${container.engine} (${container.name}) to be ready...`);
212
+ await this.waitForContainer(container);
213
+ this.logger.info(`${container.engine} (${container.name}) is ready`);
214
+ }
215
+ }
216
+ async waitForContainer(container, maxRetries = 30) {
217
+ for (let i = 0; i < maxRetries; i++) {
218
+ try {
219
+ if (container.engine === "postgres") {
220
+ execSync(`docker exec ${container.name} pg_isready -U ${container.user} -d ${container.database}`, { stdio: "pipe" });
221
+ return;
222
+ }
223
+ else if (container.engine === "mysql") {
224
+ execSync(`docker exec ${container.name} mysqladmin ping -h localhost -u ${container.user} -p${container.password}`, { stdio: "pipe" });
225
+ return;
226
+ }
227
+ }
228
+ catch {
229
+ // Not ready yet
230
+ }
231
+ await sleep(1000);
232
+ }
233
+ throw new Error(`[TypeRoad DevServer] Database ${container.name} failed to start within ${maxRetries}s`);
234
+ }
235
+ populateContainersFromConfig() {
236
+ for (const db of this.databases) {
237
+ const defaults = DB_DEFAULTS[db.engine];
238
+ this.containers.push({
239
+ name: db.containerName ?? `typeroad-dev-${db.engine}`,
240
+ port: db.port ?? defaults.port,
241
+ engine: db.engine,
242
+ host: "localhost",
243
+ user: db.user ?? defaults.user,
244
+ password: db.password ?? defaults.password,
245
+ database: db.database ?? defaults.database,
246
+ });
247
+ }
248
+ }
249
+ // --- Migrations ---
250
+ async runMigrations() {
251
+ this.logger.info("Running database migrations...");
252
+ const connections = this.app.getConnections();
253
+ for (const conn of connections) {
254
+ if (conn.engine !== "sequelize")
255
+ continue;
256
+ const seqConn = conn;
257
+ for (const tenant of this.tenants) {
258
+ try {
259
+ const runner = await seqConn.getMigrationRunner(tenant);
260
+ const applied = await runner.up();
261
+ if (applied.length > 0) {
262
+ this.logger.info(`Migrations applied for tenant "${tenant}"`, {
263
+ count: applied.length,
264
+ migrations: applied,
265
+ });
266
+ }
267
+ else {
268
+ this.logger.info(`No pending migrations for tenant "${tenant}"`);
269
+ }
270
+ }
271
+ catch (err) {
272
+ this.logger.warn(`Migration failed for tenant "${tenant}" — continuing`, {
273
+ error: err instanceof Error ? err.message : String(err),
274
+ });
275
+ }
276
+ }
277
+ }
278
+ }
279
+ // --- Frontend Env Var Logging ---
280
+ printFrontendEnvVars(port) {
281
+ const baseUrl = `http://localhost:${port}`;
282
+ const vars = {
283
+ REACT_APP_API_URL: baseUrl,
284
+ NEXT_PUBLIC_API_URL: baseUrl,
285
+ VITE_API_URL: baseUrl,
286
+ API_BASE_URL: baseUrl,
287
+ ...this.frontendVars,
288
+ };
289
+ // Add database connection vars
290
+ for (const container of this.containers) {
291
+ const prefix = container.engine.toUpperCase();
292
+ vars[`${prefix}_HOST`] = container.host;
293
+ vars[`${prefix}_PORT`] = String(container.port);
294
+ vars[`${prefix}_USER`] = container.user;
295
+ vars[`${prefix}_PASSWORD`] = container.password;
296
+ vars[`${prefix}_DATABASE`] = container.database;
297
+ if (container.engine === "postgres") {
298
+ vars.DATABASE_URL = `postgresql://${container.user}:${container.password}@${container.host}:${container.port}/${container.database}`;
299
+ }
300
+ else if (container.engine === "mysql") {
301
+ vars.DATABASE_URL = `mysql://${container.user}:${container.password}@${container.host}:${container.port}/${container.database}`;
302
+ }
303
+ }
304
+ console.log("");
305
+ console.log("┌──────────────────────────────────────────────────────────────┐");
306
+ console.log("│ FRONTEND ENVIRONMENT VARIABLES │");
307
+ console.log("├──────────────────────────────────────────────────────────────┤");
308
+ const envFileLines = [];
309
+ for (const [key, value] of Object.entries(vars)) {
310
+ console.log(`│ ${key}=${value}`);
311
+ envFileLines.push(`${key}=${value}`);
312
+ }
313
+ console.log("├──────────────────────────────────────────────────────────────┤");
314
+ console.log("│ Copy the above to your frontend .env file │");
315
+ console.log("└──────────────────────────────────────────────────────────────┘");
316
+ console.log("");
317
+ // Write .env.local for convenience
318
+ const envPath = resolve(this.projectRoot, ".env.dev");
319
+ writeFileSync(envPath, envFileLines.join("\n") + "\n", "utf-8");
320
+ this.logger.info("Environment variables written to .env.dev", { path: envPath });
321
+ }
322
+ // --- Banner & Summary ---
323
+ printBanner() {
324
+ console.log("");
325
+ console.log(" ╔══════════════════════════════════════╗");
326
+ console.log(" ║ TypeRoad DevServer v1.0 ║");
327
+ console.log(" ║ Local Development Environment ║");
328
+ console.log(" ╚══════════════════════════════════════╝");
329
+ console.log("");
330
+ }
331
+ printSummary(port) {
332
+ console.log("");
333
+ console.log("┌──────────────────────────────────────────────────────────────┐");
334
+ console.log("│ SERVER READY │");
335
+ console.log("├──────────────────────────────────────────────────────────────┤");
336
+ console.log(`│ API: http://localhost:${port}`);
337
+ console.log(`│ Health: http://localhost:${port}/health`);
338
+ for (const container of this.containers) {
339
+ console.log(`│ ${container.engine.toUpperCase()}: ${container.host}:${container.port} (${container.name})`);
340
+ }
341
+ if (this.migrationsPath) {
342
+ console.log(`│ Migrations: ${this.migrationsPath}`);
343
+ }
344
+ console.log("├──────────────────────────────────────────────────────────────┤");
345
+ console.log("│ Press Ctrl+C to stop │");
346
+ console.log("└──────────────────────────────────────────────────────────────┘");
347
+ console.log("");
348
+ }
349
+ }
350
+ // --- Defaults ---
351
+ const DB_DEFAULTS = {
352
+ postgres: {
353
+ port: 5432,
354
+ user: "typeroad",
355
+ password: "typeroad_dev",
356
+ database: "typeroad_dev",
357
+ image: "postgres:16-alpine",
358
+ },
359
+ mysql: {
360
+ port: 3306,
361
+ user: "typeroad",
362
+ password: "typeroad_dev",
363
+ database: "typeroad_dev",
364
+ image: "mysql:8.0",
365
+ },
366
+ };
367
+ // --- Helpers ---
368
+ function sleep(ms) {
369
+ return new Promise((resolve) => setTimeout(resolve, ms));
370
+ }
371
+ //# sourceMappingURL=DevServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DevServer.js","sourceRoot":"","sources":["../../src/dev/DevServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { SequelizeConnectionManager } from "../database/SequelizeConnectionManager.js";
2
+ export interface MigrationCLIConfig {
3
+ migrationsPath: string;
4
+ connection: SequelizeConnectionManager;
5
+ tenant?: string;
6
+ }
7
+ export declare class MigrationCLI {
8
+ private readonly migrationsPath;
9
+ private readonly connection;
10
+ private readonly tenant;
11
+ constructor(config: MigrationCLIConfig);
12
+ run(args?: string[]): Promise<void>;
13
+ create(name: string): void;
14
+ up(steps?: number): Promise<void>;
15
+ down(steps?: number): Promise<void>;
16
+ status(): Promise<void>;
17
+ private getRunner;
18
+ }
19
+ //# sourceMappingURL=MigrationCLI.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MigrationCLI.d.ts","sourceRoot":"","sources":["../../src/dev/MigrationCLI.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAA;AAI3F,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,0BAA0B,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAID,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IACvD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;gBAEnB,MAAM,EAAE,kBAAkB;IAMhC,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAuChE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAgBpB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcjC,IAAI,CAAC,KAAK,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;YA8Bf,SAAS;CAGxB"}
@@ -0,0 +1,140 @@
1
+ import { existsSync, writeFileSync, mkdirSync } from "fs";
2
+ import { resolve, join } from "path";
3
+ // --- CLI ---
4
+ export class MigrationCLI {
5
+ migrationsPath;
6
+ connection;
7
+ tenant;
8
+ constructor(config) {
9
+ this.migrationsPath = config.migrationsPath;
10
+ this.connection = config.connection;
11
+ this.tenant = config.tenant ?? "default";
12
+ }
13
+ async run(args = process.argv.slice(2)) {
14
+ const command = args[0];
15
+ const param = args[1];
16
+ switch (command) {
17
+ case "create":
18
+ if (!param) {
19
+ console.error("Usage: migration create <name>");
20
+ process.exit(1);
21
+ }
22
+ this.create(param);
23
+ break;
24
+ case "up":
25
+ await this.up(param ? parseInt(param, 10) : undefined);
26
+ break;
27
+ case "down":
28
+ await this.down(param ? parseInt(param, 10) : 1);
29
+ break;
30
+ case "status":
31
+ await this.status();
32
+ break;
33
+ default:
34
+ console.log("Usage: migration <create|up|down|status> [param]");
35
+ console.log("");
36
+ console.log("Commands:");
37
+ console.log(" create <name> Create a new migration file");
38
+ console.log(" up [steps] Run pending migrations (all or N steps)");
39
+ console.log(" down [steps] Revert last N migrations (default: 1)");
40
+ console.log(" status Show migration status");
41
+ break;
42
+ }
43
+ }
44
+ // --- Commands ---
45
+ create(name) {
46
+ const timestamp = new Date().toISOString().replace(/[-:T]/g, "").slice(0, 14);
47
+ const safeName = name.replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
48
+ const fileName = `${timestamp}-${safeName}.ts`;
49
+ const dirPath = resolve(this.migrationsPath);
50
+ if (!existsSync(dirPath)) {
51
+ mkdirSync(dirPath, { recursive: true });
52
+ }
53
+ const filePath = join(dirPath, fileName);
54
+ writeFileSync(filePath, MIGRATION_TEMPLATE(safeName), "utf-8");
55
+ console.log(`Migration created: ${filePath}`);
56
+ }
57
+ async up(steps) {
58
+ const runner = await this.getRunner();
59
+ const applied = await runner.up(steps);
60
+ if (applied.length === 0) {
61
+ console.log("No pending migrations.");
62
+ }
63
+ else {
64
+ console.log(`Applied ${applied.length} migration(s):`);
65
+ for (const name of applied) {
66
+ console.log(` + ${name}`);
67
+ }
68
+ }
69
+ }
70
+ async down(steps = 1) {
71
+ const runner = await this.getRunner();
72
+ const reverted = await runner.down(steps);
73
+ if (reverted.length === 0) {
74
+ console.log("No migrations to revert.");
75
+ }
76
+ else {
77
+ console.log(`Reverted ${reverted.length} migration(s):`);
78
+ for (const name of reverted) {
79
+ console.log(` - ${name}`);
80
+ }
81
+ }
82
+ }
83
+ async status() {
84
+ const runner = await this.getRunner();
85
+ const statuses = await runner.status();
86
+ if (statuses.length === 0) {
87
+ console.log("No migrations found.");
88
+ return;
89
+ }
90
+ console.log("");
91
+ console.log("Migration Status:");
92
+ console.log("─".repeat(60));
93
+ for (const s of statuses) {
94
+ const icon = s.isApplied ? "✓" : "○";
95
+ const status = s.isApplied ? "applied" : "pending";
96
+ console.log(` ${icon} ${s.name} (${status})`);
97
+ }
98
+ console.log("─".repeat(60));
99
+ const applied = statuses.filter((s) => s.isApplied).length;
100
+ const pending = statuses.filter((s) => !s.isApplied).length;
101
+ console.log(` Total: ${statuses.length} | Applied: ${applied} | Pending: ${pending}`);
102
+ console.log("");
103
+ }
104
+ // --- Internal ---
105
+ async getRunner() {
106
+ return this.connection.getMigrationRunner(this.tenant);
107
+ }
108
+ }
109
+ // --- Template ---
110
+ function MIGRATION_TEMPLATE(name) {
111
+ return `import type { QueryInterface, Sequelize } from "sequelize"
112
+
113
+ export default {
114
+ async up(queryInterface: QueryInterface, sequelize: Sequelize): Promise<void> {
115
+ // TODO: implement migration "${name}"
116
+ // Example:
117
+ // await queryInterface.createTable("my_table", {
118
+ // id: {
119
+ // type: sequelize.constructor["DataTypes"].UUID,
120
+ // primaryKey: true,
121
+ // defaultValue: sequelize.constructor["DataTypes"].UUIDV4,
122
+ // },
123
+ // name: {
124
+ // type: sequelize.constructor["DataTypes"].STRING,
125
+ // allowNull: false,
126
+ // },
127
+ // createdAt: sequelize.constructor["DataTypes"].DATE,
128
+ // updatedAt: sequelize.constructor["DataTypes"].DATE,
129
+ // })
130
+ },
131
+
132
+ async down(queryInterface: QueryInterface, _sequelize: Sequelize): Promise<void> {
133
+ // TODO: implement rollback for "${name}"
134
+ // Example:
135
+ // await queryInterface.dropTable("my_table")
136
+ },
137
+ }
138
+ `;
139
+ }
140
+ //# sourceMappingURL=MigrationCLI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MigrationCLI.js","sourceRoot":"","sources":["../../src/dev/MigrationCLI.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { DevServer } from "./DevServer.js";
2
+ export type { DevServerConfig, DevDatabaseConfig } from "./DevServer.js";
3
+ export { MigrationCLI } from "./MigrationCLI.js";
4
+ export type { MigrationCLIConfig } from "./MigrationCLI.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dev/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAExE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { DevServer } from "./DevServer.js";
2
+ export { MigrationCLI } from "./MigrationCLI.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dev/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG1C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA"}
package/dist/index.d.ts CHANGED
@@ -24,4 +24,6 @@ export { PinoLogger } from "./logging/index.js";
24
24
  export type { OnRoadLogger, PinoLoggerConfig } from "./logging/index.js";
25
25
  export type { OnRoadPlugin } from "./plugins/index.js";
26
26
  export { StorageProvider } from "./storage/index.js";
27
+ export { DevServer, MigrationCLI } from "./dev/index.js";
28
+ export type { DevServerConfig, DevDatabaseConfig, MigrationCLIConfig } from "./dev/index.js";
27
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,kBAAkB,CAAA;AACzB,OAAO,4BAA4B,CAAA;AAGnC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAGzE,OAAO,EACL,eAAe,EACf,UAAU,EACV,UAAU,EACV,OAAO,EACP,UAAU,EACV,KAAK,EACL,YAAY,GACb,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGpF,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,QAAQ,EACR,eAAe,GAChB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAG5I,OAAO,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,MAAM,EACN,aAAa,EACb,QAAQ,EACR,cAAc,GACf,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAGxG,OAAO,EACL,YAAY,EACZ,WAAW,EACX,MAAM,EACN,gBAAgB,EAChB,oBAAoB,EACpB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,2BAA2B,GAC5B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAG7D,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAC3G,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAG1E,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGvD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAC/E,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAGtE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAGrD,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,GACf,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAGxE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,kBAAkB,CAAA;AACzB,OAAO,4BAA4B,CAAA;AAGnC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAGzE,OAAO,EACL,eAAe,EACf,UAAU,EACV,UAAU,EACV,OAAO,EACP,UAAU,EACV,KAAK,EACL,YAAY,GACb,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGpF,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,QAAQ,EACR,eAAe,GAChB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAG5I,OAAO,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,MAAM,EACN,aAAa,EACb,QAAQ,EACR,cAAc,GACf,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAGxG,OAAO,EACL,YAAY,EACZ,WAAW,EACX,MAAM,EACN,gBAAgB,EAChB,oBAAoB,EACpB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,2BAA2B,GAC5B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAG7D,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAC3G,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAG1E,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGvD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAC/E,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAGtE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAGrD,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,GACf,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAGxE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGpD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACxD,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA"}
package/dist/index.js CHANGED
@@ -28,4 +28,6 @@ export { MessagingProvider, RealtimeProvider, TaskSchedulerProvider, SocketProvi
28
28
  export { PinoLogger } from "./logging/index.js";
29
29
  // --- Storage ---
30
30
  export { StorageProvider } from "./storage/index.js";
31
+ // --- Dev Tools ---
32
+ export { DevServer, MigrationCLI } from "./dev/index.js";
31
33
  //# 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,6CAA6C;AAC7C,kBAAkB;AAElB,OAAO,kBAAkB,CAAA;AACzB,OAAO,4BAA4B,CAAA;AAEnC,eAAe;AACf,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGlD,iCAAiC;AACjC,OAAO,EACL,eAAe,EACf,UAAU,EACV,UAAU,EACV,OAAO,EACP,UAAU,EACV,KAAK,EACL,YAAY,GACb,MAAM,sBAAsB,CAAA;AAG7B,eAAe;AACf,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,QAAQ,EACR,eAAe,GAChB,MAAM,iBAAiB,CAAA;AAGxB,iBAAiB;AACjB,OAAO,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,MAAM,EACN,aAAa,EACb,QAAQ,EACR,cAAc,GACf,MAAM,mBAAmB,CAAA;AAG1B,kBAAkB;AAClB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,MAAM,EACN,gBAAgB,EAChB,oBAAoB,EACpB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAW3B,mBAAmB;AACnB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE7D,mBAAmB;AACnB,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAG3G,oBAAoB;AACpB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAG7B,0BAA0B;AAC1B,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAG/E,oBAAoB;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,oBAAoB;AACpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,GACf,MAAM,sBAAsB,CAAA;AAQ7B,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAM/C,kBAAkB;AAClB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,kBAAkB;AAElB,OAAO,kBAAkB,CAAA;AACzB,OAAO,4BAA4B,CAAA;AAEnC,eAAe;AACf,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGlD,iCAAiC;AACjC,OAAO,EACL,eAAe,EACf,UAAU,EACV,UAAU,EACV,OAAO,EACP,UAAU,EACV,KAAK,EACL,YAAY,GACb,MAAM,sBAAsB,CAAA;AAG7B,eAAe;AACf,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,QAAQ,EACR,eAAe,GAChB,MAAM,iBAAiB,CAAA;AAGxB,iBAAiB;AACjB,OAAO,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,MAAM,EACN,aAAa,EACb,QAAQ,EACR,cAAc,GACf,MAAM,mBAAmB,CAAA;AAG1B,kBAAkB;AAClB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,MAAM,EACN,gBAAgB,EAChB,oBAAoB,EACpB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAW3B,mBAAmB;AACnB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE7D,mBAAmB;AACnB,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAG3G,oBAAoB;AACpB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAG7B,0BAA0B;AAC1B,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAG/E,oBAAoB;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,oBAAoB;AACpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,GACf,MAAM,sBAAsB,CAAA;AAQ7B,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAM/C,kBAAkB;AAClB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEpD,oBAAoB;AACpB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onroad/core",
3
- "version": "4.0.0-alpha.6",
3
+ "version": "4.0.0-alpha.8",
4
4
  "description": "TypeScript backend framework — DI Container, Filter Chain, EventBus, Provider Pattern",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -61,6 +61,10 @@
61
61
  "./migrations": {
62
62
  "import": "./dist/database/migrations/index.js",
63
63
  "types": "./dist/database/migrations/index.d.ts"
64
+ },
65
+ "./dev": {
66
+ "import": "./dist/dev/index.js",
67
+ "types": "./dist/dev/index.d.ts"
64
68
  }
65
69
  },
66
70
  "files": [