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.
Files changed (93) hide show
  1. package/dist/_dts-chunks/{collections-handler.d-DjgO74Wt.d.ts → collections-handler.d-B3iNFGJv.d.ts} +135 -120
  2. package/dist/_dts-chunks/{config.d-DNwsDnjs.d.ts → config.d-D8eInFE5.d.ts} +13 -1
  3. package/dist/_dts-chunks/{define-component.d-BUgTHmt3.d.ts → define-component.d-COeEsUOT.d.ts} +2 -2
  4. package/dist/_dts-chunks/{index.d-axCAzZ7m.d.ts → index.d-qjDq8N63.d.ts} +5 -5
  5. package/dist/actions/index.mjs +15 -15
  6. package/dist/api/auth-state.mjs +21 -21
  7. package/dist/api/collections-schema-detail.mjs +21 -21
  8. package/dist/api/collections-schema-export.mjs +21 -21
  9. package/dist/api/collections-schema.mjs +21 -21
  10. package/dist/api/components-detail.mjs +21 -21
  11. package/dist/api/components.mjs +21 -21
  12. package/dist/api/email-providers-default.mjs +21 -21
  13. package/dist/api/email-providers-detail.mjs +21 -21
  14. package/dist/api/email-providers-test.mjs +21 -21
  15. package/dist/api/email-providers.mjs +21 -21
  16. package/dist/api/email-send-template.mjs +23 -23
  17. package/dist/api/email-send.mjs +23 -23
  18. package/dist/api/email-templates-detail.mjs +21 -21
  19. package/dist/api/email-templates-layout.mjs +21 -21
  20. package/dist/api/email-templates-preview.mjs +21 -21
  21. package/dist/api/email-templates.mjs +21 -21
  22. package/dist/api/media-bulk.mjs +17 -17
  23. package/dist/api/media-folders.mjs +21 -21
  24. package/dist/api/media-handlers.d.ts +2 -2
  25. package/dist/api/media-handlers.mjs +21 -21
  26. package/dist/api/media.mjs +21 -21
  27. package/dist/api/singles-detail.mjs +21 -21
  28. package/dist/api/singles-schema-detail.mjs +21 -21
  29. package/dist/api/singles.mjs +21 -21
  30. package/dist/api/storage-upload-url.mjs +21 -21
  31. package/dist/api/uploads.mjs +27 -26
  32. package/dist/auth/index.mjs +6 -6
  33. package/dist/{boot-apply-PQSYLDIN.mjs → boot-apply-OE3D3KNU.mjs} +1 -1
  34. package/dist/{chunk-IZWPRDC3.mjs → chunk-2QSGNGOB.mjs} +1 -1
  35. package/dist/{chunk-DP3G27G5.mjs → chunk-35LAHTCU.mjs} +12 -2
  36. package/dist/{chunk-DNNG377Z.mjs → chunk-463A2UDH.mjs} +79 -13
  37. package/dist/{chunk-V4EQTOA4.mjs → chunk-4HUQNXVM.mjs} +2 -2
  38. package/dist/{chunk-VJ66NCL4.mjs → chunk-6C3CST4Q.mjs} +53 -4
  39. package/dist/{chunk-PKMABBB5.mjs → chunk-6GWK77EN.mjs} +1 -1
  40. package/dist/{chunk-XZKLBMN6.mjs → chunk-A75OLKXP.mjs} +44 -16
  41. package/dist/{chunk-TS7GHTG2.mjs → chunk-A7GGVOIV.mjs} +1 -1
  42. package/dist/{chunk-INV7QKLG.mjs → chunk-BZ2EOLXR.mjs} +1 -1
  43. package/dist/{chunk-X7TXCYYN.mjs → chunk-DQGQMP5F.mjs} +46 -26
  44. package/dist/{chunk-2W3DVD7S.mjs → chunk-ERTNRSP3.mjs} +1 -1
  45. package/dist/{chunk-UJ2IMJ4W.mjs → chunk-HREB7UR4.mjs} +10 -4
  46. package/dist/{chunk-NSEFNNU4.mjs → chunk-ILETUFUD.mjs} +302 -105
  47. package/dist/{chunk-A3WPLSDT.mjs → chunk-INTLFB63.mjs} +1 -1
  48. package/dist/{chunk-SBACDPNX.mjs → chunk-JCQMC6HH.mjs} +216 -27
  49. package/dist/{chunk-3FA7FKAV.mjs → chunk-JGVOZSXS.mjs} +58 -4
  50. package/dist/{chunk-M52VMPGA.mjs → chunk-KZFYCMBL.mjs} +1 -1
  51. package/dist/{chunk-W5KKPZT5.mjs → chunk-L7BXB5H3.mjs} +2 -2
  52. package/dist/{chunk-B2GV2BWH.mjs → chunk-MF4S2WSM.mjs} +2 -2
  53. package/dist/{chunk-R6JJQHFC.mjs → chunk-NXA6FD7R.mjs} +1 -1
  54. package/dist/{chunk-XGI4EMS3.mjs → chunk-OPACR7PX.mjs} +3 -3
  55. package/dist/{chunk-2OALJTK6.mjs → chunk-OV4WR3EC.mjs} +22 -42
  56. package/dist/{chunk-YZNBLFIW.mjs → chunk-RH3QV6E6.mjs} +3 -3
  57. package/dist/{chunk-LDKCUMHK.mjs → chunk-RQ3N4DIB.mjs} +2 -2
  58. package/dist/{chunk-YV4Y7SDL.mjs → chunk-TGBLNY5L.mjs} +2 -2
  59. package/dist/{chunk-GZ6DCQKC.mjs → chunk-TVG3WU6C.mjs} +5 -3
  60. package/dist/{chunk-AK6Z23OX.mjs → chunk-UGB6MLR6.mjs} +274 -45
  61. package/dist/{chunk-2Q2SX2CS.mjs → chunk-V5DUKEYT.mjs} +2 -2
  62. package/dist/{chunk-UOP63Q54.mjs → chunk-WRGCEERR.mjs} +1 -1
  63. package/dist/{chunk-O3QHXMOX.mjs → chunk-XCT6CROA.mjs} +23 -19
  64. package/dist/{chunk-P7NH2OSC.mjs → chunk-ZDNGCKSZ.mjs} +78 -49
  65. package/dist/cli/nextly.mjs +1 -1
  66. package/dist/cli/utils/index.d.ts +2 -2
  67. package/dist/cli/utils/index.mjs +1 -1
  68. package/dist/{component-schema-service-5577KVW6.mjs → component-schema-service-HUAQQ4H5.mjs} +2 -2
  69. package/dist/config.d.ts +3 -3
  70. package/dist/database/index.d.ts +2 -2
  71. package/dist/database/index.mjs +3 -3
  72. package/dist/database/seeders/index.mjs +18 -18
  73. package/dist/{db-sync-demote-LJGKLB3S.mjs → db-sync-demote-M7IEFD6N.mjs} +6 -6
  74. package/dist/{db-sync-promote-B26VSYQF.mjs → db-sync-promote-2MCB5JRZ.mjs} +6 -6
  75. package/dist/{dynamic-collection-schema-service-IEXTPIZ7.mjs → dynamic-collection-schema-service-FIRWOXZI.mjs} +2 -2
  76. package/dist/{factory-IWMBKUJM.mjs → factory-UGJGOZZ7.mjs} +2 -2
  77. package/dist/index.d.ts +16 -11
  78. package/dist/index.mjs +24 -55
  79. package/dist/{permissions-3DZZQZMI.mjs → permissions-KH3WCGAR.mjs} +16 -16
  80. package/dist/{pipeline-YOML7SWF.mjs → pipeline-JLANATHU.mjs} +10 -10
  81. package/dist/{preview-ZZTR3QGS.mjs → preview-3RSMZITY.mjs} +3 -3
  82. package/dist/{program-PW6UB2ZC.mjs → program-6V6HLEUI.mjs} +27 -27
  83. package/dist/{register-SF6E6FVU.mjs → register-FCUTHDS5.mjs} +17 -17
  84. package/dist/{reload-config-HWQ4G5MM.mjs → reload-config-52GWTPZG.mjs} +10 -10
  85. package/dist/{routeHandler-UNMMJIBM.mjs → routeHandler-FP26UQPJ.mjs} +26 -26
  86. package/dist/{runtime-schema-generator-NRA6A6Z6.mjs → runtime-schema-generator-NQOLDUDG.mjs} +2 -2
  87. package/dist/runtime.d.ts +2 -2
  88. package/dist/runtime.mjs +26 -26
  89. package/dist/{super-admin-G5ZK5F4T.mjs → super-admin-XZAU4VQM.mjs} +16 -16
  90. package/dist/{system-table-service-WGSRVEGT.mjs → system-table-service-5FIVIALU.mjs} +5 -5
  91. package/dist/{users-7KELGRYJ.mjs → users-K2NJTF55.mjs} +15 -15
  92. package/package.json +8 -8
  93. /package/dist/{first-run-QIVKWJIF.mjs → first-run-2UDWZK5X.mjs} +0 -0
