tina4-nodejs 3.13.12 → 3.13.16
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/CLAUDE.md +42 -36
- package/package.json +1 -1
- package/packages/cli/src/commands/migrate.ts +7 -5
- package/packages/cli/src/commands/migrateRollback.ts +3 -3
- package/packages/core/src/logger.ts +21 -8
- package/packages/core/src/middleware.ts +24 -3
- package/packages/core/src/server.ts +1 -1
- package/packages/orm/src/adapters/mssql.ts +12 -4
- package/packages/orm/src/adapters/mysql.ts +13 -4
- package/packages/orm/src/adapters/postgres.ts +18 -8
- package/packages/orm/src/adapters/sqlite.ts +22 -2
- package/packages/orm/src/autoCrud.ts +32 -16
- package/packages/orm/src/baseModel.ts +170 -187
- package/packages/orm/src/database.ts +189 -70
- package/packages/orm/src/databaseResult.ts +24 -0
- package/packages/orm/src/index.ts +6 -0
- package/packages/orm/src/migration.ts +128 -75
- package/packages/orm/src/queryBuilder.ts +12 -9
- package/packages/orm/src/seeder.ts +2 -1
- package/packages/orm/src/sqlTranslation.ts +16 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RouteDefinition, Tina4Request, Tina4Response } from "@tina4/core";
|
|
2
2
|
import type { DiscoveredModel } from "./model.js";
|
|
3
|
-
import { getAdapter } from "./database.js";
|
|
3
|
+
import { getAdapter, adapterQuery, adapterExecute } from "./database.js";
|
|
4
4
|
import { buildQuery, parseQueryString } from "./query.js";
|
|
5
5
|
import { validate } from "./validation.js";
|
|
6
6
|
|
|
@@ -109,9 +109,9 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
|
|
|
109
109
|
|
|
110
110
|
// params includes limit and offset at the end; countSql doesn't need them
|
|
111
111
|
const countParams = params.slice(0, -2);
|
|
112
|
-
const rows = adapter
|
|
112
|
+
const rows = await adapterQuery(adapter, sql, params);
|
|
113
113
|
|
|
114
|
-
const countRow = adapter
|
|
114
|
+
const countRow = await adapterQuery(adapter, countSql, countParams);
|
|
115
115
|
const total = Number(countRow[0]?.total ?? 0);
|
|
116
116
|
const limit = qp.limit ?? 100;
|
|
117
117
|
const page = qp.page ?? 1;
|
|
@@ -140,7 +140,7 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
|
|
|
140
140
|
const adapter = getAdapter();
|
|
141
141
|
|
|
142
142
|
const conditions = [`"${pkColumn}" = ?`, ...extraConditions];
|
|
143
|
-
const rows = adapter
|
|
143
|
+
const rows = await adapterQuery(adapter,
|
|
144
144
|
`SELECT * FROM "${tableName}" WHERE ${conditions.join(" AND ")}`,
|
|
145
145
|
[req.params.id],
|
|
146
146
|
);
|
|
@@ -183,14 +183,30 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
|
|
|
183
183
|
const values = Object.values(dbBody);
|
|
184
184
|
const placeholders = columns.map(() => "?").join(", ");
|
|
185
185
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
186
|
+
// Non-SQLite engines can't read a plain INSERT's auto-id back via
|
|
187
|
+
// lastInsertId(); RETURNING the PK column lets us recover it. SQLite
|
|
188
|
+
// tolerates RETURNING but we still prefer its lastInsertId below.
|
|
189
|
+
const isSqlite = adapter.constructor.name === "SQLiteAdapter";
|
|
190
|
+
const insertSql =
|
|
191
|
+
`INSERT INTO "${tableName}" (${columns.map((c) => `"${c}"`).join(", ")}) VALUES (${placeholders})` +
|
|
192
|
+
(isSqlite ? "" : ` RETURNING "${pkColumn}"`);
|
|
193
|
+
|
|
194
|
+
const insertResult = await adapterExecute(adapter, insertSql, values);
|
|
195
|
+
|
|
196
|
+
// Recover the new PK: SQLite via lastInsertId(); others via RETURNING.
|
|
197
|
+
let lastId: unknown = isSqlite ? adapter.lastInsertId() : null;
|
|
198
|
+
if (lastId === null && insertResult && typeof insertResult === "object") {
|
|
199
|
+
const rrows = (insertResult as any).rows;
|
|
200
|
+
if (Array.isArray(rrows) && rrows[0]) {
|
|
201
|
+
lastId = rrows[0][pkColumn] ?? rrows[0].id ?? null;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (lastId === null || lastId === undefined) {
|
|
205
|
+
lastId = adapter.lastInsertId();
|
|
206
|
+
}
|
|
190
207
|
|
|
191
208
|
// Fetch the created record to include auto-generated fields (e.g. id)
|
|
192
|
-
const
|
|
193
|
-
const created = adapter.query(
|
|
209
|
+
const created = await adapterQuery(adapter,
|
|
194
210
|
`SELECT * FROM "${tableName}" WHERE "${pkColumn}" = ?`,
|
|
195
211
|
[lastId],
|
|
196
212
|
);
|
|
@@ -212,7 +228,7 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
|
|
|
212
228
|
const body = req.body as Record<string, unknown>;
|
|
213
229
|
|
|
214
230
|
const conditions = [`"${pkColumn}" = ?`, ...extraConditions];
|
|
215
|
-
const existing = adapter
|
|
231
|
+
const existing = await adapterQuery(adapter,
|
|
216
232
|
`SELECT * FROM "${tableName}" WHERE ${conditions.join(" AND ")}`,
|
|
217
233
|
[req.params.id],
|
|
218
234
|
);
|
|
@@ -232,12 +248,12 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
|
|
|
232
248
|
.join(", ");
|
|
233
249
|
const values = [...Object.values(dbBody), req.params.id];
|
|
234
250
|
|
|
235
|
-
adapter
|
|
251
|
+
await adapterExecute(adapter,
|
|
236
252
|
`UPDATE "${tableName}" SET ${setClauses} WHERE "${pkColumn}" = ?`,
|
|
237
253
|
values,
|
|
238
254
|
);
|
|
239
255
|
|
|
240
|
-
const updated = adapter
|
|
256
|
+
const updated = await adapterQuery(adapter,
|
|
241
257
|
`SELECT * FROM "${tableName}" WHERE "${pkColumn}" = ?`,
|
|
242
258
|
[req.params.id],
|
|
243
259
|
);
|
|
@@ -258,7 +274,7 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
|
|
|
258
274
|
const adapter = getAdapter();
|
|
259
275
|
|
|
260
276
|
const conditions = [`"${pkColumn}" = ?`, ...extraConditions];
|
|
261
|
-
const existing = adapter
|
|
277
|
+
const existing = await adapterQuery(adapter,
|
|
262
278
|
`SELECT * FROM "${tableName}" WHERE ${conditions.join(" AND ")}`,
|
|
263
279
|
[req.params.id],
|
|
264
280
|
);
|
|
@@ -268,13 +284,13 @@ export function generateCrudRoutes(models: DiscoveredModel[]): RouteDefinition[]
|
|
|
268
284
|
}
|
|
269
285
|
|
|
270
286
|
if (softDelete) {
|
|
271
|
-
adapter
|
|
287
|
+
await adapterExecute(adapter,
|
|
272
288
|
`UPDATE "${tableName}" SET is_deleted = 1 WHERE "${pkColumn}" = ?`,
|
|
273
289
|
[req.params.id],
|
|
274
290
|
);
|
|
275
291
|
res.json({ message: "Deleted (soft)", data: existing[0] });
|
|
276
292
|
} else {
|
|
277
|
-
adapter
|
|
293
|
+
await adapterExecute(adapter,
|
|
278
294
|
`DELETE FROM "${tableName}" WHERE "${pkColumn}" = ?`,
|
|
279
295
|
[req.params.id],
|
|
280
296
|
);
|