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
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
countRows,
|
|
8
8
|
diffSnapshots,
|
|
9
9
|
introspectLiveSnapshot
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JCQMC6HH.mjs";
|
|
11
11
|
|
|
12
12
|
// src/domains/schema/pipeline/preview.ts
|
|
13
13
|
async function previewDesiredSchema(args, deps = {}) {
|
|
@@ -25,14 +25,16 @@ async function previewDesiredSchema(args, deps = {}) {
|
|
|
25
25
|
(c) => buildDesiredTableFromFields(
|
|
26
26
|
c.tableName,
|
|
27
27
|
c.fields,
|
|
28
|
-
dialect
|
|
28
|
+
dialect,
|
|
29
|
+
{ hasStatus: c.status === true }
|
|
29
30
|
)
|
|
30
31
|
);
|
|
31
32
|
const singleTables = Object.values(desired.singles).map(
|
|
32
33
|
(s) => buildDesiredTableFromFields(
|
|
33
34
|
s.tableName,
|
|
34
35
|
s.fields,
|
|
35
|
-
dialect
|
|
36
|
+
dialect,
|
|
37
|
+
{ hasStatus: s.status === true }
|
|
36
38
|
)
|
|
37
39
|
);
|
|
38
40
|
const componentTables = Object.values(desired.components).map(
|
|
@@ -5,16 +5,16 @@ import {
|
|
|
5
5
|
countRows,
|
|
6
6
|
diffSnapshots,
|
|
7
7
|
introspectLiveSnapshot
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JCQMC6HH.mjs";
|
|
9
9
|
import {
|
|
10
10
|
ComponentSchemaService
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-4HUQNXVM.mjs";
|
|
12
12
|
import {
|
|
13
13
|
generateRuntimeSchema
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-2QSGNGOB.mjs";
|
|
15
15
|
import {
|
|
16
16
|
getDialectTables
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-A7GGVOIV.mjs";
|
|
18
18
|
|
|
19
19
|
// src/domains/schema/pipeline/errors.ts
|
|
20
20
|
import { UnsupportedDialectVersionError } from "@nextlyhq/adapter-drizzle/version-check";
|
|
@@ -285,9 +285,6 @@ var RealPreCleanupExecutor = class {
|
|
|
285
285
|
}
|
|
286
286
|
};
|
|
287
287
|
|
|
288
|
-
// src/domains/schema/pipeline/pushschema-pipeline.ts
|
|
289
|
-
import { dequal } from "dequal";
|
|
290
|
-
|
|
291
288
|
// src/init/schema-snapshot-cache.ts
|
|
292
289
|
var g = globalThis;
|
|
293
290
|
function getCachedSnapshot() {
|
|
@@ -296,6 +293,27 @@ function getCachedSnapshot() {
|
|
|
296
293
|
function setCachedSnapshot(snapshot) {
|
|
297
294
|
g.__nextly_prevSchemaSnapshot = snapshot;
|
|
298
295
|
}
|
|
296
|
+
function keyOf(tableNames) {
|
|
297
|
+
return [...tableNames].sort().join(" ");
|
|
298
|
+
}
|
|
299
|
+
function bag() {
|
|
300
|
+
return globalThis;
|
|
301
|
+
}
|
|
302
|
+
function getLiveSnapshot(managedTableNames) {
|
|
303
|
+
return bag().__nextly_liveSnapshots?.get(keyOf(managedTableNames));
|
|
304
|
+
}
|
|
305
|
+
function setLiveSnapshot(managedTableNames, snapshot) {
|
|
306
|
+
const b = bag();
|
|
307
|
+
if (!b.__nextly_liveSnapshots) b.__nextly_liveSnapshots = /* @__PURE__ */ new Map();
|
|
308
|
+
b.__nextly_liveSnapshots.set(keyOf(managedTableNames), snapshot);
|
|
309
|
+
}
|
|
310
|
+
function clearLiveSnapshots() {
|
|
311
|
+
const b = bag();
|
|
312
|
+
if (b.__nextly_liveSnapshots) b.__nextly_liveSnapshots.clear();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// src/domains/schema/pipeline/pushschema-pipeline.ts
|
|
316
|
+
import { dequal } from "dequal";
|
|
299
317
|
|
|
300
318
|
// src/runtime/notifications/build-event.ts
|
|
301
319
|
function buildNotificationEvent(args) {
|
|
@@ -323,6 +341,96 @@ function buildNotificationEvent(args) {
|
|
|
323
341
|
};
|
|
324
342
|
}
|
|
325
343
|
|
|
344
|
+
// src/domains/schema/pipeline/ddl-emitter/identifiers.ts
|
|
345
|
+
function quoteIdent(identifier) {
|
|
346
|
+
if (identifier.includes("\0")) {
|
|
347
|
+
throw new Error(
|
|
348
|
+
`Invalid identifier (contains NUL byte): ${JSON.stringify(identifier)}`
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
return `"${identifier.replace(/"/g, '""')}"`;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// src/domains/schema/pipeline/ddl-emitter/postgres.ts
|
|
355
|
+
function columnTail(col) {
|
|
356
|
+
let s = col.type;
|
|
357
|
+
if (col.nullable === false) s += " NOT NULL";
|
|
358
|
+
if (col.default !== void 0) s += ` DEFAULT ${col.default}`;
|
|
359
|
+
return s;
|
|
360
|
+
}
|
|
361
|
+
function createTableColumn(col) {
|
|
362
|
+
if (col.name === "id") {
|
|
363
|
+
return `${quoteIdent(col.name)} ${col.type} PRIMARY KEY NOT NULL`;
|
|
364
|
+
}
|
|
365
|
+
return `${quoteIdent(col.name)} ${columnTail(col)}`;
|
|
366
|
+
}
|
|
367
|
+
function createTableCanonicalIndexes(spec) {
|
|
368
|
+
const colNames = new Set(spec.columns.map((c) => c.name));
|
|
369
|
+
const stmts = [];
|
|
370
|
+
if (colNames.has("slug")) {
|
|
371
|
+
stmts.push(
|
|
372
|
+
`CREATE UNIQUE INDEX ${quoteIdent(`idx_${spec.name}_slug`)} ON ${quoteIdent(spec.name)} USING btree (${quoteIdent("slug")})`
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
if (colNames.has("created_at")) {
|
|
376
|
+
stmts.push(
|
|
377
|
+
`CREATE INDEX ${quoteIdent(`idx_${spec.name}_created_at`)} ON ${quoteIdent(spec.name)} USING btree (${quoteIdent("created_at")} DESC)`
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
return stmts;
|
|
381
|
+
}
|
|
382
|
+
function emitPostgresDdl(op) {
|
|
383
|
+
switch (op.type) {
|
|
384
|
+
case "rename_table":
|
|
385
|
+
case "rename_column":
|
|
386
|
+
case "drop_column":
|
|
387
|
+
case "drop_table":
|
|
388
|
+
return [];
|
|
389
|
+
case "add_column":
|
|
390
|
+
return [
|
|
391
|
+
`ALTER TABLE ${quoteIdent(op.tableName)} ADD COLUMN ${quoteIdent(op.column.name)} ${columnTail(op.column)}`
|
|
392
|
+
];
|
|
393
|
+
case "add_table": {
|
|
394
|
+
const cols = op.table.columns.map(createTableColumn);
|
|
395
|
+
const createTable = `CREATE TABLE ${quoteIdent(op.table.name)} (
|
|
396
|
+
${cols.join(",\n ")}
|
|
397
|
+
)`;
|
|
398
|
+
return [createTable, ...createTableCanonicalIndexes(op.table)];
|
|
399
|
+
}
|
|
400
|
+
case "change_column_type":
|
|
401
|
+
case "change_column_nullable":
|
|
402
|
+
case "change_column_default":
|
|
403
|
+
throw new Error(
|
|
404
|
+
`emitPostgresDdl: op type "${op.type}" not yet implemented \u2014 canEmitWithoutDrizzleKit should not have routed it here`
|
|
405
|
+
);
|
|
406
|
+
default: {
|
|
407
|
+
const exhaustive = op;
|
|
408
|
+
throw new Error(
|
|
409
|
+
`emitPostgresDdl: unknown op ${JSON.stringify(exhaustive)}`
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// src/domains/schema/pipeline/ddl-emitter/index.ts
|
|
416
|
+
var FAST_PATH_OP_TYPES = /* @__PURE__ */ new Set([
|
|
417
|
+
"add_column",
|
|
418
|
+
"add_table"
|
|
419
|
+
]);
|
|
420
|
+
function canEmitWithoutDrizzleKit(ops, dialect) {
|
|
421
|
+
if (dialect !== "postgresql") return false;
|
|
422
|
+
if (ops.length === 0) return false;
|
|
423
|
+
return ops.every((op) => FAST_PATH_OP_TYPES.has(op.type));
|
|
424
|
+
}
|
|
425
|
+
function emitDdl(ops, dialect) {
|
|
426
|
+
if (dialect !== "postgresql") {
|
|
427
|
+
throw new Error(
|
|
428
|
+
`emitDdl: unsupported dialect "${dialect}" (fast path is PostgreSQL-only)`
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
return ops.flatMap((op) => emitPostgresDdl(op));
|
|
432
|
+
}
|
|
433
|
+
|
|
326
434
|
// src/domains/schema/pipeline/managed-tables.ts
|
|
327
435
|
var MANAGED_TABLE_PREFIXES_REGEX = /^(dc_|single_|comp_)/;
|
|
328
436
|
function isManagedTable(name) {
|
|
@@ -393,7 +501,7 @@ function isPreResolutionOp(op) {
|
|
|
393
501
|
}
|
|
394
502
|
|
|
395
503
|
// src/domains/schema/pipeline/sql-templates/identifier-quoting.ts
|
|
396
|
-
function
|
|
504
|
+
function quoteIdent2(name, dialect) {
|
|
397
505
|
const q4 = dialect === "mysql" ? "`" : '"';
|
|
398
506
|
if (name.includes(q4)) {
|
|
399
507
|
throw new Error(
|
|
@@ -404,7 +512,7 @@ function quoteIdent(name, dialect) {
|
|
|
404
512
|
}
|
|
405
513
|
|
|
406
514
|
// src/domains/schema/pipeline/sql-templates/mysql.ts
|
|
407
|
-
var q = (n) =>
|
|
515
|
+
var q = (n) => quoteIdent2(n, "mysql");
|
|
408
516
|
function columnDef(c) {
|
|
409
517
|
const nullable = c.nullable ? "" : " NOT NULL";
|
|
410
518
|
const def = c.default !== void 0 ? ` DEFAULT ${c.default}` : "";
|
|
@@ -480,7 +588,7 @@ var MysqlUnsupportedOperationError = class extends Error {
|
|
|
480
588
|
};
|
|
481
589
|
|
|
482
590
|
// src/domains/schema/pipeline/sql-templates/postgres.ts
|
|
483
|
-
var q2 = (n) =>
|
|
591
|
+
var q2 = (n) => quoteIdent2(n, "postgresql");
|
|
484
592
|
function columnDef2(c) {
|
|
485
593
|
const nullable = c.nullable ? "" : " NOT NULL";
|
|
486
594
|
const def = c.default !== void 0 ? ` DEFAULT ${c.default}` : "";
|
|
@@ -547,7 +655,7 @@ function generateChangeColumnDefault2(op) {
|
|
|
547
655
|
}
|
|
548
656
|
|
|
549
657
|
// src/domains/schema/pipeline/sql-templates/sqlite.ts
|
|
550
|
-
var q3 = (n) =>
|
|
658
|
+
var q3 = (n) => quoteIdent2(n, "sqlite");
|
|
551
659
|
function columnDef3(c) {
|
|
552
660
|
const nullable = c.nullable ? "" : " NOT NULL";
|
|
553
661
|
const def = c.default !== void 0 ? ` DEFAULT ${c.default}` : "";
|
|
@@ -777,6 +885,29 @@ var DdlExecutionError = class extends Error {
|
|
|
777
885
|
this.name = "DdlExecutionError";
|
|
778
886
|
}
|
|
779
887
|
};
|
|
888
|
+
var ORPHAN_DROP_PATTERNS = [
|
|
889
|
+
{
|
|
890
|
+
kind: "SEQUENCE",
|
|
891
|
+
re: /^DROP\s+SEQUENCE\s+(?:IF\s+EXISTS\s+)?(?:["`]?\w+["`]?\.)?["`]?(\w+)["`]?/i
|
|
892
|
+
},
|
|
893
|
+
{
|
|
894
|
+
kind: "INDEX",
|
|
895
|
+
re: /^DROP\s+INDEX\s+(?:IF\s+EXISTS\s+)?(?:["`]?\w+["`]?\.)?["`]?(\w+)["`]?/i
|
|
896
|
+
}
|
|
897
|
+
];
|
|
898
|
+
function logApplyRoute(useFastPath, ops) {
|
|
899
|
+
if (process.env.DEBUG_SCHEMA !== "1") return;
|
|
900
|
+
if (useFastPath) {
|
|
901
|
+
console.debug(
|
|
902
|
+
`[nextly] schema apply: fast-path DDL emitter (${ops.length} op(s))`
|
|
903
|
+
);
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
const nonAdditive = ops.filter((o) => o.type !== "add_column" && o.type !== "add_table").map((o) => o.type);
|
|
907
|
+
console.debug(
|
|
908
|
+
`[nextly] schema apply: drizzle-kit fallback (${ops.length} op(s); non-additive: ${nonAdditive.length === 0 ? "<none>" : nonAdditive.join(",")})`
|
|
909
|
+
);
|
|
910
|
+
}
|
|
780
911
|
function computeJournalSummaryFromOperations(operations) {
|
|
781
912
|
let added = 0;
|
|
782
913
|
let removed = 0;
|
|
@@ -864,11 +995,17 @@ var PushSchemaPipeline = class {
|
|
|
864
995
|
...Object.values(desired.singles).map((s) => s.tableName),
|
|
865
996
|
...Object.values(desired.components).map((c) => c.tableName)
|
|
866
997
|
];
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
998
|
+
let liveSnapshot;
|
|
999
|
+
if (this.testHooks._introspectSnapshotOverride) {
|
|
1000
|
+
liveSnapshot = await this.testHooks._introspectSnapshotOverride(
|
|
1001
|
+
db,
|
|
1002
|
+
dialect,
|
|
1003
|
+
managedTableNames
|
|
1004
|
+
);
|
|
1005
|
+
} else {
|
|
1006
|
+
const cached2 = getLiveSnapshot(managedTableNames);
|
|
1007
|
+
liveSnapshot = cached2 !== void 0 ? cached2 : await introspectLiveSnapshot(db, dialect, managedTableNames);
|
|
1008
|
+
}
|
|
872
1009
|
const desiredSnapshot = {
|
|
873
1010
|
tables: [
|
|
874
1011
|
...Object.values(desired.collections).map(
|
|
@@ -910,9 +1047,17 @@ var PushSchemaPipeline = class {
|
|
|
910
1047
|
countRows: (table) => countRows(db, dialect, table),
|
|
911
1048
|
dialect
|
|
912
1049
|
});
|
|
913
|
-
const
|
|
1050
|
+
const dropsCoveredByCandidates = /* @__PURE__ */ new Set();
|
|
1051
|
+
for (const c of candidates) {
|
|
1052
|
+
dropsCoveredByCandidates.add(`${c.tableName}::${c.fromColumn}`);
|
|
1053
|
+
}
|
|
1054
|
+
const dispatchEvents = classificationResult.events.filter(
|
|
1055
|
+
(e) => e.kind !== "destructive_drop" || !dropsCoveredByCandidates.has(`${e.tableName}::${e.columnName}`)
|
|
1056
|
+
);
|
|
1057
|
+
const needsPrompt = candidates.length > 0 || dispatchEvents.length > 0;
|
|
1058
|
+
const dispatchResult = needsPrompt ? await this.deps.promptDispatcher.dispatch({
|
|
914
1059
|
candidates,
|
|
915
|
-
events:
|
|
1060
|
+
events: dispatchEvents,
|
|
916
1061
|
classification: classificationResult.level,
|
|
917
1062
|
channel: promptChannel
|
|
918
1063
|
}) : {
|
|
@@ -928,11 +1073,43 @@ var PushSchemaPipeline = class {
|
|
|
928
1073
|
dispatchResult.resolutions,
|
|
929
1074
|
classificationResult.events
|
|
930
1075
|
);
|
|
931
|
-
const resolvedOps = applyResolutionsToOperations(
|
|
1076
|
+
const resolvedOps = this.testHooks._resolvedOpsOverride ?? applyResolutionsToOperations(
|
|
932
1077
|
operations,
|
|
933
1078
|
toRenameResolutions(dispatchResult.confirmedRenames, candidates)
|
|
934
1079
|
);
|
|
935
1080
|
const drizzleSchema = this.testHooks._buildDrizzleSchemaOverride ? this.testHooks._buildDrizzleSchemaOverride(patchedDesired, dialect) : this.buildDrizzleSchema(patchedDesired, dialect);
|
|
1081
|
+
const affectedTableNames = /* @__PURE__ */ new Set();
|
|
1082
|
+
for (const op of resolvedOps) {
|
|
1083
|
+
switch (op.type) {
|
|
1084
|
+
case "add_table":
|
|
1085
|
+
affectedTableNames.add(op.table.name);
|
|
1086
|
+
break;
|
|
1087
|
+
case "rename_table":
|
|
1088
|
+
affectedTableNames.add(op.toName);
|
|
1089
|
+
break;
|
|
1090
|
+
case "drop_table":
|
|
1091
|
+
break;
|
|
1092
|
+
case "add_column":
|
|
1093
|
+
case "drop_column":
|
|
1094
|
+
case "rename_column":
|
|
1095
|
+
case "change_column_type":
|
|
1096
|
+
case "change_column_nullable":
|
|
1097
|
+
case "change_column_default":
|
|
1098
|
+
affectedTableNames.add(op.tableName);
|
|
1099
|
+
break;
|
|
1100
|
+
default: {
|
|
1101
|
+
const _exhaustive = op;
|
|
1102
|
+
void _exhaustive;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
const scopedSchema = {};
|
|
1107
|
+
for (const [tableName, tableObj] of Object.entries(drizzleSchema)) {
|
|
1108
|
+
if (affectedTableNames.has(tableName)) {
|
|
1109
|
+
scopedSchema[tableName] = tableObj;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
const effectiveDrizzleSchema = Object.keys(scopedSchema).length > 0 ? scopedSchema : drizzleSchema;
|
|
936
1113
|
const kit = this.testHooks._kitOverride ? this.testHooks._kitOverride : await this.importDrizzleKit(dialect, databaseName);
|
|
937
1114
|
const isSqlite = dialect === "sqlite";
|
|
938
1115
|
const runApply = async (tx) => {
|
|
@@ -970,22 +1147,30 @@ var PushSchemaPipeline = class {
|
|
|
970
1147
|
err
|
|
971
1148
|
);
|
|
972
1149
|
}
|
|
973
|
-
const desiredTableNames = Object.keys(
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1150
|
+
const desiredTableNames = Object.keys(effectiveDrizzleSchema);
|
|
1151
|
+
const useFastPath = canEmitWithoutDrizzleKit(resolvedOps, dialect);
|
|
1152
|
+
logApplyRoute(useFastPath, resolvedOps);
|
|
1153
|
+
let emittedStatements;
|
|
1154
|
+
if (useFastPath) {
|
|
1155
|
+
emittedStatements = emitDdl(resolvedOps, dialect);
|
|
1156
|
+
} else {
|
|
1157
|
+
let pushResult;
|
|
1158
|
+
try {
|
|
1159
|
+
pushResult = await withCapturedStdout(
|
|
1160
|
+
() => kit.pushSchema(effectiveDrizzleSchema, tx, desiredTableNames),
|
|
1161
|
+
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
1162
|
+
process.env.DEBUG_SCHEMA === "1" ? { debug: (msg) => console.debug(msg) } : void 0
|
|
1163
|
+
);
|
|
1164
|
+
} catch (err) {
|
|
1165
|
+
throw new PushSchemaError(
|
|
1166
|
+
err instanceof Error ? err.message : String(err),
|
|
1167
|
+
err
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
emittedStatements = pushResult.statementsToExecute;
|
|
986
1171
|
}
|
|
987
1172
|
const safe = this.filterUnsafeStatements(
|
|
988
|
-
|
|
1173
|
+
emittedStatements,
|
|
989
1174
|
desiredTableNames
|
|
990
1175
|
);
|
|
991
1176
|
try {
|
|
@@ -1066,25 +1251,67 @@ var PushSchemaPipeline = class {
|
|
|
1066
1251
|
}
|
|
1067
1252
|
}
|
|
1068
1253
|
filterUnsafeStatements(statements, desiredTableNames) {
|
|
1069
|
-
const desiredSet = new Set(
|
|
1070
|
-
desiredTableNames.map((t) => t.toLowerCase())
|
|
1071
|
-
);
|
|
1254
|
+
const desiredSet = new Set(desiredTableNames.map((t) => t.toLowerCase()));
|
|
1072
1255
|
return statements.filter((stmt) => {
|
|
1073
1256
|
const dropMatch = stmt.match(
|
|
1074
1257
|
/^DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?(?:["`]?\w+["`]?\.)?["`]?(\w+)["`]?/i
|
|
1075
1258
|
);
|
|
1076
|
-
if (
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1259
|
+
if (dropMatch) {
|
|
1260
|
+
const tableName = dropMatch[1] ?? "<unknown>";
|
|
1261
|
+
const isInDesired = desiredSet.has(tableName.toLowerCase());
|
|
1262
|
+
if (isInDesired) {
|
|
1263
|
+
return true;
|
|
1264
|
+
}
|
|
1265
|
+
console.warn(
|
|
1266
|
+
`[Nextly schema] Blocked DROP TABLE "${tableName}" emitted by drizzle-kit pushSchema (table not in current desired schema). If this drop was intentional, route it through the pre-resolution executor with explicit user confirmation. (managed=${isManagedTable(tableName)})`
|
|
1267
|
+
);
|
|
1268
|
+
return false;
|
|
1081
1269
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1270
|
+
for (const { kind, re } of ORPHAN_DROP_PATTERNS) {
|
|
1271
|
+
const m = stmt.match(re);
|
|
1272
|
+
if (!m) continue;
|
|
1273
|
+
const objectName = m[1] ?? "";
|
|
1274
|
+
if (this.inferOwnerTableFromObjectName(objectName, desiredSet) !== null) {
|
|
1275
|
+
return true;
|
|
1276
|
+
}
|
|
1277
|
+
console.warn(
|
|
1278
|
+
`[Nextly schema] Blocked DROP ${kind} "${objectName}" emitted by drizzle-kit pushSchema (owner table not in current desired schema or name is non-conventional). If this drop was intentional, route it through the pre-resolution executor with explicit user confirmation, or drop it manually before re-running if the ${kind.toLowerCase()} name is custom.`
|
|
1279
|
+
);
|
|
1280
|
+
return false;
|
|
1281
|
+
}
|
|
1282
|
+
return true;
|
|
1086
1283
|
});
|
|
1087
1284
|
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Infers the owner table of a sequence or index from its name using
|
|
1287
|
+
* Postgres's default naming conventions:
|
|
1288
|
+
* - SERIAL / IDENTITY sequences: `<table>_<col>_seq`
|
|
1289
|
+
* - Indexes: `<table>_<col(s)>_idx | _key | _pkey | _unique`
|
|
1290
|
+
*
|
|
1291
|
+
* Strategy: walk underscore-delimited prefixes from longest to shortest
|
|
1292
|
+
* and return the first candidate found in `desiredSet`. Longest-first
|
|
1293
|
+
* ensures that multi-word table names like `email_templates` are
|
|
1294
|
+
* preferred over the shorter prefix `email`.
|
|
1295
|
+
*
|
|
1296
|
+
* Examples:
|
|
1297
|
+
* accounts_id_seq → "accounts" (if in desiredSet)
|
|
1298
|
+
* email_templates_id_seq → "email_templates" (if in desiredSet)
|
|
1299
|
+
* dc_posts_title_idx → "dc_posts" (if in desiredSet)
|
|
1300
|
+
* idx_completely_custom → null (no prefix matches)
|
|
1301
|
+
*
|
|
1302
|
+
* Returns the matched table name (lowercased) or `null` if no prefix
|
|
1303
|
+
* in `desiredSet` was found. A `null` result means we can't identify
|
|
1304
|
+
* the owner, and the caller should treat the statement as unsafe.
|
|
1305
|
+
*/
|
|
1306
|
+
inferOwnerTableFromObjectName(objectName, desiredSet) {
|
|
1307
|
+
const lower = objectName.toLowerCase();
|
|
1308
|
+
const parts = lower.split("_");
|
|
1309
|
+
for (let i = parts.length - 1; i > 0; i--) {
|
|
1310
|
+
const candidate = parts.slice(0, i).join("_");
|
|
1311
|
+
if (desiredSet.has(candidate)) return candidate;
|
|
1312
|
+
}
|
|
1313
|
+
return null;
|
|
1314
|
+
}
|
|
1088
1315
|
async runSqlitePragma(db, pragma) {
|
|
1089
1316
|
const { sql: sqlTag } = await import("drizzle-orm");
|
|
1090
1317
|
const dbTyped = db;
|
|
@@ -1455,6 +1682,8 @@ export {
|
|
|
1455
1682
|
TTYRequiredError,
|
|
1456
1683
|
PromptCancelledError,
|
|
1457
1684
|
RealPreCleanupExecutor,
|
|
1685
|
+
setLiveSnapshot,
|
|
1686
|
+
clearLiveSnapshots,
|
|
1458
1687
|
generateSQL,
|
|
1459
1688
|
PushSchemaPipeline,
|
|
1460
1689
|
noopPreRenameExecutor,
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
hasAnyPermission,
|
|
9
9
|
hasPermission
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-L7BXB5H3.mjs";
|
|
11
11
|
import {
|
|
12
12
|
env
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-HREB7UR4.mjs";
|
|
14
14
|
import {
|
|
15
15
|
container
|
|
16
16
|
} from "./chunk-D5HQBNUB.mjs";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
routeAuthRequest
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-INTLFB63.mjs";
|
|
4
4
|
import {
|
|
5
5
|
POST
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TGBLNY5L.mjs";
|
|
7
7
|
import {
|
|
8
8
|
readJsonBody
|
|
9
9
|
} from "./chunk-VQJQHVEV.mjs";
|
|
10
10
|
import {
|
|
11
11
|
POST as POST2
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-RQ3N4DIB.mjs";
|
|
13
13
|
import {
|
|
14
14
|
createJsonErrorResponse,
|
|
15
15
|
isErrorResponse,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
requireCollectionAccess,
|
|
19
19
|
requirePermission,
|
|
20
20
|
toNextlyAuthError
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-V5DUKEYT.mjs";
|
|
22
22
|
import {
|
|
23
23
|
nextlyValidationFromZod
|
|
24
24
|
} from "./chunk-GJNSJU4S.mjs";
|
|
@@ -45,12 +45,12 @@ import {
|
|
|
45
45
|
import {
|
|
46
46
|
ensureHmrListener,
|
|
47
47
|
getCachedNextly
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-ZDNGCKSZ.mjs";
|
|
49
49
|
import {
|
|
50
50
|
getService,
|
|
51
51
|
isServicesRegistered,
|
|
52
52
|
registerServices
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-DQGQMP5F.mjs";
|
|
54
54
|
import {
|
|
55
55
|
readOrGenerateRequestId
|
|
56
56
|
} from "./chunk-67GXH6PR.mjs";
|
|
@@ -61,20 +61,20 @@ import {
|
|
|
61
61
|
ImageSizeService,
|
|
62
62
|
ServiceDispatcher,
|
|
63
63
|
parseWhereQuery
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-ILETUFUD.mjs";
|
|
65
65
|
import {
|
|
66
66
|
containsSuperAdminRole,
|
|
67
67
|
hasSuperAdminExcluding,
|
|
68
68
|
isSuperAdmin,
|
|
69
69
|
listEffectivePermissions
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-L7BXB5H3.mjs";
|
|
71
71
|
import {
|
|
72
72
|
BaseService,
|
|
73
73
|
withTimezoneFormatting
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-ERTNRSP3.mjs";
|
|
75
75
|
import {
|
|
76
76
|
getDialectTables
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-A7GGVOIV.mjs";
|
|
78
78
|
import {
|
|
79
79
|
nextlyMigrationJournalMysql,
|
|
80
80
|
nextlyMigrationJournalPg,
|
|
@@ -82,7 +82,7 @@ import {
|
|
|
82
82
|
} from "./chunk-H26B4FYG.mjs";
|
|
83
83
|
import {
|
|
84
84
|
env
|
|
85
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-HREB7UR4.mjs";
|
|
86
86
|
import {
|
|
87
87
|
getImageProcessor,
|
|
88
88
|
getMediaStorage
|
|
@@ -2154,8 +2154,8 @@ function buildAuthRouterDeps(getService2) {
|
|
|
2154
2154
|
}
|
|
2155
2155
|
},
|
|
2156
2156
|
createSuperAdmin: async (data) => {
|
|
2157
|
-
const { seedPermissions } = await import("./permissions-
|
|
2158
|
-
const { seedSuperAdmin } = await import("./super-admin-
|
|
2157
|
+
const { seedPermissions } = await import("./permissions-KH3WCGAR.mjs");
|
|
2158
|
+
const { seedSuperAdmin } = await import("./super-admin-XZAU4VQM.mjs");
|
|
2159
2159
|
const adapter = getService2("adapter");
|
|
2160
2160
|
await seedPermissions(adapter, { silent: true });
|
|
2161
2161
|
const result = await seedSuperAdmin(adapter, {
|
|
@@ -2180,7 +2180,7 @@ function buildAuthRouterDeps(getService2) {
|
|
|
2180
2180
|
};
|
|
2181
2181
|
},
|
|
2182
2182
|
seedPermissions: async () => {
|
|
2183
|
-
const { seedPermissions } = await import("./permissions-
|
|
2183
|
+
const { seedPermissions } = await import("./permissions-KH3WCGAR.mjs");
|
|
2184
2184
|
const adapter = getService2("adapter");
|
|
2185
2185
|
await seedPermissions(adapter, { silent: true });
|
|
2186
2186
|
},
|
|
@@ -2336,10 +2336,8 @@ async function ensureServicesInitialized() {
|
|
|
2336
2336
|
if (nextlyConfig.users) serviceConfig.users = nextlyConfig.users;
|
|
2337
2337
|
if (nextlyConfig.admin) serviceConfig.admin = nextlyConfig.admin;
|
|
2338
2338
|
if (nextlyConfig.auth) serviceConfig.auth = nextlyConfig.auth;
|
|
2339
|
-
if (nextlyConfig.security)
|
|
2340
|
-
|
|
2341
|
-
if (nextlyConfig.apiKeys)
|
|
2342
|
-
serviceConfig.apiKeys = nextlyConfig.apiKeys;
|
|
2339
|
+
if (nextlyConfig.security) serviceConfig.security = nextlyConfig.security;
|
|
2340
|
+
if (nextlyConfig.apiKeys) serviceConfig.apiKeys = nextlyConfig.apiKeys;
|
|
2343
2341
|
if (nextlyConfig.db) {
|
|
2344
2342
|
const dbConfig = nextlyConfig.db;
|
|
2345
2343
|
if (dbConfig.schemasDir) serviceConfig.schemasDir = dbConfig.schemasDir;
|
|
@@ -2347,6 +2345,12 @@ async function ensureServicesInitialized() {
|
|
|
2347
2345
|
serviceConfig.migrationsDir = dbConfig.migrationsDir;
|
|
2348
2346
|
}
|
|
2349
2347
|
}
|
|
2348
|
+
if (process.env.NODE_ENV === "development" && // eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
2349
|
+
process.env.NEXTLY_DISABLE_INSTRUMENTATION_WARNING !== "1") {
|
|
2350
|
+
console.warn(
|
|
2351
|
+
"[nextly] Cold-boot triggered by an incoming request \u2014 no instrumentation.ts detected. Each Next.js worker will now independently run schema introspection and permission seeding against your database, multiplying connection load. Add an `instrumentation.ts` at your project root (see https://nextly.dev/docs/getting-started/instrumentation) to fold this into a single worker-warmup. Suppress with NEXTLY_DISABLE_INSTRUMENTATION_WARNING=1."
|
|
2352
|
+
);
|
|
2353
|
+
}
|
|
2350
2354
|
await registerServices(serviceConfig);
|
|
2351
2355
|
try {
|
|
2352
2356
|
const emailTemplateService = getService("emailTemplateService");
|
|
@@ -2392,7 +2396,7 @@ async function ensureServicesInitialized() {
|
|
|
2392
2396
|
} else {
|
|
2393
2397
|
console.log("[Auth Handler] Services auto-initialized with defaults");
|
|
2394
2398
|
}
|
|
2395
|
-
const { runBootTimeApplyIfDev } = await import("./boot-apply-
|
|
2399
|
+
const { runBootTimeApplyIfDev } = await import("./boot-apply-OE3D3KNU.mjs");
|
|
2396
2400
|
await runBootTimeApplyIfDev({ caller: "auth-handler" });
|
|
2397
2401
|
ensureHmrListener();
|
|
2398
2402
|
}
|