@@ -35,7 +35,7 @@ import {
35
35
  PasswordSchema,
36
36
  validatePasswordStrength,
37
37
  verifyPassword
38
- } from "./chunk-W5KKPZT5.mjs";
38
+ } from "./chunk-L7BXB5H3.mjs";
39
39
  import {
40
40
  respondAction,
41
41
  respondData
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getColumnDescriptor,
3
3
  getSystemColumnDescriptors
4
- } from "./chunk-DNNG377Z.mjs";
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: void 0
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({ name: "id", type: "text", nullable: false, default: void 0 });
265
- columns.push({ name: "_parent_id", type: "text", nullable: false, default: void 0 });
266
- columns.push({ name: "_parent_table", type: "varchar", nullable: false, default: void 0 });
267
- columns.push({ name: "_parent_field", type: "varchar", nullable: false, default: void 0 });
268
- columns.push({ name: "_order", type: "int4", nullable: true, default: void 0 });
269
- columns.push({ name: "_component_type", type: "varchar", nullable: true, default: void 0 });
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({ name: "id", type: "varchar(36)", nullable: false, default: void 0 });
272
- columns.push({ name: "_parent_id", type: "varchar(36)", nullable: false, default: void 0 });
273
- columns.push({ name: "_parent_table", type: "varchar(255)", nullable: false, default: void 0 });
274
- columns.push({ name: "_parent_field", type: "varchar(255)", nullable: false, default: void 0 });
275
- columns.push({ name: "_order", type: "int(11)", nullable: true, default: void 0 });
276
- columns.push({ name: "_component_type", type: "varchar(255)", nullable: true, default: void 0 });
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({ name: "id", type: "text", nullable: false, default: void 0 });
279
- columns.push({ name: "_parent_id", type: "text", nullable: false, default: void 0 });
280
- columns.push({ name: "_parent_table", type: "text", nullable: false, default: void 0 });
281
- columns.push({ name: "_parent_field", type: "text", nullable: false, default: void 0 });
282
- columns.push({ name: "_order", type: "integer", nullable: true, default: void 0 });
283
- columns.push({ name: "_component_type", type: "text", nullable: true, default: void 0 });
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({ name: "created_at", type: "timestamp", nullable: false, default: void 0 });
300
- columns.push({ name: "updated_at", type: "timestamp", nullable: false, default: void 0 });
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({ name: "created_at", type: "datetime", nullable: false, default: void 0 });
303
- columns.push({ name: "updated_at", type: "datetime", nullable: false, default: void 0 });
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({ name: "created_at", type: "integer", nullable: false, default: void 0 });
306
- columns.push({ name: "updated_at", type: "integer", nullable: false, default: void 0 });
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-2W3DVD7S.mjs";
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: config.tableName ?? this.generateTableName(config.slug),
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-IWMBKUJM.mjs");
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
  BaseService
