nextly 0.0.1 → 0.0.2-alpha.0
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/LICENSE +22 -0
- package/README.md +122 -0
- package/dist/_dts-chunks/collections-handler.d-DjgO74Wt.d.ts +20540 -0
- package/dist/_dts-chunks/config.d-DNwsDnjs.d.ts +2589 -0
- package/dist/_dts-chunks/define-component.d-BUgTHmt3.d.ts +1149 -0
- package/dist/_dts-chunks/image-processor.d-OO1PmMrv.d.ts +335 -0
- package/dist/_dts-chunks/index.d-axCAzZ7m.d.ts +17842 -0
- package/dist/_dts-chunks/media.d-DjDOZo4B.d.ts +117 -0
- package/dist/_dts-chunks/on-error.d-CHIKWNxd.d.ts +38 -0
- package/dist/_dts-chunks/storage.d-BUhQ2we_.d.ts +404 -0
- package/dist/actions/index.d.ts +239 -0
- package/dist/actions/index.mjs +281 -0
- package/dist/api/auth-state.d.ts +5 -0
- package/dist/api/auth-state.mjs +131 -0
- package/dist/api/collections-schema-detail.d.ts +56 -0
- package/dist/api/collections-schema-detail.mjs +244 -0
- package/dist/api/collections-schema-export.d.ts +56 -0
- package/dist/api/collections-schema-export.mjs +129 -0
- package/dist/api/collections-schema.d.ts +59 -0
- package/dist/api/collections-schema.mjs +207 -0
- package/dist/api/components-detail.d.ts +50 -0
- package/dist/api/components-detail.mjs +132 -0
- package/dist/api/components.d.ts +69 -0
- package/dist/api/components.mjs +144 -0
- package/dist/api/email-providers-default.d.ts +40 -0
- package/dist/api/email-providers-default.mjs +75 -0
- package/dist/api/email-providers-detail.d.ts +81 -0
- package/dist/api/email-providers-detail.mjs +109 -0
- package/dist/api/email-providers-test.d.ts +43 -0
- package/dist/api/email-providers-test.mjs +114 -0
- package/dist/api/email-providers.d.ts +69 -0
- package/dist/api/email-providers.mjs +110 -0
- package/dist/api/email-send-template.d.ts +41 -0
- package/dist/api/email-send-template.mjs +58 -0
- package/dist/api/email-send.d.ts +42 -0
- package/dist/api/email-send.mjs +58 -0
- package/dist/api/email-templates-detail.d.ts +74 -0
- package/dist/api/email-templates-detail.mjs +112 -0
- package/dist/api/email-templates-layout.d.ts +55 -0
- package/dist/api/email-templates-layout.mjs +92 -0
- package/dist/api/email-templates-preview.d.ts +48 -0
- package/dist/api/email-templates-preview.mjs +93 -0
- package/dist/api/email-templates.d.ts +61 -0
- package/dist/api/email-templates.mjs +118 -0
- package/dist/api/health.d.ts +68 -0
- package/dist/api/health.mjs +67 -0
- package/dist/api/index.d.ts +54 -0
- package/dist/api/index.mjs +16 -0
- package/dist/api/media-bulk.d.ts +74 -0
- package/dist/api/media-bulk.mjs +196 -0
- package/dist/api/media-folders.d.ts +112 -0
- package/dist/api/media-folders.mjs +187 -0
- package/dist/api/media-handlers.d.ts +102 -0
- package/dist/api/media-handlers.mjs +437 -0
- package/dist/api/media.d.ts +117 -0
- package/dist/api/media.mjs +242 -0
- package/dist/api/singles-detail.d.ts +87 -0
- package/dist/api/singles-detail.mjs +170 -0
- package/dist/api/singles-schema-detail.d.ts +54 -0
- package/dist/api/singles-schema-detail.mjs +182 -0
- package/dist/api/singles.d.ts +34 -0
- package/dist/api/singles.mjs +94 -0
- package/dist/api/storage-upload-url.d.ts +48 -0
- package/dist/api/storage-upload-url.mjs +202 -0
- package/dist/api/uploads.d.ts +109 -0
- package/dist/api/uploads.mjs +359 -0
- package/dist/auth/index.d.ts +425 -0
- package/dist/auth/index.mjs +199 -0
- package/dist/boot-apply-PQSYLDIN.mjs +7 -0
- package/dist/chunk-2OALJTK6.mjs +489 -0
- package/dist/chunk-2Q2SX2CS.mjs +365 -0
- package/dist/chunk-2TFX4ND3.mjs +13 -0
- package/dist/chunk-2TWPDSYD.mjs +87 -0
- package/dist/chunk-2W3DVD7S.mjs +647 -0
- package/dist/chunk-2ZFKXPQM.mjs +88 -0
- package/dist/chunk-3FA7FKAV.mjs +832 -0
- package/dist/chunk-3NZ2KMBL.mjs +58 -0
- package/dist/chunk-4MJLT6PZ.mjs +0 -0
- package/dist/chunk-56WO4WX7.mjs +0 -0
- package/dist/chunk-5APFUGAD.mjs +89 -0
- package/dist/chunk-5HMZ644B.mjs +108 -0
- package/dist/chunk-67GXH6PR.mjs +32 -0
- package/dist/chunk-6JNEPWRW.mjs +14368 -0
- package/dist/chunk-6NFHQIJD.mjs +45 -0
- package/dist/chunk-7P6ASYW6.mjs +9 -0
- package/dist/chunk-A3WPLSDT.mjs +1364 -0
- package/dist/chunk-AGJ6F2T3.mjs +144 -0
- package/dist/chunk-AK6Z23OX.mjs +1464 -0
- package/dist/chunk-APKKRD2G.mjs +102 -0
- package/dist/chunk-B2GV2BWH.mjs +73 -0
- package/dist/chunk-D5HQBNUB.mjs +74 -0
- package/dist/chunk-DNNG377Z.mjs +204 -0
- package/dist/chunk-DP3G27G5.mjs +135 -0
- package/dist/chunk-DV6WVX2Q.mjs +0 -0
- package/dist/chunk-DXGGXIUZ.mjs +57 -0
- package/dist/chunk-EGXBZCGC.mjs +943 -0
- package/dist/chunk-ERCNLX3V.mjs +176 -0
- package/dist/chunk-FQULBZ53.mjs +850 -0
- package/dist/chunk-G2AA4QLC.mjs +262 -0
- package/dist/chunk-GDBJ5JCU.mjs +488 -0
- package/dist/chunk-GJNSJU4S.mjs +19 -0
- package/dist/chunk-GZ6DCQKC.mjs +69 -0
- package/dist/chunk-H26B4FYG.mjs +167 -0
- package/dist/chunk-I4JMR3UR.mjs +21 -0
- package/dist/chunk-INV7QKLG.mjs +508 -0
- package/dist/chunk-IUDOC7N7.mjs +46 -0
- package/dist/chunk-IZWPRDC3.mjs +206 -0
- package/dist/chunk-KIMNCZGV.mjs +15 -0
- package/dist/chunk-L6HW2DA7.mjs +15 -0
- package/dist/chunk-LAZXX4HR.mjs +100 -0
- package/dist/chunk-LDKCUMHK.mjs +95 -0
- package/dist/chunk-LRXMECUA.mjs +0 -0
- package/dist/chunk-M52VMPGA.mjs +119 -0
- package/dist/chunk-MGUWEEI6.mjs +160 -0
- package/dist/chunk-NRUWQ5Z7.mjs +419 -0
- package/dist/chunk-NSEFNNU4.mjs +25360 -0
- package/dist/chunk-NTHVDFGO.mjs +138 -0
- package/dist/chunk-O3QHXMOX.mjs +3166 -0
- package/dist/chunk-P7NH2OSC.mjs +2605 -0
- package/dist/chunk-PKMABBB5.mjs +184 -0
- package/dist/chunk-PWS6XGJK.mjs +76 -0
- package/dist/chunk-R6JJQHFC.mjs +20 -0
- package/dist/chunk-RJLLGGPG.mjs +0 -0
- package/dist/chunk-SBACDPNX.mjs +689 -0
- package/dist/chunk-TO5AFLVQ.mjs +124 -0
- package/dist/chunk-TS7GHTG2.mjs +5436 -0
- package/dist/chunk-UJ2IMJ4W.mjs +133 -0
- package/dist/chunk-UOP63Q54.mjs +102 -0
- package/dist/chunk-UUOFWCM6.mjs +78 -0
- package/dist/chunk-V4EQTOA4.mjs +893 -0
- package/dist/chunk-VJ66NCL4.mjs +193 -0
- package/dist/chunk-VQJQHVEV.mjs +29 -0
- package/dist/chunk-VTJADRO3.mjs +141 -0
- package/dist/chunk-VWF3JO32.mjs +0 -0
- package/dist/chunk-W4MGXIRR.mjs +27 -0
- package/dist/chunk-W5KKPZT5.mjs +1204 -0
- package/dist/chunk-WD34YQ6T.mjs +381 -0
- package/dist/chunk-WZBYMYVW.mjs +14 -0
- package/dist/chunk-X23WKS3Z.mjs +50 -0
- package/dist/chunk-X7TXCYYN.mjs +6496 -0
- package/dist/chunk-XGI4EMS3.mjs +140 -0
- package/dist/chunk-XZKLBMN6.mjs +1153 -0
- package/dist/chunk-YB7INWPY.mjs +0 -0
- package/dist/chunk-YV4Y7SDL.mjs +83 -0
- package/dist/chunk-YZNBLFIW.mjs +1688 -0
- package/dist/chunk-YZZCTONM.mjs +263 -0
- package/dist/chunk-ZE6A3FYH.mjs +289 -0
- package/dist/cli/nextly.mjs +68 -0
- package/dist/cli/utils/index.d.ts +449 -0
- package/dist/cli/utils/index.mjs +49 -0
- package/dist/component-schema-service-5577KVW6.mjs +11 -0
- package/dist/config-loader-23YEMC3Z.mjs +23 -0
- package/dist/config.d.ts +44 -0
- package/dist/config.mjs +109 -0
- package/dist/container-ORGFGYSZ.mjs +9 -0
- package/dist/database/index.d.ts +12 -0
- package/dist/database/index.mjs +40 -0
- package/dist/database/seeders/index.d.ts +93 -0
- package/dist/database/seeders/index.mjs +47 -0
- package/dist/db-sync-demote-LJGKLB3S.mjs +117 -0
- package/dist/db-sync-promote-B26VSYQF.mjs +113 -0
- package/dist/dev-reload-broadcaster-B73IQ53V.mjs +25 -0
- package/dist/dist-M2NOU37V.mjs +19 -0
- package/dist/drizzle-kit-lazy-D2M2PXR2.mjs +13 -0
- package/dist/dynamic-collection-schema-service-IEXTPIZ7.mjs +8 -0
- package/dist/errors/index.d.ts +159 -0
- package/dist/errors/index.mjs +10 -0
- package/dist/factory-IWMBKUJM.mjs +15 -0
- package/dist/first-run-QIVKWJIF.mjs +63 -0
- package/dist/fresh-push-NR67DC3R.mjs +8 -0
- package/dist/index.d.ts +4175 -0
- package/dist/index.mjs +1336 -0
- package/dist/local-plugin-PTET4NAT.mjs +7 -0
- package/dist/logger-NU46DXNY.mjs +15 -0
- package/dist/logger-YE4TC7ZN.mjs +9 -0
- package/dist/migration-journal-EP532Y4L.mjs +139 -0
- package/dist/migrations/mysql/0000_eager_sentry.sql +174 -0
- package/dist/migrations/mysql/0001_soft_giant_girl.sql +27 -0
- package/dist/migrations/mysql/0002_media_table.sql +24 -0
- package/dist/migrations/mysql/0003_dynamic_singles.sql +37 -0
- package/dist/migrations/mysql/0004_dynamic_components.sql +35 -0
- package/dist/migrations/mysql/0005_user_management_tables.sql +92 -0
- package/dist/migrations/mysql/0006_api_keys.sql +36 -0
- package/dist/migrations/mysql/0007_general_settings.sql +20 -0
- package/dist/migrations/mysql/0008_site_settings_logo_url.sql +9 -0
- package/dist/migrations/mysql/0009_activity_log.sql +30 -0
- package/dist/migrations/mysql/0010_site_settings_sidebar.sql +13 -0
- package/dist/migrations/mysql/0011_missing_tables_and_columns.sql +54 -0
- package/dist/migrations/mysql/0012_image_sizes_and_focal_point.sql +30 -0
- package/dist/migrations/mysql/0012_media_folders.sql +43 -0
- package/dist/migrations/mysql/0013_user_brute_force_protection.sql +31 -0
- package/dist/migrations/mysql/0014_email_template_attachments.sql +12 -0
- package/dist/migrations/mysql/0015_media_uploaded_by_nullable.sql +15 -0
- package/dist/migrations/mysql/20260429_000000_000_initial_journal.sql +22 -0
- package/dist/migrations/mysql/20260501_000000_journal_batch.sql +17 -0
- package/dist/migrations/mysql/20260501_000001_audit_log.sql +24 -0
- package/dist/migrations/mysql/20260504_000000_nextly_meta.sql +21 -0
- package/dist/migrations/mysql/meta/0000_snapshot.json +1005 -0
- package/dist/migrations/mysql/meta/0001_snapshot.json +1099 -0
- package/dist/migrations/mysql/meta/_journal.json +41 -0
- package/dist/migrations/postgresql/0000_misty_king_bedlam.sql +169 -0
- package/dist/migrations/postgresql/0001_perpetual_captain_marvel.sql +8 -0
- package/dist/migrations/postgresql/0002_sad_spectrum.sql +16 -0
- package/dist/migrations/postgresql/0003_hesitant_ultron.sql +17 -0
- package/dist/migrations/postgresql/0004_media_table.sql +24 -0
- package/dist/migrations/postgresql/0005_media_folders.sql +36 -0
- package/dist/migrations/postgresql/0006_dynamic_collections_update.sql +50 -0
- package/dist/migrations/postgresql/0007_dynamic_singles.sql +38 -0
- package/dist/migrations/postgresql/0008_dynamic_components.sql +37 -0
- package/dist/migrations/postgresql/0009_user_management_tables.sql +95 -0
- package/dist/migrations/postgresql/0010_api_keys.sql +34 -0
- package/dist/migrations/postgresql/0011_general_settings.sql +20 -0
- package/dist/migrations/postgresql/0012_site_settings_logo_url.sql +9 -0
- package/dist/migrations/postgresql/0013_activity_log.sql +29 -0
- package/dist/migrations/postgresql/0014_image_sizes_and_focal_point.sql +33 -0
- package/dist/migrations/postgresql/0014_site_settings_sidebar.sql +13 -0
- package/dist/migrations/postgresql/0015_user_brute_force_protection.sql +29 -0
- package/dist/migrations/postgresql/0016_email_template_attachments.sql +12 -0
- package/dist/migrations/postgresql/0017_media_uploaded_by_nullable.sql +15 -0
- package/dist/migrations/postgresql/20260429_000000_000_initial_journal.sql +24 -0
- package/dist/migrations/postgresql/20260501_000000_journal_batch.sql +17 -0
- package/dist/migrations/postgresql/20260501_000001_audit_log.sql +24 -0
- package/dist/migrations/postgresql/20260504_000000_nextly_meta.sql +22 -0
- package/dist/migrations/postgresql/meta/0000_snapshot.json +1286 -0
- package/dist/migrations/postgresql/meta/0001_snapshot.json +1407 -0
- package/dist/migrations/postgresql/meta/0002_snapshot.json +1552 -0
- package/dist/migrations/postgresql/meta/0003_snapshot.json +1695 -0
- package/dist/migrations/postgresql/meta/0010_snapshot.json +2345 -0
- package/dist/migrations/postgresql/meta/_journal.json +90 -0
- package/dist/migrations/sqlite/0000_api_keys.sql +34 -0
- package/dist/migrations/sqlite/0001_general_settings.sql +20 -0
- package/dist/migrations/sqlite/0002_site_settings_logo_url.sql +9 -0
- package/dist/migrations/sqlite/0003_activity_log.sql +29 -0
- package/dist/migrations/sqlite/0004_image_sizes_and_focal_point.sql +29 -0
- package/dist/migrations/sqlite/0004_site_settings_sidebar.sql +11 -0
- package/dist/migrations/sqlite/0005_user_brute_force_protection.sql +29 -0
- package/dist/migrations/sqlite/0006_email_template_attachments.sql +12 -0
- package/dist/migrations/sqlite/0007_media_uploaded_by_nullable.sql +111 -0
- package/dist/migrations/sqlite/20260429_000000_000_initial_journal.sql +24 -0
- package/dist/migrations/sqlite/20260501_000000_journal_batch.sql +19 -0
- package/dist/migrations/sqlite/20260501_000001_audit_log.sql +24 -0
- package/dist/migrations/sqlite/20260504_000000_nextly_meta.sql +21 -0
- package/dist/migrations/sqlite/20260505_000000_user_management_tables.sql +77 -0
- package/dist/next.d.ts +57 -0
- package/dist/next.mjs +55 -0
- package/dist/observability/index.d.ts +87 -0
- package/dist/observability/index.mjs +57 -0
- package/dist/permissions-3DZZQZMI.mjs +39 -0
- package/dist/pipeline-YOML7SWF.mjs +29 -0
- package/dist/preview-ZZTR3QGS.mjs +9 -0
- package/dist/program-PW6UB2ZC.mjs +5934 -0
- package/dist/reconcile-single-tables-7ENVXJGB.mjs +7 -0
- package/dist/register-SF6E6FVU.mjs +49 -0
- package/dist/reload-config-HWQ4G5MM.mjs +23 -0
- package/dist/resolve-single-table-name-JSOMUB3R.mjs +7 -0
- package/dist/routeHandler-UNMMJIBM.mjs +77 -0
- package/dist/runtime-schema-generator-NRA6A6Z6.mjs +8 -0
- package/dist/runtime.d.ts +120 -0
- package/dist/runtime.mjs +73 -0
- package/dist/schema-hash-FMMG6VPJ.mjs +13 -0
- package/dist/schema-registry-EQ36FZDP.mjs +7 -0
- package/dist/scripts/load-env.mjs +42 -0
- package/dist/storage/index.d.ts +566 -0
- package/dist/storage/index.mjs +45 -0
- package/dist/super-admin-G5ZK5F4T.mjs +39 -0
- package/dist/system-table-service-WGSRVEGT.mjs +17 -0
- package/dist/users-7KELGRYJ.mjs +38 -0
- package/package.json +308 -9
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PromptCancelledError,
|
|
3
|
+
TTYRequiredError
|
|
4
|
+
} from "./chunk-AK6Z23OX.mjs";
|
|
5
|
+
|
|
6
|
+
// src/domains/schema/pipeline/prompt-dispatcher/clack-terminal.ts
|
|
7
|
+
import * as clack from "@clack/prompts";
|
|
8
|
+
function hasTTY() {
|
|
9
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
10
|
+
}
|
|
11
|
+
var ClackTerminalPromptDispatcher = class {
|
|
12
|
+
async dispatch(args) {
|
|
13
|
+
const { candidates, events } = args;
|
|
14
|
+
if (candidates.length === 0 && events.length === 0) {
|
|
15
|
+
return { confirmedRenames: [], resolutions: [], proceed: true };
|
|
16
|
+
}
|
|
17
|
+
if (!hasTTY()) {
|
|
18
|
+
const renameSample = candidates.slice(0, 3).map((c) => `${c.fromColumn} -> ${c.toColumn} on ${c.tableName}`).join(", ");
|
|
19
|
+
const eventSample = events.slice(0, 3).map(
|
|
20
|
+
(e) => e.kind === "type_change" ? `type change on ${e.tableName}.${e.columnName} (${e.fromType} -> ${e.toType})` : `${e.kind === "add_not_null_with_nulls" ? "NOT NULL on" : "required field"} ${e.tableName}.${e.columnName}`
|
|
21
|
+
).join(", ");
|
|
22
|
+
const parts = [];
|
|
23
|
+
if (candidates.length > 0) {
|
|
24
|
+
parts.push(`${candidates.length} rename candidate(s): ${renameSample}`);
|
|
25
|
+
}
|
|
26
|
+
if (events.length > 0) {
|
|
27
|
+
parts.push(`${events.length} resolution event(s): ${eventSample}`);
|
|
28
|
+
}
|
|
29
|
+
throw new TTYRequiredError(
|
|
30
|
+
// Multi-line so log readers can scan rename vs event sections
|
|
31
|
+
// separately without an arbitrary semicolon-join.
|
|
32
|
+
`Schema change needs confirmation.
|
|
33
|
+
${parts.join("\n")}`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const renameResult = candidates.length > 0 ? await this.runShrinkingPoolPrompts(candidates) : {
|
|
37
|
+
confirmedRenames: [],
|
|
38
|
+
resolutions: [],
|
|
39
|
+
proceed: true
|
|
40
|
+
};
|
|
41
|
+
if (!renameResult.proceed) return renameResult;
|
|
42
|
+
const eventResult = await this.runEventPrompts(events);
|
|
43
|
+
return {
|
|
44
|
+
confirmedRenames: renameResult.confirmedRenames,
|
|
45
|
+
resolutions: eventResult.resolutions,
|
|
46
|
+
proceed: eventResult.proceed
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Walk classifier events in order. NOT-NULL kinds get a multi-step
|
|
50
|
+
// (select kind -> text value if provide_default -> next event); type_change
|
|
51
|
+
// gets a single warning + Y/N. Any abort or cancel returns proceed=false.
|
|
52
|
+
async runEventPrompts(events) {
|
|
53
|
+
if (events.length === 0) {
|
|
54
|
+
return { resolutions: [], proceed: true };
|
|
55
|
+
}
|
|
56
|
+
const resolutions = [];
|
|
57
|
+
clack.intro("Schema change requires confirmation");
|
|
58
|
+
for (const event of events) {
|
|
59
|
+
if (event.kind === "type_change") {
|
|
60
|
+
clack.note(
|
|
61
|
+
[
|
|
62
|
+
event.perDialectWarning.pg,
|
|
63
|
+
event.perDialectWarning.mysql,
|
|
64
|
+
event.perDialectWarning.sqlite
|
|
65
|
+
].join("\n"),
|
|
66
|
+
`Type change on ${event.tableName}.${event.columnName}: ${event.fromType} -> ${event.toType}`
|
|
67
|
+
);
|
|
68
|
+
const proceed = await clack.confirm({
|
|
69
|
+
message: `Proceed with type change on ${event.tableName}.${event.columnName}?`,
|
|
70
|
+
initialValue: false
|
|
71
|
+
});
|
|
72
|
+
if (clack.isCancel(proceed) || proceed === false) {
|
|
73
|
+
clack.outro("Cancelled");
|
|
74
|
+
return { resolutions, proceed: false };
|
|
75
|
+
}
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const headline = event.kind === "add_not_null_with_nulls" ? `Adding NOT NULL to "${event.tableName}.${event.columnName}"
|
|
79
|
+
${event.nullCount} of ${event.tableRowCount} rows have NULL values.` : `New required field "${event.tableName}.${event.columnName}" on table with ${event.tableRowCount} existing rows.`;
|
|
80
|
+
clack.note(headline, "Resolution needed");
|
|
81
|
+
const labels = {
|
|
82
|
+
provide_default: "Provide a default value for empty rows",
|
|
83
|
+
make_optional: "Make the field optional (cancel the NOT NULL)",
|
|
84
|
+
delete_nonconforming: event.kind === "add_not_null_with_nulls" ? `Delete the ${event.nullCount} rows with empty values` : "Delete rows that violate the constraint",
|
|
85
|
+
abort: "Cancel everything"
|
|
86
|
+
};
|
|
87
|
+
const options = event.applicableResolutions.map((kind2) => ({
|
|
88
|
+
value: kind2,
|
|
89
|
+
label: labels[kind2]
|
|
90
|
+
}));
|
|
91
|
+
const choice = await clack.select({
|
|
92
|
+
message: "How do you want to handle this?",
|
|
93
|
+
options
|
|
94
|
+
});
|
|
95
|
+
if (clack.isCancel(choice)) {
|
|
96
|
+
clack.outro("Cancelled");
|
|
97
|
+
return { resolutions, proceed: false };
|
|
98
|
+
}
|
|
99
|
+
const kind = choice;
|
|
100
|
+
if (kind === "abort") {
|
|
101
|
+
clack.outro("Cancelled");
|
|
102
|
+
return { resolutions, proceed: false };
|
|
103
|
+
}
|
|
104
|
+
if (kind === "provide_default") {
|
|
105
|
+
const value = await clack.text({
|
|
106
|
+
message: `Default value for "${event.columnName}":`,
|
|
107
|
+
validate: (v) => !v || v.trim().length === 0 ? "Cannot be empty" : void 0
|
|
108
|
+
});
|
|
109
|
+
if (clack.isCancel(value)) {
|
|
110
|
+
clack.outro("Cancelled");
|
|
111
|
+
return { resolutions, proceed: false };
|
|
112
|
+
}
|
|
113
|
+
resolutions.push({
|
|
114
|
+
kind: "provide_default",
|
|
115
|
+
eventId: event.id,
|
|
116
|
+
value
|
|
117
|
+
});
|
|
118
|
+
} else {
|
|
119
|
+
resolutions.push({ kind, eventId: event.id });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
clack.outro("Resolutions confirmed");
|
|
123
|
+
return { resolutions, proceed: true };
|
|
124
|
+
}
|
|
125
|
+
// Walks candidates in a shrinking-pool pattern:
|
|
126
|
+
// 1. Group candidates by `fromColumn` (the dropped column).
|
|
127
|
+
// 2. For each unique drop, ask the user to pick from its valid adds
|
|
128
|
+
// (filtered to those that haven't been consumed).
|
|
129
|
+
// 3. If user picks 'rename' with a specific add, mark both the drop
|
|
130
|
+
// and the add as consumed; future prompts skip them.
|
|
131
|
+
// 4. If user picks 'drop_and_add', drop survives as drop+add (no rename).
|
|
132
|
+
async runShrinkingPoolPrompts(candidates) {
|
|
133
|
+
const consumedDrops = /* @__PURE__ */ new Set();
|
|
134
|
+
const consumedAdds = /* @__PURE__ */ new Set();
|
|
135
|
+
const confirmed = [];
|
|
136
|
+
const dropToOptions = /* @__PURE__ */ new Map();
|
|
137
|
+
for (const c of candidates) {
|
|
138
|
+
const key = `${c.tableName}::${c.fromColumn}`;
|
|
139
|
+
const list = dropToOptions.get(key) ?? [];
|
|
140
|
+
list.push(c);
|
|
141
|
+
dropToOptions.set(key, list);
|
|
142
|
+
}
|
|
143
|
+
clack.intro("Schema rename detected");
|
|
144
|
+
for (const [dropKey, options] of dropToOptions) {
|
|
145
|
+
if (consumedDrops.has(dropKey)) continue;
|
|
146
|
+
const remaining = options.filter((c) => {
|
|
147
|
+
const addKey = `${c.tableName}::${c.toColumn}`;
|
|
148
|
+
return !consumedAdds.has(addKey);
|
|
149
|
+
});
|
|
150
|
+
if (remaining.length === 0) continue;
|
|
151
|
+
const first = remaining[0];
|
|
152
|
+
const selectOptions = remaining.map((c) => ({
|
|
153
|
+
value: `rename:${c.toColumn}`,
|
|
154
|
+
label: `Rename ${c.fromColumn} -> ${c.toColumn}`,
|
|
155
|
+
hint: c.typesCompatible ? `${c.fromType} -> ${c.toType} (data preserved)` : `${c.fromType} -> ${c.toType} (incompatible types; not recommended)`
|
|
156
|
+
}));
|
|
157
|
+
selectOptions.push({
|
|
158
|
+
value: "drop_and_add",
|
|
159
|
+
label: `Drop ${first.fromColumn} and add new column(s) (data lost)`
|
|
160
|
+
});
|
|
161
|
+
const compatible = remaining.find((c) => c.typesCompatible);
|
|
162
|
+
const initialValue = compatible !== void 0 ? `rename:${compatible.toColumn}` : "drop_and_add";
|
|
163
|
+
const choice = await clack.select({
|
|
164
|
+
message: `Column "${first.fromColumn}" was removed in ${first.tableName}. What should happen?`,
|
|
165
|
+
options: selectOptions,
|
|
166
|
+
initialValue
|
|
167
|
+
});
|
|
168
|
+
if (clack.isCancel(choice)) {
|
|
169
|
+
clack.outro("Cancelled");
|
|
170
|
+
throw new PromptCancelledError();
|
|
171
|
+
}
|
|
172
|
+
if (typeof choice === "string" && choice.startsWith("rename:")) {
|
|
173
|
+
const targetColumn = choice.slice("rename:".length);
|
|
174
|
+
const picked = remaining.find((c) => c.toColumn === targetColumn);
|
|
175
|
+
if (picked) {
|
|
176
|
+
confirmed.push(picked);
|
|
177
|
+
consumedDrops.add(dropKey);
|
|
178
|
+
consumedAdds.add(`${picked.tableName}::${picked.toColumn}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
clack.outro("Schema renames confirmed");
|
|
183
|
+
return {
|
|
184
|
+
confirmedRenames: confirmed,
|
|
185
|
+
resolutions: [],
|
|
186
|
+
proceed: true
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export {
|
|
192
|
+
ClackTerminalPromptDispatcher
|
|
193
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NextlyError
|
|
3
|
+
} from "./chunk-NRUWQ5Z7.mjs";
|
|
4
|
+
|
|
5
|
+
// src/api/read-json-body.ts
|
|
6
|
+
async function readJsonBody(req, extraLogContext) {
|
|
7
|
+
try {
|
|
8
|
+
return await req.json();
|
|
9
|
+
} catch {
|
|
10
|
+
throw new NextlyError({
|
|
11
|
+
code: "VALIDATION_ERROR",
|
|
12
|
+
publicMessage: "Validation failed.",
|
|
13
|
+
publicData: {
|
|
14
|
+
errors: [
|
|
15
|
+
{
|
|
16
|
+
path: "",
|
|
17
|
+
code: "invalid_json",
|
|
18
|
+
message: "Request body is not valid JSON."
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
logContext: { reason: "invalid-json-body", ...extraLogContext }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
readJsonBody
|
|
29
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// src/shared/lib/pluralization.ts
|
|
2
|
+
function isAlreadyPlural(word) {
|
|
3
|
+
const lower = word.toLowerCase();
|
|
4
|
+
const knownPlurals = [
|
|
5
|
+
"people",
|
|
6
|
+
"children",
|
|
7
|
+
"men",
|
|
8
|
+
"women",
|
|
9
|
+
"teeth",
|
|
10
|
+
"feet",
|
|
11
|
+
"mice",
|
|
12
|
+
"geese",
|
|
13
|
+
"oxen",
|
|
14
|
+
"sheep",
|
|
15
|
+
"deer",
|
|
16
|
+
"fish",
|
|
17
|
+
"species",
|
|
18
|
+
"series",
|
|
19
|
+
"crises",
|
|
20
|
+
"analyses",
|
|
21
|
+
"theses",
|
|
22
|
+
"phenomena",
|
|
23
|
+
"criteria",
|
|
24
|
+
"data",
|
|
25
|
+
"alumni",
|
|
26
|
+
"cacti",
|
|
27
|
+
"fungi",
|
|
28
|
+
"nuclei",
|
|
29
|
+
"radii"
|
|
30
|
+
];
|
|
31
|
+
if (knownPlurals.includes(lower)) return true;
|
|
32
|
+
if (lower.endsWith("ies")) return true;
|
|
33
|
+
if (lower.endsWith("ves")) return true;
|
|
34
|
+
if (lower.endsWith("en")) {
|
|
35
|
+
const beforeEN = lower.slice(-3, -2);
|
|
36
|
+
if (beforeEN && !/[aeiou]/.test(beforeEN)) {
|
|
37
|
+
if (lower === "oxen" || lower === "children") return true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (lower.endsWith("i") && lower.length > 2) {
|
|
41
|
+
const beforeI = lower.slice(-2, -1);
|
|
42
|
+
if (["c", "g", "l", "r"].includes(beforeI)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (lower.endsWith("a") && lower.length > 2) {
|
|
47
|
+
const beforeA = lower.slice(-2, -1);
|
|
48
|
+
if (["n", "r"].includes(beforeA)) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (lower.endsWith("oes")) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (lower.endsWith("s") && lower.length > 1 && !isLikelySingular(lower)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
function isLikelySingular(word) {
|
|
61
|
+
const lower = word.toLowerCase();
|
|
62
|
+
const singularEndings = [
|
|
63
|
+
"ss",
|
|
64
|
+
"us",
|
|
65
|
+
"is",
|
|
66
|
+
"os",
|
|
67
|
+
"sis",
|
|
68
|
+
"asis",
|
|
69
|
+
"isis",
|
|
70
|
+
"ysis",
|
|
71
|
+
"tis",
|
|
72
|
+
"itis",
|
|
73
|
+
"esis"
|
|
74
|
+
];
|
|
75
|
+
for (const ending of singularEndings) {
|
|
76
|
+
if (lower.endsWith(ending)) return true;
|
|
77
|
+
}
|
|
78
|
+
const knowSingulars = [
|
|
79
|
+
"glass",
|
|
80
|
+
"class",
|
|
81
|
+
"mass",
|
|
82
|
+
"pass",
|
|
83
|
+
"grass",
|
|
84
|
+
"status",
|
|
85
|
+
"atlas",
|
|
86
|
+
"bus",
|
|
87
|
+
"gas",
|
|
88
|
+
"lens",
|
|
89
|
+
"canvas",
|
|
90
|
+
"process",
|
|
91
|
+
"address",
|
|
92
|
+
"access",
|
|
93
|
+
"success",
|
|
94
|
+
"princess",
|
|
95
|
+
"actress",
|
|
96
|
+
"hostess",
|
|
97
|
+
"witness",
|
|
98
|
+
"fortress",
|
|
99
|
+
"express"
|
|
100
|
+
];
|
|
101
|
+
if (knowSingulars.includes(lower)) return true;
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
function simplePluralize(singular) {
|
|
105
|
+
const normalized = singular.trim();
|
|
106
|
+
if (!normalized) return "";
|
|
107
|
+
if (isAlreadyPlural(normalized)) {
|
|
108
|
+
return normalized;
|
|
109
|
+
}
|
|
110
|
+
if (normalized.endsWith("s") || normalized.endsWith("x") || normalized.endsWith("z")) {
|
|
111
|
+
return normalized + "es";
|
|
112
|
+
}
|
|
113
|
+
if (normalized.endsWith("y") && !/[aeiou]y$/i.test(normalized)) {
|
|
114
|
+
return normalized.slice(0, -1) + "ies";
|
|
115
|
+
}
|
|
116
|
+
return normalized + "s";
|
|
117
|
+
}
|
|
118
|
+
function toSingularLabel(slug) {
|
|
119
|
+
const words = slug.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
|
|
120
|
+
const lastWord = words[words.length - 1];
|
|
121
|
+
if (lastWord.endsWith("s") && lastWord.length > 1) {
|
|
122
|
+
if (!isLikelySingular(lastWord)) {
|
|
123
|
+
words[words.length - 1] = lastWord.slice(0, -1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return words.join(" ");
|
|
127
|
+
}
|
|
128
|
+
function toPluralLabel(slug) {
|
|
129
|
+
const words = slug.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
|
|
130
|
+
const lastWord = words[words.length - 1];
|
|
131
|
+
if (lastWord && !isAlreadyPlural(lastWord)) {
|
|
132
|
+
words[words.length - 1] = simplePluralize(lastWord);
|
|
133
|
+
}
|
|
134
|
+
return words.join(" ");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export {
|
|
138
|
+
simplePluralize,
|
|
139
|
+
toSingularLabel,
|
|
140
|
+
toPluralLabel
|
|
141
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// src/observability/logger.ts
|
|
2
|
+
var defaultLogger = {
|
|
3
|
+
error: (p) => console.error(
|
|
4
|
+
JSON.stringify({ level: "error", ts: (/* @__PURE__ */ new Date()).toISOString(), ...p })
|
|
5
|
+
),
|
|
6
|
+
warn: (p) => console.warn(
|
|
7
|
+
JSON.stringify({ level: "warn", ts: (/* @__PURE__ */ new Date()).toISOString(), ...p })
|
|
8
|
+
),
|
|
9
|
+
info: (p) => console.info(
|
|
10
|
+
JSON.stringify({ level: "info", ts: (/* @__PURE__ */ new Date()).toISOString(), ...p })
|
|
11
|
+
),
|
|
12
|
+
debug: (p) => console.debug(
|
|
13
|
+
JSON.stringify({ level: "debug", ts: (/* @__PURE__ */ new Date()).toISOString(), ...p })
|
|
14
|
+
)
|
|
15
|
+
};
|
|
16
|
+
var currentLogger = defaultLogger;
|
|
17
|
+
function setNextlyLogger(logger) {
|
|
18
|
+
currentLogger = logger ?? defaultLogger;
|
|
19
|
+
}
|
|
20
|
+
function getNextlyLogger() {
|
|
21
|
+
return currentLogger;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
setNextlyLogger,
|
|
26
|
+
getNextlyLogger
|
|
27
|
+
};
|