create-nexwire 4.2.2 → 4.2.4

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.
Files changed (90) hide show
  1. package/express/package.json +48 -23
  2. package/express/src/database/migrations/sqlite/0000_init.sql +47 -60
  3. package/express/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -89
  4. package/express/src/database/migrations/sqlite/meta/_journal.json +1 -1
  5. package/express/src/database/schema.ts +2 -3
  6. package/express/src/framework/database/app-schema.ts +37 -0
  7. package/express/src/framework/database/connection.ts +198 -196
  8. package/express/src/framework/database/seed.ts +35 -22
  9. package/express/src/framework/facade.ts +35 -5
  10. package/express/src/framework/kernel.ts +54 -52
  11. package/express/src/framework/maker-cli/db/core.mjs +291 -288
  12. package/express/src/framework/maker-cli/index.mjs +2 -0
  13. package/express/src/framework/maker-cli/module/core.mjs +155 -87
  14. package/express/src/framework/maker-cli/module/index.mjs +13 -4
  15. package/express/src/framework/maker-cli/provider/core.mjs +49 -0
  16. package/express/src/framework/maker-cli/provider/index.mjs +12 -0
  17. package/express/src/framework/maker-cli/stubs/notification/controller.ts.stub +76 -77
  18. package/express/src/framework/maker-cli/stubs/notification/job.ts.stub +11 -13
  19. package/express/src/framework/maker-cli/stubs/notification/model.ts.stub +29 -0
  20. package/express/src/framework/maker-cli/stubs/notification/provider.ts.stub +174 -0
  21. package/express/src/framework/maker-cli/stubs/notification/route.api.ts.stub +11 -10
  22. package/express/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +1 -1
  23. package/express/src/framework/maker-cli/stubs/notification/schema.plain.ts.stub +25 -25
  24. package/express/src/framework/maker-cli/stubs/notification/schema.ts.stub +25 -25
  25. package/express/src/framework/maker-cli/stubs/provider/module-barrel.ts.stub +19 -0
  26. package/express/src/framework/maker-cli/stubs/provider/module.ts.stub +21 -0
  27. package/express/src/framework/maker-cli/stubs/provider/name.ts.stub +21 -0
  28. package/express/src/framework/maker-cli/utils/help.mjs +6 -1
  29. package/express/src/framework/notification/index.ts +65 -47
  30. package/express/src/framework/providers/adapter.ts +139 -0
  31. package/express/src/framework/providers/contracts.ts +126 -0
  32. package/express/src/framework/providers/loader.ts +105 -0
  33. package/express/src/framework/providers/registry.ts +88 -0
  34. package/express/src/middlewares/auth-middleware.ts +65 -38
  35. package/express/src/providers/README.md +107 -0
  36. package/express/src/resources/src/main.ts +1 -1
  37. package/express/src/resources/src/pages/auth/forgetPassword.vue +1 -1
  38. package/express/src/resources/src/pages/auth/login.vue +1 -1
  39. package/express/src/resources/src/pages/auth/register.vue +1 -1
  40. package/express/src/resources/src/pages/auth/resetPassword.vue +1 -1
  41. package/express/src/resources/src/pages/auth/verifyEmail.vue +1 -1
  42. package/express/src/resources/src/pages/dashboard/index.vue +66 -66
  43. package/express/src/storage/database/nexwire.sqlite +0 -0
  44. package/hono/package.json +44 -19
  45. package/hono/src/database/migrations/sqlite/0000_init.sql +47 -60
  46. package/hono/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -89
  47. package/hono/src/database/migrations/sqlite/meta/_journal.json +1 -1
  48. package/hono/src/database/schema.ts +2 -3
  49. package/hono/src/framework/database/app-schema.ts +37 -0
  50. package/hono/src/framework/database/connection.ts +198 -196
  51. package/hono/src/framework/database/seed.ts +35 -22
  52. package/hono/src/framework/facade.ts +59 -29
  53. package/hono/src/framework/kernel.ts +50 -48
  54. package/hono/src/framework/maker-cli/db/core.mjs +291 -288
  55. package/hono/src/framework/maker-cli/index.mjs +2 -0
  56. package/hono/src/framework/maker-cli/module/core.mjs +123 -52
  57. package/hono/src/framework/maker-cli/module/index.mjs +13 -4
  58. package/hono/src/framework/maker-cli/provider/core.mjs +49 -0
  59. package/hono/src/framework/maker-cli/provider/index.mjs +12 -0
  60. package/hono/src/framework/maker-cli/stubs/notification/controller.ts.stub +90 -85
  61. package/hono/src/framework/maker-cli/stubs/notification/job.ts.stub +10 -12
  62. package/hono/src/framework/maker-cli/stubs/notification/model.ts.stub +29 -0
  63. package/hono/src/framework/maker-cli/stubs/notification/provider.ts.stub +174 -0
  64. package/hono/src/framework/maker-cli/stubs/notification/route.api.ts.stub +11 -10
  65. package/hono/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +1 -1
  66. package/hono/src/framework/maker-cli/stubs/notification/schema.plain.ts.stub +25 -25
  67. package/hono/src/framework/maker-cli/stubs/notification/schema.ts.stub +25 -25
  68. package/hono/src/framework/maker-cli/stubs/provider/module-barrel.ts.stub +19 -0
  69. package/hono/src/framework/maker-cli/stubs/provider/module.ts.stub +21 -0
  70. package/hono/src/framework/maker-cli/stubs/provider/name.ts.stub +21 -0
  71. package/hono/src/framework/maker-cli/utils/help.mjs +6 -1
  72. package/hono/src/framework/notification/index.ts +65 -47
  73. package/hono/src/framework/providers/adapter.ts +139 -0
  74. package/hono/src/framework/providers/contracts.ts +126 -0
  75. package/hono/src/framework/providers/loader.ts +105 -0
  76. package/hono/src/framework/providers/registry.ts +88 -0
  77. package/hono/src/middlewares/auth-middleware.ts +65 -38
  78. package/hono/src/providers/README.md +107 -0
  79. package/hono/src/resources/src/main.ts +1 -1
  80. package/hono/src/resources/src/pages/auth/forgetPassword.vue +1 -1
  81. package/hono/src/resources/src/pages/auth/login.vue +1 -1
  82. package/hono/src/resources/src/pages/auth/register.vue +1 -1
  83. package/hono/src/resources/src/pages/auth/resetPassword.vue +1 -1
  84. package/hono/src/resources/src/pages/auth/verifyEmail.vue +1 -1
  85. package/hono/src/resources/src/pages/dashboard/index.vue +66 -66
  86. package/hono/src/storage/database/nexwire.sqlite +0 -0
  87. package/package.json +10 -10
  88. package/src/index.js +14 -6
  89. package/express/src/modules/auth/database/models/notification.ts +0 -24
  90. package/hono/src/modules/auth/database/models/notification.ts +0 -24