3
- } from "./chunk-2W3DVD7S.mjs";
3
+ } from "./chunk-ERTNRSP3.mjs";
4
4
  import {
5
5
  getDialectTables
6
- } from "./chunk-TS7GHTG2.mjs";
6
+ } from "./chunk-A7GGVOIV.mjs";
7
7
  import {
8
8
  getAuthLogger
9
9
  } from "./chunk-LAZXX4HR.mjs";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  seedPermissions
3
- } from "./chunk-UOP63Q54.mjs";
3
+ } from "./chunk-WRGCEERR.mjs";
4
4
  import {
5
5
  seedSuperAdmin
6
- } from "./chunk-PKMABBB5.mjs";
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-HWQ4G5MM.mjs");
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-VJ66NCL4.mjs";
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-AK6Z23OX.mjs";
17
+ } from "./chunk-UGB6MLR6.mjs";
18
18
  import {
19
19
  RealClassifier,
20
20
  RegexRenameDetector
21
- } from "./chunk-SBACDPNX.mjs";
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-VJ66NCL4.mjs";
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
- } from "./chunk-AK6Z23OX.mjs";
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-SBACDPNX.mjs";
24
+ } from "./chunk-JCQMC6HH.mjs";
23
25
  import {
24
26
  generateRuntimeSchema
25
- } from "./chunk-IZWPRDC3.mjs";
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-SF6E6FVU.mjs");
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) return;
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("schemaRegistry");
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-NSEFNNU4.mjs";
8
+ } from "./chunk-ILETUFUD.mjs";
9
9
  import {
10
10
  BaseRegistryService,
11
11
  assertGlobalResourceSlugAvailable
12
- } from "./chunk-3FA7FKAV.mjs";
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-2W3DVD7S.mjs";
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-2Q2SX2CS.mjs";
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-P7NH2OSC.mjs";
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-2Q2SX2CS.mjs";
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-P7NH2OSC.mjs";
14
+ } from "./chunk-ZDNGCKSZ.mjs";
15
15
  import {
16
16
  respondAction
17
17
  } from "./chunk-IUDOC7N7.mjs";