nextly 0.0.2-alpha.1 → 0.0.2-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/dist/_dts-chunks/{collections-handler.d-DjgO74Wt.d.ts → collections-handler.d-B3iNFGJv.d.ts} +135 -120
- package/dist/_dts-chunks/{config.d-DNwsDnjs.d.ts → config.d-D8eInFE5.d.ts} +13 -1
- package/dist/_dts-chunks/{define-component.d-BUgTHmt3.d.ts → define-component.d-COeEsUOT.d.ts} +2 -2
- package/dist/_dts-chunks/{index.d-axCAzZ7m.d.ts → index.d-qjDq8N63.d.ts} +5 -5
- package/dist/actions/index.mjs +15 -15
- package/dist/api/auth-state.mjs +21 -21
- package/dist/api/collections-schema-detail.mjs +21 -21
- package/dist/api/collections-schema-export.mjs +21 -21
- package/dist/api/collections-schema.mjs +21 -21
- package/dist/api/components-detail.mjs +21 -21
- package/dist/api/components.mjs +21 -21
- package/dist/api/email-providers-default.mjs +21 -21
- package/dist/api/email-providers-detail.mjs +21 -21
- package/dist/api/email-providers-test.mjs +21 -21
- package/dist/api/email-providers.mjs +21 -21
- package/dist/api/email-send-template.mjs +23 -23
- package/dist/api/email-send.mjs +23 -23
- package/dist/api/email-templates-detail.mjs +21 -21
- package/dist/api/email-templates-layout.mjs +21 -21
- package/dist/api/email-templates-preview.mjs +21 -21
- package/dist/api/email-templates.mjs +21 -21
- package/dist/api/media-bulk.mjs +17 -17
- package/dist/api/media-folders.mjs +21 -21
- package/dist/api/media-handlers.d.ts +2 -2
- package/dist/api/media-handlers.mjs +21 -21
- package/dist/api/media.mjs +21 -21
- package/dist/api/singles-detail.mjs +21 -21
- package/dist/api/singles-schema-detail.mjs +21 -21
- package/dist/api/singles.mjs +21 -21
- package/dist/api/storage-upload-url.mjs +21 -21
- package/dist/api/uploads.mjs +27 -26
- package/dist/auth/index.mjs +6 -6
- package/dist/{boot-apply-PQSYLDIN.mjs → boot-apply-OE3D3KNU.mjs} +1 -1
- package/dist/{chunk-IZWPRDC3.mjs → chunk-2QSGNGOB.mjs} +1 -1
- package/dist/{chunk-DP3G27G5.mjs → chunk-35LAHTCU.mjs} +12 -2
- package/dist/{chunk-DNNG377Z.mjs → chunk-463A2UDH.mjs} +79 -13
- package/dist/{chunk-V4EQTOA4.mjs → chunk-4HUQNXVM.mjs} +2 -2
- package/dist/{chunk-VJ66NCL4.mjs → chunk-6C3CST4Q.mjs} +53 -4
- package/dist/{chunk-PKMABBB5.mjs → chunk-6GWK77EN.mjs} +1 -1
- package/dist/{chunk-XZKLBMN6.mjs → chunk-A75OLKXP.mjs} +44 -16
- package/dist/{chunk-TS7GHTG2.mjs → chunk-A7GGVOIV.mjs} +1 -1
- package/dist/{chunk-INV7QKLG.mjs → chunk-BZ2EOLXR.mjs} +1 -1
- package/dist/{chunk-X7TXCYYN.mjs → chunk-DQGQMP5F.mjs} +46 -26
- package/dist/{chunk-2W3DVD7S.mjs → chunk-ERTNRSP3.mjs} +1 -1
- package/dist/{chunk-UJ2IMJ4W.mjs → chunk-HREB7UR4.mjs} +10 -4
- package/dist/{chunk-NSEFNNU4.mjs → chunk-ILETUFUD.mjs} +302 -105
- package/dist/{chunk-A3WPLSDT.mjs → chunk-INTLFB63.mjs} +1 -1
- package/dist/{chunk-SBACDPNX.mjs → chunk-JCQMC6HH.mjs} +216 -27
- package/dist/{chunk-3FA7FKAV.mjs → chunk-JGVOZSXS.mjs} +58 -4
- package/dist/{chunk-M52VMPGA.mjs → chunk-KZFYCMBL.mjs} +1 -1
- package/dist/{chunk-W5KKPZT5.mjs → chunk-L7BXB5H3.mjs} +2 -2
- package/dist/{chunk-B2GV2BWH.mjs → chunk-MF4S2WSM.mjs} +2 -2
- package/dist/{chunk-R6JJQHFC.mjs → chunk-NXA6FD7R.mjs} +1 -1
- package/dist/{chunk-XGI4EMS3.mjs → chunk-OPACR7PX.mjs} +3 -3
- package/dist/{chunk-2OALJTK6.mjs → chunk-OV4WR3EC.mjs} +22 -42
- package/dist/{chunk-YZNBLFIW.mjs → chunk-RH3QV6E6.mjs} +3 -3
- package/dist/{chunk-LDKCUMHK.mjs → chunk-RQ3N4DIB.mjs} +2 -2
- package/dist/{chunk-YV4Y7SDL.mjs → chunk-TGBLNY5L.mjs} +2 -2
- package/dist/{chunk-GZ6DCQKC.mjs → chunk-TVG3WU6C.mjs} +5 -3
- package/dist/{chunk-AK6Z23OX.mjs → chunk-UGB6MLR6.mjs} +274 -45
- package/dist/{chunk-2Q2SX2CS.mjs → chunk-V5DUKEYT.mjs} +2 -2
- package/dist/{chunk-UOP63Q54.mjs → chunk-WRGCEERR.mjs} +1 -1
- package/dist/{chunk-O3QHXMOX.mjs → chunk-XCT6CROA.mjs} +23 -19
- package/dist/{chunk-P7NH2OSC.mjs → chunk-ZDNGCKSZ.mjs} +78 -49
- package/dist/cli/nextly.mjs +1 -1
- package/dist/cli/utils/index.d.ts +2 -2
- package/dist/cli/utils/index.mjs +1 -1
- package/dist/{component-schema-service-5577KVW6.mjs → component-schema-service-HUAQQ4H5.mjs} +2 -2
- package/dist/config.d.ts +3 -3
- package/dist/database/index.d.ts +2 -2
- package/dist/database/index.mjs +3 -3
- package/dist/database/seeders/index.mjs +18 -18
- package/dist/{db-sync-demote-LJGKLB3S.mjs → db-sync-demote-M7IEFD6N.mjs} +6 -6
- package/dist/{db-sync-promote-B26VSYQF.mjs → db-sync-promote-2MCB5JRZ.mjs} +6 -6
- package/dist/{dynamic-collection-schema-service-IEXTPIZ7.mjs → dynamic-collection-schema-service-FIRWOXZI.mjs} +2 -2
- package/dist/{factory-IWMBKUJM.mjs → factory-UGJGOZZ7.mjs} +2 -2
- package/dist/index.d.ts +16 -11
- package/dist/index.mjs +24 -55
- package/dist/{permissions-3DZZQZMI.mjs → permissions-KH3WCGAR.mjs} +16 -16
- package/dist/{pipeline-YOML7SWF.mjs → pipeline-JLANATHU.mjs} +10 -10
- package/dist/{preview-ZZTR3QGS.mjs → preview-3RSMZITY.mjs} +3 -3
- package/dist/{program-PW6UB2ZC.mjs → program-6V6HLEUI.mjs} +27 -27
- package/dist/{register-SF6E6FVU.mjs → register-FCUTHDS5.mjs} +17 -17
- package/dist/{reload-config-HWQ4G5MM.mjs → reload-config-52GWTPZG.mjs} +10 -10
- package/dist/{routeHandler-UNMMJIBM.mjs → routeHandler-FP26UQPJ.mjs} +26 -26
- package/dist/{runtime-schema-generator-NRA6A6Z6.mjs → runtime-schema-generator-NQOLDUDG.mjs} +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.mjs +26 -26
- package/dist/{super-admin-G5ZK5F4T.mjs → super-admin-XZAU4VQM.mjs} +16 -16
- package/dist/{system-table-service-WGSRVEGT.mjs → system-table-service-5FIVIALU.mjs} +5 -5
- package/dist/{users-7KELGRYJ.mjs → users-K2NJTF55.mjs} +15 -15
- package/package.json +8 -8
- /package/dist/{first-run-QIVKWJIF.mjs → first-run-2UDWZK5X.mjs} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getColumnDescriptor,
|
|
3
3
|
getSystemColumnDescriptors
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-463A2UDH.mjs";
|
|
5
5
|
|
|
6
6
|
// src/domains/schema/pipeline/classifier/count-helpers.ts
|
|
7
7
|
import { sql } from "drizzle-orm";
|
|
@@ -214,6 +214,17 @@ var RealClassifier = class {
|
|
|
214
214
|
]
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
|
+
} else if (op.type === "drop_column") {
|
|
218
|
+
const tableRowCount = await args.countRows(op.tableName);
|
|
219
|
+
events.push({
|
|
220
|
+
id: formatEventId("destructive_drop", op.tableName, op.columnName),
|
|
221
|
+
kind: "destructive_drop",
|
|
222
|
+
tableName: op.tableName,
|
|
223
|
+
columnName: op.columnName,
|
|
224
|
+
columnType: op.columnType,
|
|
225
|
+
tableRowCount,
|
|
226
|
+
applicableResolutions: ["confirm_drop", "abort"]
|
|
227
|
+
});
|
|
217
228
|
}
|
|
218
229
|
}
|
|
219
230
|
const hasInteractive = events.some((e) => e.kind !== "type_change");
|
|
@@ -236,7 +247,9 @@ function buildDesiredTableFromFields(tableName, fields, dialect, options = {}) {
|
|
|
236
247
|
name: reserved.name,
|
|
237
248
|
type: reserved.dialectType,
|
|
238
249
|
nullable: reserved.nullable,
|
|
239
|
-
default
|
|
250
|
+
// Forward descriptor default so the classifier doesn't flag status as
|
|
251
|
+
// `add_required_field_no_default` and require TTY confirmation.
|
|
252
|
+
default: reserved.default
|
|
240
253
|
});
|
|
241
254
|
}
|
|
242
255
|
for (const field of fields) {
|
|
@@ -261,26 +274,116 @@ function buildDesiredTableFromFields(tableName, fields, dialect, options = {}) {
|
|
|
261
274
|
function buildDesiredTableFromComponentFields(tableName, fields, dialect) {
|
|
262
275
|
const columns = [];
|
|
263
276
|
if (dialect === "postgresql") {
|
|
264
|
-
columns.push({
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
277
|
+
columns.push({
|
|
278
|
+
name: "id",
|
|
279
|
+
type: "text",
|
|
280
|
+
nullable: false,
|
|
281
|
+
default: void 0
|
|
282
|
+
});
|
|
283
|
+
columns.push({
|
|
284
|
+
name: "_parent_id",
|
|
285
|
+
type: "text",
|
|
286
|
+
nullable: false,
|
|
287
|
+
default: void 0
|
|
288
|
+
});
|
|
289
|
+
columns.push({
|
|
290
|
+
name: "_parent_table",
|
|
291
|
+
type: "varchar",
|
|
292
|
+
nullable: false,
|
|
293
|
+
default: void 0
|
|
294
|
+
});
|
|
295
|
+
columns.push({
|
|
296
|
+
name: "_parent_field",
|
|
297
|
+
type: "varchar",
|
|
298
|
+
nullable: false,
|
|
299
|
+
default: void 0
|
|
300
|
+
});
|
|
301
|
+
columns.push({
|
|
302
|
+
name: "_order",
|
|
303
|
+
type: "int4",
|
|
304
|
+
nullable: true,
|
|
305
|
+
default: void 0
|
|
306
|
+
});
|
|
307
|
+
columns.push({
|
|
308
|
+
name: "_component_type",
|
|
309
|
+
type: "varchar",
|
|
310
|
+
nullable: true,
|
|
311
|
+
default: void 0
|
|
312
|
+
});
|
|
270
313
|
} else if (dialect === "mysql") {
|
|
271
|
-
columns.push({
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
314
|
+
columns.push({
|
|
315
|
+
name: "id",
|
|
316
|
+
type: "varchar(36)",
|
|
317
|
+
nullable: false,
|
|
318
|
+
default: void 0
|
|
319
|
+
});
|
|
320
|
+
columns.push({
|
|
321
|
+
name: "_parent_id",
|
|
322
|
+
type: "varchar(36)",
|
|
323
|
+
nullable: false,
|
|
324
|
+
default: void 0
|
|
325
|
+
});
|
|
326
|
+
columns.push({
|
|
327
|
+
name: "_parent_table",
|
|
328
|
+
type: "varchar(255)",
|
|
329
|
+
nullable: false,
|
|
330
|
+
default: void 0
|
|
331
|
+
});
|
|
332
|
+
columns.push({
|
|
333
|
+
name: "_parent_field",
|
|
334
|
+
type: "varchar(255)",
|
|
335
|
+
nullable: false,
|
|
336
|
+
default: void 0
|
|
337
|
+
});
|
|
338
|
+
columns.push({
|
|
339
|
+
name: "_order",
|
|
340
|
+
type: "int(11)",
|
|
341
|
+
nullable: true,
|
|
342
|
+
default: void 0
|
|
343
|
+
});
|
|
344
|
+
columns.push({
|
|
345
|
+
name: "_component_type",
|
|
346
|
+
type: "varchar(255)",
|
|
347
|
+
nullable: true,
|
|
348
|
+
default: void 0
|
|
349
|
+
});
|
|
277
350
|
} else {
|
|
278
|
-
columns.push({
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
351
|
+
columns.push({
|
|
352
|
+
name: "id",
|
|
353
|
+
type: "text",
|
|
354
|
+
nullable: false,
|
|
355
|
+
default: void 0
|
|
356
|
+
});
|
|
357
|
+
columns.push({
|
|
358
|
+
name: "_parent_id",
|
|
359
|
+
type: "text",
|
|
360
|
+
nullable: false,
|
|
361
|
+
default: void 0
|
|
362
|
+
});
|
|
363
|
+
columns.push({
|
|
364
|
+
name: "_parent_table",
|
|
365
|
+
type: "text",
|
|
366
|
+
nullable: false,
|
|
367
|
+
default: void 0
|
|
368
|
+
});
|
|
369
|
+
columns.push({
|
|
370
|
+
name: "_parent_field",
|
|
371
|
+
type: "text",
|
|
372
|
+
nullable: false,
|
|
373
|
+
default: void 0
|
|
374
|
+
});
|
|
375
|
+
columns.push({
|
|
376
|
+
name: "_order",
|
|
377
|
+
type: "integer",
|
|
378
|
+
nullable: true,
|
|
379
|
+
default: void 0
|
|
380
|
+
});
|
|
381
|
+
columns.push({
|
|
382
|
+
name: "_component_type",
|
|
383
|
+
type: "text",
|
|
384
|
+
nullable: true,
|
|
385
|
+
default: void 0
|
|
386
|
+
});
|
|
284
387
|
}
|
|
285
388
|
for (const field of fields) {
|
|
286
389
|
const desc = getColumnDescriptor(
|
|
@@ -296,18 +399,104 @@ function buildDesiredTableFromComponentFields(tableName, fields, dialect) {
|
|
|
296
399
|
});
|
|
297
400
|
}
|
|
298
401
|
if (dialect === "postgresql") {
|
|
299
|
-
columns.push({
|
|
300
|
-
|
|
402
|
+
columns.push({
|
|
403
|
+
name: "created_at",
|
|
404
|
+
type: "timestamp",
|
|
405
|
+
nullable: false,
|
|
406
|
+
default: void 0
|
|
407
|
+
});
|
|
408
|
+
columns.push({
|
|
409
|
+
name: "updated_at",
|
|
410
|
+
type: "timestamp",
|
|
411
|
+
nullable: false,
|
|
412
|
+
default: void 0
|
|
413
|
+
});
|
|
301
414
|
} else if (dialect === "mysql") {
|
|
302
|
-
columns.push({
|
|
303
|
-
|
|
415
|
+
columns.push({
|
|
416
|
+
name: "created_at",
|
|
417
|
+
type: "datetime",
|
|
418
|
+
nullable: false,
|
|
419
|
+
default: void 0
|
|
420
|
+
});
|
|
421
|
+
columns.push({
|
|
422
|
+
name: "updated_at",
|
|
423
|
+
type: "datetime",
|
|
424
|
+
nullable: false,
|
|
425
|
+
default: void 0
|
|
426
|
+
});
|
|
304
427
|
} else {
|
|
305
|
-
columns.push({
|
|
306
|
-
|
|
428
|
+
columns.push({
|
|
429
|
+
name: "created_at",
|
|
430
|
+
type: "integer",
|
|
431
|
+
nullable: false,
|
|
432
|
+
default: void 0
|
|
433
|
+
});
|
|
434
|
+
columns.push({
|
|
435
|
+
name: "updated_at",
|
|
436
|
+
type: "integer",
|
|
437
|
+
nullable: false,
|
|
438
|
+
default: void 0
|
|
439
|
+
});
|
|
307
440
|
}
|
|
308
441
|
return { name: tableName, columns };
|
|
309
442
|
}
|
|
310
443
|
|
|
444
|
+
// src/domains/schema/pipeline/diff/normalize-default.ts
|
|
445
|
+
var PG_REDUNDANT_CAST_TYPES = [
|
|
446
|
+
// Two-word forms come first so the regex prefers the longer match.
|
|
447
|
+
"character varying",
|
|
448
|
+
"character",
|
|
449
|
+
"double precision",
|
|
450
|
+
"timestamp without time zone",
|
|
451
|
+
"timestamp with time zone",
|
|
452
|
+
"time without time zone",
|
|
453
|
+
"time with time zone",
|
|
454
|
+
// Single-word forms.
|
|
455
|
+
"text",
|
|
456
|
+
"varchar",
|
|
457
|
+
"bpchar",
|
|
458
|
+
"integer",
|
|
459
|
+
"bigint",
|
|
460
|
+
"smallint",
|
|
461
|
+
"numeric",
|
|
462
|
+
"real",
|
|
463
|
+
"boolean",
|
|
464
|
+
"uuid",
|
|
465
|
+
"jsonb",
|
|
466
|
+
"json"
|
|
467
|
+
];
|
|
468
|
+
var CAST_SUFFIX_RE = new RegExp(
|
|
469
|
+
`::(?:${PG_REDUNDANT_CAST_TYPES.join("|")})$`,
|
|
470
|
+
"i"
|
|
471
|
+
);
|
|
472
|
+
var NORMALIZE_LOWERCASE_FUNCTIONS = /* @__PURE__ */ new Set(["now()"]);
|
|
473
|
+
function normalizeDefault(expr) {
|
|
474
|
+
if (expr === void 0) return void 0;
|
|
475
|
+
let normalised = stripRedundantCast(expr);
|
|
476
|
+
const lower = normalised.toLowerCase();
|
|
477
|
+
if (NORMALIZE_LOWERCASE_FUNCTIONS.has(lower)) {
|
|
478
|
+
normalised = lower;
|
|
479
|
+
}
|
|
480
|
+
return normalised;
|
|
481
|
+
}
|
|
482
|
+
function stripRedundantCast(expr) {
|
|
483
|
+
const match = expr.match(CAST_SUFFIX_RE);
|
|
484
|
+
if (!match) return expr;
|
|
485
|
+
const beforeCast = expr.slice(0, match.index);
|
|
486
|
+
if (isCompleteLiteral(beforeCast)) {
|
|
487
|
+
return beforeCast;
|
|
488
|
+
}
|
|
489
|
+
return expr;
|
|
490
|
+
}
|
|
491
|
+
function isCompleteLiteral(value) {
|
|
492
|
+
if (value.startsWith("'") && value.endsWith("'") && value.length >= 2) {
|
|
493
|
+
return true;
|
|
494
|
+
}
|
|
495
|
+
if (/^-?[0-9]+(?:\.[0-9]+)?$/.test(value)) return true;
|
|
496
|
+
if (value === "true" || value === "false") return true;
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
|
|
311
500
|
// src/domains/schema/pipeline/diff/diff.ts
|
|
312
501
|
function diffSnapshots(prev, cur) {
|
|
313
502
|
const prevByName = /* @__PURE__ */ new Map();
|
|
@@ -387,7 +576,7 @@ function diffColumns(tableName, prev, cur) {
|
|
|
387
576
|
toNullable: curC.nullable
|
|
388
577
|
});
|
|
389
578
|
}
|
|
390
|
-
if (prevC.default !== curC.default) {
|
|
579
|
+
if (normalizeDefault(prevC.default) !== normalizeDefault(curC.default)) {
|
|
391
580
|
defaultChanges.push({
|
|
392
581
|
type: "change_column_default",
|
|
393
582
|
tableName,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-5HMZ644B.mjs";
|
|
5
5
|
import {
|
|
6
6
|
BaseService
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ERTNRSP3.mjs";
|
|
8
8
|
import {
|
|
9
9
|
NextlyError,
|
|
10
10
|
toDbError
|
|
@@ -380,6 +380,8 @@ var CollectionRegistryService = class extends BaseRegistryService {
|
|
|
380
380
|
resourceType = "Collection";
|
|
381
381
|
tableNamePrefix = "dc_";
|
|
382
382
|
permissionSeedService;
|
|
383
|
+
/** Invoked when code-first sync resolves a new `tableName` for an existing slug. */
|
|
384
|
+
onTableNameChanged;
|
|
383
385
|
constructor(adapter, logger) {
|
|
384
386
|
super(adapter, logger);
|
|
385
387
|
}
|
|
@@ -390,6 +392,10 @@ var CollectionRegistryService = class extends BaseRegistryService {
|
|
|
390
392
|
setPermissionSeedService(service) {
|
|
391
393
|
this.permissionSeedService = service;
|
|
392
394
|
}
|
|
395
|
+
/** Register a callback fired when sync resolves a new `tableName` for a slug. */
|
|
396
|
+
setOnTableNameChanged(callback) {
|
|
397
|
+
this.onTableNameChanged = callback;
|
|
398
|
+
}
|
|
393
399
|
async getCollectionBySlug(slug) {
|
|
394
400
|
return this.getRecordBySlug(slug);
|
|
395
401
|
}
|
|
@@ -543,6 +549,9 @@ var CollectionRegistryService = class extends BaseRegistryService {
|
|
|
543
549
|
if (data.status !== void 0) {
|
|
544
550
|
updateData.status = data.status === true ? 1 : 0;
|
|
545
551
|
}
|
|
552
|
+
if (data.tableName !== void 0) {
|
|
553
|
+
updateData.table_name = this.ensureTableNamePrefix(data.tableName);
|
|
554
|
+
}
|
|
546
555
|
try {
|
|
547
556
|
const results = await this.adapter.update(
|
|
548
557
|
this.registryTableName,
|
|
@@ -600,11 +609,12 @@ var CollectionRegistryService = class extends BaseRegistryService {
|
|
|
600
609
|
try {
|
|
601
610
|
const existing = await this.getCollectionBySlug(config.slug);
|
|
602
611
|
const schemaHash = calculateSchemaHash(config.fields);
|
|
612
|
+
const desiredTableName = config.tableName ? this.ensureTableNamePrefix(config.tableName) : this.generateTableName(config.slug);
|
|
603
613
|
if (!existing) {
|
|
604
614
|
await this.registerCollection({
|
|
605
615
|
slug: config.slug,
|
|
606
616
|
labels: config.labels,
|
|
607
|
-
tableName:
|
|
617
|
+
tableName: desiredTableName,
|
|
608
618
|
description: config.description,
|
|
609
619
|
fields: config.fields,
|
|
610
620
|
timestamps: config.timestamps ?? true,
|
|
@@ -619,7 +629,15 @@ var CollectionRegistryService = class extends BaseRegistryService {
|
|
|
619
629
|
});
|
|
620
630
|
result.created.push(config.slug);
|
|
621
631
|
await this.seedPermissionsForCollection(config.slug);
|
|
622
|
-
} else if (!schemaHashesMatch(schemaHash, existing.schemaHash) || config.status === true !== (existing.status === true)) {
|
|
632
|
+
} else if (!schemaHashesMatch(schemaHash, existing.schemaHash) || config.status === true !== (existing.status === true) || desiredTableName !== existing.tableName) {
|
|
633
|
+
if (desiredTableName !== existing.tableName) {
|
|
634
|
+
await this.renamePhysicalTable(
|
|
635
|
+
existing.tableName,
|
|
636
|
+
desiredTableName,
|
|
637
|
+
config.slug
|
|
638
|
+
);
|
|
639
|
+
this.onTableNameChanged?.(config.slug);
|
|
640
|
+
}
|
|
623
641
|
await this.updateCollection(
|
|
624
642
|
config.slug,
|
|
625
643
|
{
|
|
@@ -631,7 +649,8 @@ var CollectionRegistryService = class extends BaseRegistryService {
|
|
|
631
649
|
configPath: config.configPath,
|
|
632
650
|
schemaHash,
|
|
633
651
|
locked: true,
|
|
634
|
-
status: config.status === true
|
|
652
|
+
status: config.status === true,
|
|
653
|
+
tableName: desiredTableName
|
|
635
654
|
},
|
|
636
655
|
{ source: "code" }
|
|
637
656
|
);
|
|
@@ -755,6 +774,41 @@ var CollectionRegistryService = class extends BaseRegistryService {
|
|
|
755
774
|
);
|
|
756
775
|
return this.deserializeRecord(result);
|
|
757
776
|
}
|
|
777
|
+
/**
|
|
778
|
+
* Rename the physical table when a code-first collection's `dbName` changes.
|
|
779
|
+
* Renames only when old exists and new doesn't; warns when both exist; no-op
|
|
780
|
+
* otherwise (boot auto-create handles the missing-table case).
|
|
781
|
+
*/
|
|
782
|
+
async renamePhysicalTable(oldTableName, newTableName, slug) {
|
|
783
|
+
let oldExists;
|
|
784
|
+
let newExists;
|
|
785
|
+
try {
|
|
786
|
+
oldExists = await this.adapter.tableExists(oldTableName);
|
|
787
|
+
newExists = await this.adapter.tableExists(newTableName);
|
|
788
|
+
} catch (error) {
|
|
789
|
+
this.logger.warn(
|
|
790
|
+
`Skipping rename for collection "${slug}": table introspection failed (${error instanceof Error ? error.message : String(error)}). Boot pipeline will reconcile.`
|
|
791
|
+
);
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
if (oldExists && !newExists) {
|
|
795
|
+
try {
|
|
796
|
+
const { dialect } = this.adapter.getCapabilities();
|
|
797
|
+
const q = dialect === "mysql" ? "`" : '"';
|
|
798
|
+
await this.adapter.executeQuery(
|
|
799
|
+
`ALTER TABLE ${q}${oldTableName}${q} RENAME TO ${q}${newTableName}${q}`
|
|
800
|
+
);
|
|
801
|
+
} catch (error) {
|
|
802
|
+
this.logger.warn(
|
|
803
|
+
`Failed to rename physical table for collection "${slug}" (${oldTableName} \u2192 ${newTableName}): ${error instanceof Error ? error.message : String(error)}`
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
} else if (oldExists && newExists) {
|
|
807
|
+
this.logger.warn(
|
|
808
|
+
`Cannot rename physical table for collection "${slug}": both "${oldTableName}" and "${newTableName}" exist. Resolve manually (drop one or copy rows).`
|
|
809
|
+
);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
758
812
|
async seedPermissionsForCollection(slug) {
|
|
759
813
|
if (!this.permissionSeedService) return;
|
|
760
814
|
try {
|
|
@@ -57,7 +57,7 @@ async function createAdapter(options = {}) {
|
|
|
57
57
|
);
|
|
58
58
|
}
|
|
59
59
|
logger?.debug(`Creating ${dialect} adapter...`);
|
|
60
|
-
const { createAdapterFromEnv } = await import("./factory-
|
|
60
|
+
const { createAdapterFromEnv } = await import("./factory-UGJGOZZ7.mjs");
|
|
61
61
|
const originalDialect = process.env.DB_DIALECT;
|
|
62
62
|
const originalUrl = process.env.DATABASE_URL;
|
|
63
63
|
try {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
seedPermissions
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WRGCEERR.mjs";
|
|
4
4
|
import {
|
|
5
5
|
seedSuperAdmin
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6GWK77EN.mjs";
|
|
7
7
|
|
|
8
8
|
// src/database/seeders/index.ts
|
|
9
9
|
async function seedAll(adapter, options) {
|
|
@@ -5,7 +5,7 @@ async function runBootTimeApplyIfDev(opts) {
|
|
|
5
5
|
if (process.env.NEXTLY_DISABLE_BOOT_APPLY === "1") return;
|
|
6
6
|
const label = callerLabel(opts?.caller);
|
|
7
7
|
try {
|
|
8
|
-
const { reloadNextlyConfig } = await import("./reload-config-
|
|
8
|
+
const { reloadNextlyConfig } = await import("./reload-config-52GWTPZG.mjs");
|
|
9
9
|
await reloadNextlyConfig();
|
|
10
10
|
} catch (err) {
|
|
11
11
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ClackTerminalPromptDispatcher
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6C3CST4Q.mjs";
|
|
4
4
|
import {
|
|
5
5
|
getAdapterFromDI,
|
|
6
6
|
getCollectionRegistryFromDI,
|
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
getProductionNotifier,
|
|
15
15
|
noopMigrationJournal,
|
|
16
16
|
noopPreRenameExecutor
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-UGB6MLR6.mjs";
|
|
18
18
|
import {
|
|
19
19
|
RealClassifier,
|
|
20
20
|
RegexRenameDetector
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-JCQMC6HH.mjs";
|
|
22
22
|
|
|
23
23
|
// src/domains/schema/pipeline/snapshot.ts
|
|
24
24
|
function buildDesiredSchemaFromRegistry(registry, overrides) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ClackTerminalPromptDispatcher
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6C3CST4Q.mjs";
|
|
4
4
|
import {
|
|
5
5
|
extractDatabaseNameFromUrl
|
|
6
6
|
} from "./chunk-KIMNCZGV.mjs";
|
|
@@ -8,21 +8,23 @@ import {
|
|
|
8
8
|
DrizzleStatementExecutor,
|
|
9
9
|
PushSchemaPipeline,
|
|
10
10
|
RealPreCleanupExecutor,
|
|
11
|
+
clearLiveSnapshots,
|
|
11
12
|
createApplyDesiredSchema,
|
|
12
13
|
getProductionNotifier,
|
|
13
14
|
noopMigrationJournal,
|
|
14
|
-
noopPreRenameExecutor
|
|
15
|
-
|
|
15
|
+
noopPreRenameExecutor,
|
|
16
|
+
setLiveSnapshot
|
|
17
|
+
} from "./chunk-UGB6MLR6.mjs";
|
|
16
18
|
import {
|
|
17
19
|
RealClassifier,
|
|
18
20
|
RegexRenameDetector,
|
|
19
21
|
buildDesiredTableFromFields,
|
|
20
22
|
diffSnapshots,
|
|
21
23
|
introspectLiveSnapshot
|
|
22
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-JCQMC6HH.mjs";
|
|
23
25
|
import {
|
|
24
26
|
generateRuntimeSchema
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-2QSGNGOB.mjs";
|
|
26
28
|
|
|
27
29
|
// src/domains/schema/utils/resolve-table-name.ts
|
|
28
30
|
function resolveCollectionTableName(slug, dbName) {
|
|
@@ -33,7 +35,7 @@ function resolveCollectionTableName(slug, dbName) {
|
|
|
33
35
|
|
|
34
36
|
// src/init/reload-config.ts
|
|
35
37
|
async function defaultResolver(name) {
|
|
36
|
-
const { getService } = await import("./register-
|
|
38
|
+
const { getService } = await import("./register-FCUTHDS5.mjs");
|
|
37
39
|
return getService(name);
|
|
38
40
|
}
|
|
39
41
|
async function reloadNextlyConfig(opts) {
|
|
@@ -99,18 +101,17 @@ async function reloadNextlyConfig(opts) {
|
|
|
99
101
|
fields: c.fields ?? []
|
|
100
102
|
});
|
|
101
103
|
}
|
|
102
|
-
if (targets.length === 0 && singleTargets.length === 0 && componentTargets.length === 0)
|
|
104
|
+
if (targets.length === 0 && singleTargets.length === 0 && componentTargets.length === 0)
|
|
105
|
+
return;
|
|
106
|
+
const managedTableNames = [
|
|
107
|
+
...targets.map((t) => t.tableName),
|
|
108
|
+
...singleTargets.map((t) => t.tableName),
|
|
109
|
+
...componentTargets.map((t) => t.tableName)
|
|
110
|
+
];
|
|
111
|
+
clearLiveSnapshots();
|
|
103
112
|
let liveSnapshot;
|
|
104
113
|
try {
|
|
105
|
-
liveSnapshot = await introspectLiveSnapshot(
|
|
106
|
-
db,
|
|
107
|
-
dialect,
|
|
108
|
-
[
|
|
109
|
-
...targets.map((t) => t.tableName),
|
|
110
|
-
...singleTargets.map((t) => t.tableName),
|
|
111
|
-
...componentTargets.map((t) => t.tableName)
|
|
112
|
-
]
|
|
113
|
-
);
|
|
114
|
+
liveSnapshot = await introspectLiveSnapshot(db, dialect, managedTableNames);
|
|
114
115
|
} catch (err) {
|
|
115
116
|
const msg = err instanceof Error ? err.message : String(err);
|
|
116
117
|
logger?.error(
|
|
@@ -118,6 +119,7 @@ async function reloadNextlyConfig(opts) {
|
|
|
118
119
|
);
|
|
119
120
|
return;
|
|
120
121
|
}
|
|
122
|
+
setLiveSnapshot(managedTableNames, liveSnapshot);
|
|
121
123
|
const liveByTable = /* @__PURE__ */ new Map();
|
|
122
124
|
for (const t of liveSnapshot.tables) liveByTable.set(t.name, t);
|
|
123
125
|
let hasChanges = false;
|
|
@@ -383,7 +385,9 @@ async function reloadNextlyConfig(opts) {
|
|
|
383
385
|
} catch {
|
|
384
386
|
}
|
|
385
387
|
try {
|
|
386
|
-
const schemaReg = await resolve(
|
|
388
|
+
const schemaReg = await resolve(
|
|
389
|
+
"schemaRegistry"
|
|
390
|
+
);
|
|
387
391
|
for (const [tableName, table] of collectionFreshTables) {
|
|
388
392
|
schemaReg.registerDynamicSchema(tableName, table);
|
|
389
393
|
}
|
|
@@ -413,10 +417,7 @@ async function reloadNextlyConfig(opts) {
|
|
|
413
417
|
if (!applyResult.success) {
|
|
414
418
|
const code = applyResult.error.code;
|
|
415
419
|
if (code === "CONFIRMATION_REQUIRED_NO_TTY") {
|
|
416
|
-
const detail = applyResult.error.message.replace(/^TTY required for schema confirmation\.\s*/i, "").replace(
|
|
417
|
-
/\s*Run from an interactive terminal,.*$/i,
|
|
418
|
-
""
|
|
419
|
-
).trim();
|
|
420
|
+
const detail = applyResult.error.message.replace(/^TTY required for schema confirmation\.\s*/i, "").replace(/\s*Run from an interactive terminal,.*$/i, "").trim();
|
|
420
421
|
console.warn(
|
|
421
422
|
`
|
|
422
423
|
[Nextly] Schema change needs your confirmation:
|
|
@@ -442,28 +443,7 @@ explicit confirmation.
|
|
|
442
443
|
}
|
|
443
444
|
function classifyForCodeFirst(operations, _dialect) {
|
|
444
445
|
if (operations.length === 0) return { safe: true };
|
|
445
|
-
const dropsPerTable = /* @__PURE__ */ new Map();
|
|
446
|
-
const addsPerTable = /* @__PURE__ */ new Map();
|
|
447
|
-
for (const op of operations) {
|
|
448
|
-
if (op.type === "drop_column") {
|
|
449
|
-
dropsPerTable.set(
|
|
450
|
-
op.tableName,
|
|
451
|
-
(dropsPerTable.get(op.tableName) ?? 0) + 1
|
|
452
|
-
);
|
|
453
|
-
} else if (op.type === "add_column") {
|
|
454
|
-
addsPerTable.set(op.tableName, (addsPerTable.get(op.tableName) ?? 0) + 1);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
446
|
const reasons = [];
|
|
458
|
-
for (const [t, drops] of dropsPerTable) {
|
|
459
|
-
const adds = addsPerTable.get(t) ?? 0;
|
|
460
|
-
if (drops > adds) {
|
|
461
|
-
const surplus = drops - adds;
|
|
462
|
-
reasons.push(
|
|
463
|
-
adds === 0 ? `drops ${drops} column(s) from '${t}' with no replacement(s); ${surplus} cannot be renamed without data loss` : `drops ${drops} columns from '${t}' but only ${adds} replacement(s); at least ${surplus} cannot be renamed without data loss`
|
|
464
|
-
);
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
447
|
for (const op of operations) {
|
|
468
448
|
if (op.type === "drop_table") {
|
|
469
449
|
reasons.push(`drops table '${op.tableName}'`);
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
PermissionService,
|
|
6
6
|
RolePermissionService,
|
|
7
7
|
SYSTEM_RESOURCES
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ILETUFUD.mjs";
|
|
9
9
|
import {
|
|
10
10
|
BaseRegistryService,
|
|
11
11
|
assertGlobalResourceSlugAvailable
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JGVOZSXS.mjs";
|
|
13
13
|
import {
|
|
14
14
|
resolveSingleTableName
|
|
15
15
|
} from "./chunk-I4JMR3UR.mjs";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "./chunk-5HMZ644B.mjs";
|
|
20
20
|
import {
|
|
21
21
|
BaseService
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-ERTNRSP3.mjs";
|
|
23
23
|
import {
|
|
24
24
|
NextlyError,
|
|
25
25
|
toDbError
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
isErrorResponse,
|
|
3
3
|
requireAuthentication,
|
|
4
4
|
toNextlyAuthError
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-V5DUKEYT.mjs";
|
|
6
6
|
import {
|
|
7
7
|
nextlyValidationFromZod
|
|
8
8
|
} from "./chunk-GJNSJU4S.mjs";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-TO5AFLVQ.mjs";
|
|
12
12
|
import {
|
|
13
13
|
getCachedNextly
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ZDNGCKSZ.mjs";
|
|
15
15
|
import {
|
|
16
16
|
respondAction
|
|
17
17
|
} from "./chunk-IUDOC7N7.mjs";
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
isErrorResponse,
|
|
3
3
|
requireAuthentication,
|
|
4
4
|
toNextlyAuthError
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-V5DUKEYT.mjs";
|
|
6
6
|
import {
|
|
7
7
|
nextlyValidationFromZod
|
|
8
8
|
} from "./chunk-GJNSJU4S.mjs";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-TO5AFLVQ.mjs";
|
|
12
12
|
import {
|
|
13
13
|
getCachedNextly
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ZDNGCKSZ.mjs";
|
|
15
15
|
import {
|
|
16
16
|
respondAction
|
|
17
17
|
} from "./chunk-IUDOC7N7.mjs";
|