@@ -0,0 +1,37 @@
1
+ import { discoverModuleFiles, importFile } from "@/framework/modules/discover.js";
2
+
3
+ /**
4
+ * Why: Builds the Drizzle schema from the modules that actually exist.
5
+ * When: The database connection is initialised.
6
+ * Where: Framework database connection.
7
+ * How: Discovers `src/modules/**\/database/models/*` and merges their exports.
8
+ * The generated barrel at `src/database/schema.ts` is only used by
9
+ * drizzle-kit, so deleting or replacing a module never leaves the
10
+ * framework importing a file that is no longer there.
11
+ */
12
+ let cachedSchema: Record<string, unknown> | null = null;
13
+
14
+ export async function loadAppSchema(): Promise<Record<string, unknown>> {
15
+ if (cachedSchema) return cachedSchema;
16
+
17
+ const schema: Record<string, unknown> = {};
18
+ const files = await discoverModuleFiles("**/database/models/*.{ts,js}");
19
+
20
+ for (const file of files) {
21
+ try {
22
+ const models = await importFile(file);
23
+ Object.assign(schema, models);
24
+ } catch {
25
+ // A model file that fails to load is skipped: the rest of the schema
26
+ // still works, and the framework keeps booting.
27
+ }
28
+ }
29
+
30
+ cachedSchema = schema;
31
+ return schema;
32
+ }
33
+
34
+ /** Clears the cached schema. Mainly useful in tests. */
35
+ export function clearAppSchema(): void {
36
+ cachedSchema = null;
37
+ }
@@ -1,196 +1,198 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { databaseConfig } from "@/config/index.js";
4
- import * as schema from "@/database/schema.js";
5
-
6
- export type Dialect = "sqlite" | "mysql" | "postgresql";
7
-
8
- let databaseInstance: any;
9
- let pool: any;
10
- let dialect: Dialect;
11
-
12
- async function optionalImport<T = any>(name: string): Promise<T> {
13
- return import(name) as Promise<T>;
14
- }
15
-
16
- /**
17
- * Why: Resolves the active DB driver from DATABASE_URL.
18
- * When: Called during bootstrap and dialect-specific branching.
19
- * Where: Used by init/close and schema generation helpers.
20
- * How: Checks DATABASE_URL prefix and maps to sqlite/mysql/postgresql.
21
- */
22
- export function detectDialect(): Dialect {
23
- const url = databaseConfig.url.toLowerCase();
24
- if (url.startsWith("mysql")) return "mysql";
25
- if (url.startsWith("postgres")) return "postgresql";
26
- return "sqlite";
27
- }
28
-
29
- /**
30
- * Why: Creates a singleton Drizzle connection for the current dialect.
31
- * When: Called once at app/worker/scheduler startup.
32
- * Where: Framework bootstrap entry points.
33
- * How: Builds dialect-specific pool/client and stores it in module state.
34
- */
35
- export async function initDatabase() {
36
- if (databaseInstance) return databaseInstance;
37
-
38
- dialect = detectDialect();
39
-
40
- if (dialect === "sqlite") {
41
- let drizzleSqlite: any;
42
- let createClient: any;
43
- try {
44
- [{ drizzle: drizzleSqlite }, { createClient }] = await Promise.all([
45
- optionalImport("drizzle-orm/libsql"),
46
- optionalImport("@libsql/client")
47
- ]);
48
- } catch {
49
- throw new Error("Missing sqlite dependencies. Install with: bun add drizzle-orm @libsql/client");
50
- }
51
-
52
- const file = path.resolve(process.cwd(), databaseConfig.url.replace(/^sqlite:/, ""));
53
- await fs.mkdir(path.dirname(file), { recursive: true });
54
- pool = createClient({ url: `file:${file.replace(/\\/g, "/")}` });
55
- databaseInstance = drizzleSqlite(pool, { schema });
56
- return databaseInstance;
57
- }
58
-
59
- if (dialect === "mysql") {
60
- let drizzleMysql: any;
61
- let mysql: any;
62
- try {
63
- [{ drizzle: drizzleMysql }, mysql] = await Promise.all([optionalImport("drizzle-orm/mysql2"), optionalImport("mysql2/promise")]);
64
- } catch {
65
- throw new Error("Missing mysql dependencies. Install with: bun add drizzle-orm mysql2");
66
- }
67
-
68
- pool = mysql.createPool({ uri: databaseConfig.url, connectionLimit: 10, enableKeepAlive: true });
69
- databaseInstance = drizzleMysql(pool, { schema, mode: "default" });
70
- return databaseInstance;
71
- }
72
-
73
- let drizzlePg: any;
74
- let postgres: any;
75
- try {
76
- [{ drizzle: drizzlePg }, { default: postgres }] = await Promise.all([
77
- optionalImport("drizzle-orm/postgres-js"),
78
- optionalImport("postgres")
79
- ]);
80
- } catch {
81
- throw new Error("Missing postgres dependencies. Install with: bun add drizzle-orm postgres");
82
- }
83
-
84
- pool = postgres(databaseConfig.url);
85
- databaseInstance = drizzlePg(pool, { schema });
86
- return databaseInstance;
87
- }
88
-
89
- /**
90
- * Why: Returns initialized Drizzle instance for queries.
91
- * When: Used by app code after bootstrap.
92
- * Where: Facade `db` proxy and direct internal consumers.
93
- * How: Throws if initDatabase has not completed.
94
- */
95
- export function database() {
96
- if (!databaseInstance) throw new Error("Database is not initialized");
97
- return databaseInstance;
98
- }
99
-
100
- /**
101
- * Why: Exposes low-level pool/client for advanced operations.
102
- * When: Needed by internals that require native pool behavior.
103
- * Where: Scheduler lock and infrastructure helpers.
104
- * How: Returns shared pool and guards against uninitialized access.
105
- */
106
- export function databasePool() {
107
- if (!pool) throw new Error("Database pool is not initialized");
108
- return pool;
109
- }
110
-
111
- /**
112
- * Why: Gracefully closes DB resources during shutdown/reset flows.
113
- * When: Server stop, worker stop, migration/reset commands.
114
- * Where: Runtime lifecycle scripts.
115
- * How: Detects dialect, closes pool, and clears singleton state.
116
- */
117
- export async function closeDatabase() {
118
- if (!pool) return;
119
-
120
- const activeDialect = databaseDialect();
121
-
122
- if (activeDialect === "sqlite") {
123
- pool.close?.();
124
- pool = undefined;
125
- databaseInstance = undefined;
126
- return;
127
- }
128
-
129
- if (activeDialect === "mysql") {
130
- await pool.end();
131
- pool = undefined;
132
- databaseInstance = undefined;
133
- return;
134
- }
135
-
136
- await pool.end();
137
- pool = undefined;
138
- databaseInstance = undefined;
139
- }
140
-
141
- /**
142
- * Why: Returns active dialect for conditional SQL/runtime behavior.
143
- * When: Dialect-specific features are required.
144
- * Where: Locking, schema, and shutdown helpers.
145
- * How: Uses initialized dialect or falls back to detection.
146
- */
147
- export function databaseDialect() {
148
- return dialect || detectDialect();
149
- }
150
-
151
- /**
152
- * Why: Normalizes raw query results into a consistent { rows } shape.
153
- * When: Drivers differ in what db.execute() returns:
154
- * - postgres-js / libsql return a plain array of rows
155
- * - mysql2 returns a [rows, fields] tuple
156
- * - pg node clients already wrap rows in { rows }
157
- * Consumers across modules read `result.rows`.
158
- * Where: Applied to every db.execute() call.
159
- * How: Wraps arrays of row objects (and the mysql2 tuple) into { rows },
160
- * leaves object shapes untouched.
161
- */
162
- function normalizeExecuteResult(result: unknown): unknown {
163
- if (Array.isArray(result)) {
164
- if (result.length === 2 && Array.isArray(result[1])) {
165
- return { rows: result[0], fields: result[1] };
166
- }
167
- const isRowList = result.length === 0 || result.every((row) => row != null && typeof row === "object" && !Array.isArray(row));
168
- if (isRowList) {
169
- return { rows: result };
170
- }
171
- }
172
- return result;
173
- }
174
-
175
- /**
176
- * Why: Provides ergonomic global query surface without calling database().
177
- * When: Used by modules, seeders, and facade consumers.
178
- * Where: Exposed via framework facade as `db`.
179
- * How: Proxy forwards property access to the initialized Drizzle instance.
180
- */
181
- export const db = new Proxy(
182
- {},
183
- {
184
- get(_target, property) {
185
- const instance = database();
186
- if (property === "execute") {
187
- return async (query: unknown, params?: unknown) => {
188
- const raw = instance.execute ? await instance.execute(query, params) : await instance.all(query);
189
- return normalizeExecuteResult(raw);
190
- };
191
- }
192
- const value = instance[property as keyof typeof instance];
193
- return typeof value === "function" ? value.bind(instance) : value;
194
- }
195
- }
196
- ) as any;
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { databaseConfig } from "@/config/index.js";
4
+ import { loadAppSchema } from "@/framework/database/app-schema.js";
5
+
6
+ export type Dialect = "sqlite" | "mysql" | "postgresql";
7
+
8
+ let databaseInstance: any;
9
+ let pool: any;
10
+ let dialect: Dialect;
11
+
12
+ async function optionalImport<T = any>(name: string): Promise<T> {
13
+ return import(name) as Promise<T>;
14
+ }
15
+
16
+ /**
17
+ * Why: Resolves the active DB driver from DATABASE_URL.
18
+ * When: Called during bootstrap and dialect-specific branching.
19
+ * Where: Used by init/close and schema generation helpers.
20
+ * How: Checks DATABASE_URL prefix and maps to sqlite/mysql/postgresql.
21
+ */
22
+ export function detectDialect(): Dialect {
23
+ const url = databaseConfig.url.toLowerCase();
24
+ if (url.startsWith("mysql")) return "mysql";
25
+ if (url.startsWith("postgres")) return "postgresql";
26
+ return "sqlite";
27
+ }
28
+
29
+ /**
30
+ * Why: Creates a singleton Drizzle connection for the current dialect.
31
+ * When: Called once at app/worker/scheduler startup.
32
+ * Where: Framework bootstrap entry points.
33
+ * How: Builds dialect-specific pool/client and stores it in module state.
34
+ */
35
+ export async function initDatabase() {
36
+ if (databaseInstance) return databaseInstance;
37
+
38
+ dialect = detectDialect();
39
+
40
+ const schema = await loadAppSchema();
41
+
42
+ if (dialect === "sqlite") {
43
+ let drizzleSqlite: any;
44
+ let createClient: any;
45
+ try {
46
+ [{ drizzle: drizzleSqlite }, { createClient }] = await Promise.all([
47
+ optionalImport("drizzle-orm/libsql"),
48
+ optionalImport("@libsql/client")
49
+ ]);
50
+ } catch {
51
+ throw new Error("Missing sqlite dependencies. Install with: bun add drizzle-orm @libsql/client");
52
+ }
53
+
54
+ const file = path.resolve(process.cwd(), databaseConfig.url.replace(/^sqlite:/, ""));
55
+ await fs.mkdir(path.dirname(file), { recursive: true });
56
+ pool = createClient({ url: `file:${file.replace(/\\/g, "/")}` });
57
+ databaseInstance = drizzleSqlite(pool, { schema });
58
+ return databaseInstance;
59
+ }
60
+
61
+ if (dialect === "mysql") {
62
+ let drizzleMysql: any;
63
+ let mysql: any;
64
+ try {
65
+ [{ drizzle: drizzleMysql }, mysql] = await Promise.all([optionalImport("drizzle-orm/mysql2"), optionalImport("mysql2/promise")]);
66
+ } catch {
67
+ throw new Error("Missing mysql dependencies. Install with: bun add drizzle-orm mysql2");
68
+ }
69
+
70
+ pool = mysql.createPool({ uri: databaseConfig.url, connectionLimit: 10, enableKeepAlive: true });
71
+ databaseInstance = drizzleMysql(pool, { schema, mode: "default" });
72
+ return databaseInstance;
73
+ }
74
+
75
+ let drizzlePg: any;
76
+ let postgres: any;
77
+ try {
78
+ [{ drizzle: drizzlePg }, { default: postgres }] = await Promise.all([
79
+ optionalImport("drizzle-orm/postgres-js"),
80
+ optionalImport("postgres")
81
+ ]);
82
+ } catch {
83
+ throw new Error("Missing postgres dependencies. Install with: bun add drizzle-orm postgres");
84
+ }
85
+
86
+ pool = postgres(databaseConfig.url);
87
+ databaseInstance = drizzlePg(pool, { schema });
88
+ return databaseInstance;
89
+ }
90
+
91
+ /**
92
+ * Why: Returns initialized Drizzle instance for queries.
93
+ * When: Used by app code after bootstrap.
94
+ * Where: Facade `db` proxy and direct internal consumers.
95
+ * How: Throws if initDatabase has not completed.
96
+ */
97
+ export function database() {
98
+ if (!databaseInstance) throw new Error("Database is not initialized");
99
+ return databaseInstance;
100
+ }
101
+
102
+ /**
103
+ * Why: Exposes low-level pool/client for advanced operations.
104
+ * When: Needed by internals that require native pool behavior.
105
+ * Where: Scheduler lock and infrastructure helpers.
106
+ * How: Returns shared pool and guards against uninitialized access.
107
+ */
108
+ export function databasePool() {
109
+ if (!pool) throw new Error("Database pool is not initialized");
110
+ return pool;
111
+ }
112
+
113
+ /**
114
+ * Why: Gracefully closes DB resources during shutdown/reset flows.
115
+ * When: Server stop, worker stop, migration/reset commands.
116
+ * Where: Runtime lifecycle scripts.
117
+ * How: Detects dialect, closes pool, and clears singleton state.
118
+ */
119
+ export async function closeDatabase() {
120
+ if (!pool) return;
121
+
122
+ const activeDialect = databaseDialect();
123
+
124
+ if (activeDialect === "sqlite") {
125
+ pool.close?.();
126
+ pool = undefined;
127
+ databaseInstance = undefined;
128
+ return;
129
+ }
130
+
131
+ if (activeDialect === "mysql") {
132
+ await pool.end();
133
+ pool = undefined;
134
+ databaseInstance = undefined;
135
+ return;
136
+ }
137
+
138
+ await pool.end();
139
+ pool = undefined;
140
+ databaseInstance = undefined;
141
+ }
142
+
143
+ /**
144
+ * Why: Returns active dialect for conditional SQL/runtime behavior.
145
+ * When: Dialect-specific features are required.
146
+ * Where: Locking, schema, and shutdown helpers.
147
+ * How: Uses initialized dialect or falls back to detection.
148
+ */
149
+ export function databaseDialect() {
150
+ return dialect || detectDialect();
151
+ }
152
+
153
+ /**
154
+ * Why: Normalizes raw query results into a consistent { rows } shape.
155
+ * When: Drivers differ in what db.execute() returns:
156
+ * - postgres-js / libsql return a plain array of rows
157
+ * - mysql2 returns a [rows, fields] tuple
158
+ * - pg node clients already wrap rows in { rows }
159
+ * Consumers across modules read `result.rows`.
160
+ * Where: Applied to every db.execute() call.
161
+ * How: Wraps arrays of row objects (and the mysql2 tuple) into { rows },
162
+ * leaves object shapes untouched.
163
+ */
164
+ function normalizeExecuteResult(result: unknown): unknown {
165
+ if (Array.isArray(result)) {
166
+ if (result.length === 2 && Array.isArray(result[1])) {
167
+ return { rows: result[0], fields: result[1] };
168
+ }
169
+ const isRowList = result.length === 0 || result.every((row) => row != null && typeof row === "object" && !Array.isArray(row));
170
+ if (isRowList) {
171
+ return { rows: result };
172
+ }
173
+ }
174
+ return result;
175
+ }
176
+
177
+ /**
178
+ * Why: Provides ergonomic global query surface without calling database().
179
+ * When: Used by modules, seeders, and facade consumers.
180
+ * Where: Exposed via framework facade as `db`.
181
+ * How: Proxy forwards property access to the initialized Drizzle instance.
182
+ */
183
+ export const db = new Proxy(
184
+ {},
185
+ {
186
+ get(_target, property) {
187
+ const instance = database();
188
+ if (property === "execute") {
189
+ return async (query: unknown, params?: unknown) => {
190
+ const raw = instance.execute ? await instance.execute(query, params) : await instance.all(query);
191
+ return normalizeExecuteResult(raw);
192
+ };
193
+ }
194
+ const value = instance[property as keyof typeof instance];
195
+ return typeof value === "function" ? value.bind(instance) : value;
196
+ }
197
+ }
198
+ ) as any;
@@ -45,30 +45,39 @@ try {
45
45
  const seeders: SeederEntry[] = [];
46
46
 
47
47
  for (const file of files) {
48
- const source = await readFile(file, "utf8");
49
- const isUnfilledStub = !/^\s*export\s/m.test(source);
50
- const mod = await importFile(file);
51
- if (typeof mod.default !== "function") {
52
- if (isUnfilledStub) {
53
- console.log(`Skipped unfilled seeder ${file} (no exports yet)`);
48
+ try {
49
+ const source = await readFile(file, "utf8");
50
+ const isUnfilledStub = !/^\s*export\s/m.test(source);
51
+ const mod = await importFile(file).catch((err: any) => {
52
+ console.warn(`[seed:skip] ${file}: ${err?.message || err}`);
53
+ return null as any;
54
+ });
55
+ if (!mod) continue;
56
+ if (typeof mod.default !== "function") {
57
+ if (isUnfilledStub) {
58
+ console.log(`Skipped unfilled seeder ${file} (no exports yet)`);
59
+ continue;
60
+ }
61
+ console.warn(`[seed:skip] ${file}: has no default export function`);
54
62
  continue;
55
63
  }
56
- throw new Error(`Seeder file ${file} has no default export function`);
57
- }
58
- const table: any = mod.table;
59
- const entry: SeederEntry = {
60
- file,
61
- name: file
62
- .split(/[\\/]/)
63
- .pop()!
64
- .replace(/\.(ts|js)$/, ""),
65
- execute: () => mod.default(),
66
- dependsOn: table ? getTableDeps(table) : []
67
- };
68
- if (table) {
69
- entry.tableName = table[NAME_SYMBOL] as string;
64
+ const table: any = mod.table;
65
+ const entry: SeederEntry = {
66
+ file,
67
+ name: file
68
+ .split(/[\\/]/)
69
+ .pop()!
70
+ .replace(/\.(ts|js)$/, ""),
71
+ execute: () => mod.default(),
72
+ dependsOn: table ? getTableDeps(table) : []
73
+ };
74
+ if (table) {
75
+ entry.tableName = table[NAME_SYMBOL] as string;
76
+ }
77
+ seeders.push(entry);
78
+ } catch (err: any) {
79
+ console.warn(`[seed:skip] ${file}: ${err?.message || err}`);
70
80
  }
71
- seeders.push(entry);
72
81
  }
73
82
 
74
83
  const tableToSeeder = new Map<string, SeederEntry>();
@@ -130,7 +139,11 @@ try {
130
139
  }
131
140
 
132
141
  for (const s of sorted) {
133
- await s.execute();
142
+ try {
143
+ await s.execute();
144
+ } catch (err: any) {
145
+ console.warn(`[seed:skip] ${s.name} failed: ${err?.message || err}`);
146
+ }
134
147
  }
135
148
 
136
149
  console.log(`Executed ${sorted.length} seeder file(s)${moduleName ? ` for module ${moduleName}` : ""}`);
@@ -1,29 +1,59 @@
1
- /**
2
- * Why: Central public API surface for framework consumers.
3
- * When: Modules/middlewares need framework utilities.
4
- * Where: App-layer imports should target this file.
5
- * How: Re-exports stable, reusable helpers while hiding setup internals.
6
- */
7
-
8
- export { createRoute, z } from "@hono/zod-openapi";
9
- export * as lodash from "lodash-es";
10
- export * as HttpStatusCodes from "stoker/http-status-codes";
11
- export { jsonContent } from "stoker/openapi/helpers";
12
- export { cache } from "@/framework/cache/cache.js";
13
- export { database, db } from "@/framework/database/connection.js";
14
- export { type PaginatedResult, paginate, paginateModel, paginateQuery, paginateTable } from "@/framework/database/paginate.js";
15
- export { command, dispatchCommand, dispatchEvent } from "@/framework/events/dispatcher.js";
16
- export { createRouter, group } from "@/framework/http/router.js";
17
- export { validate } from "@/framework/http/validation.js";
18
- export { notify } from "@/framework/notification/index.js";
19
- export { queue, queueJob, shouldQueue } from "@/framework/queue/queue.js";
20
- export { broadcast } from "@/framework/realtime/index.js";
21
- export { defineSchedule } from "@/framework/scheduler/scheduler.js";
22
- export { session } from "@/framework/session/session.js";
23
- export { storage } from "@/framework/storage/storage.js";
24
- export { cookie } from "@/framework/support/cookie.js";
25
- export { jwt } from "@/framework/support/jwt.js";
26
- export { logger } from "@/framework/support/logger.js";
27
- export { mail } from "@/framework/support/mail.js";
28
- export { password } from "@/framework/support/password.js";
29
- export { urls } from "@/framework/support/url.js";
1
+ /**
2
+ * Why: Central public API surface for framework consumers.
3
+ * When: Modules/middlewares need framework utilities.
4
+ * Where: App-layer imports should target this file.
5
+ * How: Re-exports stable, reusable helpers while hiding setup internals.
6
+ */
7
+
8
+ export { createRoute, z } from "@hono/zod-openapi";
9
+ export * as lodash from "lodash-es";
10
+ export * as HttpStatusCodes from "stoker/http-status-codes";
11
+ export { jsonContent } from "stoker/openapi/helpers";
12
+ export { cache } from "@/framework/cache/cache.js";
13
+ export { database, db } from "@/framework/database/connection.js";
14
+ export { type PaginatedResult, paginate, paginateModel, paginateQuery, paginateTable } from "@/framework/database/paginate.js";
15
+ export { command, dispatchCommand, dispatchEvent } from "@/framework/events/dispatcher.js";
16
+ export { createRouter, group } from "@/framework/http/router.js";
17
+ export { validate } from "@/framework/http/validation.js";
18
+ export { notify } from "@/framework/notification/index.js";
19
+ export type {
20
+ AuthProvider,
21
+ AuthProviderRefreshToken,
22
+ AuthProviderUser,
23
+ AuthUserContact,
24
+ AuthUserContext,
25
+ NotifiableTarget,
26
+ NotificationCreateInput,
27
+ NotificationListOptions,
28
+ NotificationPage,
29
+ NotificationProvider,
30
+ NotificationRecord
31
+ } from "@/framework/providers/contracts.js";
32
+ export { resolveAuthProvider, resolveNotificationProvider } from "@/framework/providers/adapter.js";
33
+ export { loadProviders } from "@/framework/providers/loader.js";
34
+ export {
35
+ clearAuthProvider,
36
+ clearNotificationProvider,
37
+ clearProvider,
38
+ getAuthProvider,
39
+ getNotificationProvider,
40
+ getProvider,
41
+ hasAuthProvider,
42
+ hasNotificationProvider,
43
+ hasProvider,
44
+ listProviders,
45
+ registerAuthProvider,
46
+ registerNotificationProvider,
47
+ registerProvider
48
+ } from "@/framework/providers/registry.js";
49
+ export { queue, queueJob, shouldQueue } from "@/framework/queue/queue.js";
50
+ export { broadcast } from "@/framework/realtime/index.js";
51
+ export { defineSchedule } from "@/framework/scheduler/scheduler.js";
52
+ export { session } from "@/framework/session/session.js";
53
+ export { storage } from "@/framework/storage/storage.js";
54
+ export { cookie } from "@/framework/support/cookie.js";
55
+ export { jwt } from "@/framework/support/jwt.js";
56
+ export { logger } from "@/framework/support/logger.js";
57
+ export { mail } from "@/framework/support/mail.js";
58
+ export { password } from "@/framework/support/password.js";
59
+ export { urls } from "@/framework/support/url.js";