@intelligo-dev/cli 1.0.0-beta.1 → 1.0.0-beta.14
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/NOTICE +6 -0
- package/README.md +102 -0
- package/dist/bin.js +122 -37
- package/dist/bin.js.map +1 -1
- package/dist/commands/add.d.ts +26 -1
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +70 -4
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/create-flow.d.ts +37 -0
- package/dist/commands/create-flow.d.ts.map +1 -0
- package/dist/commands/create-flow.js +212 -0
- package/dist/commands/create-flow.js.map +1 -0
- package/dist/commands/create.d.ts +27 -6
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +53 -13
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/doctor.d.ts +14 -3
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +295 -37
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/migrate-check.d.ts +73 -1
- package/dist/commands/migrate-check.d.ts.map +1 -1
- package/dist/commands/migrate-check.js +130 -5
- package/dist/commands/migrate-check.js.map +1 -1
- package/dist/commands/migrate.d.ts +97 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +141 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/sync-messages.d.ts +37 -0
- package/dist/commands/sync-messages.d.ts.map +1 -0
- package/dist/commands/sync-messages.js +88 -0
- package/dist/commands/sync-messages.js.map +1 -0
- package/dist/commands/sync-scaffold.d.ts +36 -0
- package/dist/commands/sync-scaffold.d.ts.map +1 -0
- package/dist/commands/sync-scaffold.js +53 -0
- package/dist/commands/sync-scaffold.js.map +1 -0
- package/dist/commands/sync.d.ts +103 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +361 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/upgrade-check.d.ts +5 -5
- package/dist/commands/upgrade-check.d.ts.map +1 -1
- package/dist/commands/upgrade-check.js +22 -6
- package/dist/commands/upgrade-check.js.map +1 -1
- package/dist/env-files.d.ts +12 -0
- package/dist/env-files.d.ts.map +1 -0
- package/dist/env-files.js +29 -0
- package/dist/env-files.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +36 -15
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +32 -16
- package/dist/manifest.js.map +1 -1
- package/dist/migrations.d.ts +3 -6
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +3 -6
- package/dist/migrations.js.map +1 -1
- package/dist/model-catalogue.d.ts +14 -0
- package/dist/model-catalogue.d.ts.map +1 -0
- package/dist/model-catalogue.js +34 -0
- package/dist/model-catalogue.js.map +1 -0
- package/dist/module-exports.d.ts +63 -0
- package/dist/module-exports.d.ts.map +1 -0
- package/dist/module-exports.js +231 -0
- package/dist/module-exports.js.map +1 -0
- package/dist/registry-bundle.d.ts +43 -0
- package/dist/registry-bundle.d.ts.map +1 -0
- package/dist/registry-bundle.js +74 -0
- package/dist/registry-bundle.js.map +1 -0
- package/dist/registry-items.d.ts +84 -0
- package/dist/registry-items.d.ts.map +1 -0
- package/dist/registry-items.js +187 -0
- package/dist/registry-items.js.map +1 -0
- package/package.json +36 -10
- package/src/bin.ts +316 -0
- package/src/commands/add.ts +255 -0
- package/src/commands/create-flow.ts +284 -0
- package/src/commands/create.ts +149 -0
- package/src/commands/doctor.ts +487 -0
- package/src/commands/migrate-check.ts +298 -0
- package/src/commands/migrate.ts +228 -0
- package/src/commands/sync-messages.ts +114 -0
- package/src/commands/sync-scaffold.ts +83 -0
- package/src/commands/sync.ts +534 -0
- package/src/commands/upgrade-check.ts +160 -0
- package/src/env-files.ts +31 -0
- package/src/index.ts +39 -0
- package/src/manifest.ts +147 -0
- package/src/migrations-dir.ts +25 -0
- package/src/migrations.ts +133 -0
- package/src/model-catalogue.ts +35 -0
- package/src/module-exports.ts +266 -0
- package/src/registry-bundle.ts +103 -0
- package/src/registry-items.ts +237 -0
- package/templates/admin-page/admin-page.tsx.tpl +2 -3
- package/templates/app-scaffold/assistant-route.ts.tpl +2 -2
- package/templates/app-scaffold/auth-route.ts.tpl +10 -0
- package/templates/app-scaffold/components.json.tpl +6 -2
- package/templates/app-scaffold/db-schema.ts.tpl +29 -0
- package/templates/app-scaffold/drizzle-journal.json.tpl +5 -0
- package/templates/app-scaffold/drizzle.config.ts.tpl +45 -0
- package/templates/app-scaffold/env.example.tpl +65 -1
- package/templates/app-scaffold/globals.css.tpl +172 -281
- package/templates/app-scaffold/i18n-request.ts.tpl +25 -0
- package/templates/app-scaffold/instrumentation.ts.tpl +21 -0
- package/templates/app-scaffold/intelligo.ts.tpl +95 -41
- package/templates/app-scaffold/layout.tsx.tpl +18 -1
- package/templates/app-scaffold/lib-utils.ts.tpl +1 -6
- package/templates/app-scaffold/next.config.mjs.tpl +2 -0
- package/templates/app-scaffold/package.json.tpl +31 -17
- package/templates/app-scaffold/page.tsx.tpl +16 -0
- package/templates/app-scaffold/plans.ts.tpl +32 -13
- package/templates/app-scaffold/{middleware.ts.tpl → proxy.ts.tpl} +6 -0
- package/templates/app-scaffold/sonner.tsx.tpl +42 -20
- package/templates/app-scaffold/stripe-webhook-route.ts.tpl +24 -0
- package/templates/app-scaffold/theme-provider.tsx.tpl +6 -4
- package/templates/app-scaffold/tsconfig.json.tpl +20 -4
- package/templates/app-scaffold/use-mobile.ts.tpl +19 -0
- package/templates/app-scaffold/workspace-bootstrap.ts.tpl +30 -0
- package/templates/maintenance/maintenance-route.ts.tpl +119 -0
- package/templates/manifest.json +75 -17
- package/templates/registry/ai-agent-activity.json +23 -0
- package/templates/registry/ai-agent-progress.json +21 -0
- package/templates/registry/ai-approval-card.json +27 -0
- package/templates/registry/ai-artifact.json +22 -0
- package/templates/registry/ai-branch.json +21 -0
- package/templates/registry/ai-citations.json +24 -0
- package/templates/registry/ai-code-block.json +23 -0
- package/templates/registry/ai-composer-menu.json +19 -0
- package/templates/registry/ai-file-diff.json +25 -0
- package/templates/registry/ai-image-generation.json +23 -0
- package/templates/registry/ai-markdown.json +23 -0
- package/templates/registry/ai-message-bubble.json +23 -0
- package/templates/registry/ai-message-scroller.json +22 -0
- package/templates/registry/ai-message.json +21 -0
- package/templates/registry/ai-motion.json +19 -0
- package/templates/registry/ai-prompt-input.json +28 -0
- package/templates/registry/ai-reasoning-text.json +22 -0
- package/templates/registry/ai-reasoning.json +22 -0
- package/templates/registry/ai-shimmer-text.json +19 -0
- package/templates/registry/ai-sidebar.json +25 -0
- package/templates/registry/ai-speech-input.json +21 -0
- package/templates/registry/ai-streaming-response.json +24 -0
- package/templates/registry/ai-suggestion.json +19 -0
- package/templates/registry/ai-todo-list.json +22 -0
- package/templates/registry/ai-tool-approval.json +26 -0
- package/templates/registry/ai-tool-result.json +25 -0
- package/templates/registry/alert-dialog.json +23 -0
- package/templates/registry/animated-list.json +21 -0
- package/templates/registry/app-shell.json +93 -0
- package/templates/registry/artifacts.json +82 -0
- package/templates/registry/attachment.json +22 -0
- package/templates/registry/auth-email-verification.json +39 -0
- package/templates/registry/auth-login.json +72 -0
- package/templates/registry/auth-password-reset.json +53 -0
- package/templates/registry/auth-signup.json +41 -0
- package/templates/registry/billing-settings.json +60 -0
- package/templates/registry/button.json +22 -0
- package/templates/registry/chat-eve.json +19 -0
- package/templates/registry/chat-panel.json +30 -0
- package/templates/registry/chat-share.json +42 -0
- package/templates/registry/chat-widget.json +34 -0
- package/templates/registry/chat.json +326 -0
- package/templates/registry/checkbox.json +22 -0
- package/templates/registry/checkout.json +40 -0
- package/templates/registry/collapsible.json +19 -0
- package/templates/registry/command.json +23 -0
- package/templates/registry/copy-button.json +21 -0
- package/templates/registry/dashboard.json +69 -0
- package/templates/registry/dialog.json +24 -0
- package/templates/registry/document-viewer.json +22 -0
- package/templates/registry/dropdown-menu.json +23 -0
- package/templates/registry/expandable-tabs.json +22 -0
- package/templates/registry/feature-gating.json +73 -0
- package/templates/registry/file-upload.json +24 -0
- package/templates/registry/hold-action-button.json +22 -0
- package/templates/registry/input-group.json +23 -0
- package/templates/registry/input.json +19 -0
- package/templates/registry/intelligo.json +187 -0
- package/templates/registry/invitation-accept.json +64 -0
- package/templates/registry/language-switcher.json +29 -0
- package/templates/registry/morphing-modal.json +24 -0
- package/templates/registry/notification-stack.json +24 -0
- package/templates/registry/notifications.json +87 -0
- package/templates/registry/onboarding.json +83 -0
- package/templates/registry/otp-input.json +22 -0
- package/templates/registry/page-header.json +15 -0
- package/templates/registry/payment-poll.json +52 -0
- package/templates/registry/popover-morph.json +22 -0
- package/templates/registry/popover.json +22 -0
- package/templates/registry/pricing.json +111 -0
- package/templates/registry/privacy-settings.json +65 -0
- package/templates/registry/profile-settings.json +68 -0
- package/templates/registry/progress.json +19 -0
- package/templates/registry/radio-group.json +22 -0
- package/templates/registry/registry.json +2945 -0
- package/templates/registry/route-error.json +65 -0
- package/templates/registry/select-morph.json +23 -0
- package/templates/registry/select.json +23 -0
- package/templates/registry/settings-shell.json +47 -0
- package/templates/registry/sheet.json +24 -0
- package/templates/registry/sidebar.json +28 -0
- package/templates/registry/smoke.json +34 -0
- package/templates/registry/spinner.json +16 -0
- package/templates/registry/stat-card.json +18 -0
- package/templates/registry/status-badge.json +18 -0
- package/templates/registry/switch.json +20 -0
- package/templates/registry/tabs.json +23 -0
- package/templates/registry/team-settings.json +97 -0
- package/templates/registry/textarea.json +16 -0
- package/templates/registry/tooltip.json +22 -0
- package/templates/registry/trial-banner.json +43 -0
- package/templates/registry/usage.json +84 -0
- package/templates/registry/workspace-settings.json +71 -0
- package/templates/registry-items.json +116 -0
- package/templates/registry-requires.json +180 -0
- package/templates/usage-page/usage-page.tsx.tpl +23 -8
- package/templates/vitest/server-only.ts.tpl +7 -0
- package/templates/vitest/vitest.config.ts.tpl +37 -0
- package/templates/billing-page/billing-page.tsx.tpl +0 -72
|
@@ -15,11 +15,42 @@
|
|
|
15
15
|
* schema but no rows there at all, which this reports distinctly:
|
|
16
16
|
* "unmanaged" is a different problem from "behind", and baselining is
|
|
17
17
|
* the fix (see the migrations README).
|
|
18
|
+
*
|
|
19
|
+
* The framework's chain is one baseline. A database that ran the pre-1.0
|
|
20
|
+
* chain holds its hashes, which `legacy-chain.json` (next to the
|
|
21
|
+
* journal) lists: they are reported as `legacy`, not as unknown, and a
|
|
22
|
+
* database holding all of them is `adoptable` — its schema is the
|
|
23
|
+
* baseline's, so `migrate` records the baseline without running it.
|
|
24
|
+
*
|
|
25
|
+
* The exit code is 1 whenever anything is pending or the database is
|
|
26
|
+
* ahead, which a brand-new database and a stale one share. A deploy
|
|
27
|
+
* gate that must tell them apart reads `migrate --check --json`: one
|
|
28
|
+
* JSON object on stdout, same exit code, whose `state` is
|
|
29
|
+
*
|
|
30
|
+
* - `up_to_date` — every migration is applied;
|
|
31
|
+
* - `pending` — a migrated database is behind this checkout;
|
|
32
|
+
* - `fresh` — no migration records and none of the framework's
|
|
33
|
+
* tables: an empty database, `migrate` applies the chain;
|
|
34
|
+
* - `unmanaged` — the tables exist with no records (`db:push`);
|
|
35
|
+
* - `ahead` — applied migrations this checkout does not contain;
|
|
36
|
+
* - `legacy` — the pre-1.0 chain; `adoptable` says whether
|
|
37
|
+
* `migrate` can take it over.
|
|
38
|
+
*
|
|
39
|
+
* Beside `state` it carries `exitCode`, `chain`, `applied`, `pending`,
|
|
40
|
+
* `unknown`, `legacy`, `legacyMissing` and `adoptable`.
|
|
18
41
|
*/
|
|
19
42
|
import { createHash } from "node:crypto";
|
|
20
|
-
import { readFileSync } from "node:fs";
|
|
43
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
21
44
|
import path from "node:path";
|
|
22
45
|
import { readMigrationChain } from "../migrations.js";
|
|
46
|
+
/** The pre-1.0 chain's tags and hashes, if this checkout ships them. */
|
|
47
|
+
export function readLegacyChain(migrationsDir) {
|
|
48
|
+
const file = path.join(migrationsDir, "legacy-chain.json");
|
|
49
|
+
if (!existsSync(file))
|
|
50
|
+
return [];
|
|
51
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
52
|
+
return parsed.entries ?? [];
|
|
53
|
+
}
|
|
23
54
|
/** Drizzle hashes the file contents with sha256. */
|
|
24
55
|
export function hashMigration(sql) {
|
|
25
56
|
return createHash("sha256").update(sql).digest("hex");
|
|
@@ -45,33 +76,70 @@ export async function migrateCheck(migrationsDir, query) {
|
|
|
45
76
|
catch {
|
|
46
77
|
tableMissing = true;
|
|
47
78
|
}
|
|
79
|
+
const legacyChain = readLegacyChain(migrationsDir);
|
|
80
|
+
// A migration can be recorded under more than one hash: npm's
|
|
81
|
+
// 1.0.0-beta.6 shipped different bytes for three of them.
|
|
82
|
+
const legacyByHash = new Map(legacyChain.flatMap((e) => [e.hash, ...(e.alternates ?? [])].map((h) => [h, e.tag])));
|
|
48
83
|
const appliedHashes = new Set(rows.map((r) => r.hash));
|
|
49
84
|
const applied = [];
|
|
50
85
|
const unknown = [];
|
|
86
|
+
const legacy = [];
|
|
51
87
|
for (const hash of appliedHashes) {
|
|
52
88
|
const tag = hashToTag.get(hash);
|
|
89
|
+
const legacyTag = legacyByHash.get(hash);
|
|
53
90
|
if (tag)
|
|
54
91
|
applied.push(tag);
|
|
92
|
+
else if (legacyTag)
|
|
93
|
+
legacy.push(legacyTag);
|
|
55
94
|
else
|
|
56
95
|
unknown.push(hash.slice(0, 12));
|
|
57
96
|
}
|
|
58
97
|
const appliedTags = new Set(applied);
|
|
59
98
|
const pending = chain.journalTags.filter((t) => !appliedTags.has(t));
|
|
99
|
+
const baseline = chain.journalTags[0];
|
|
60
100
|
return {
|
|
61
101
|
chain: chain.journalTags,
|
|
62
102
|
applied,
|
|
63
103
|
pending,
|
|
64
104
|
unknown,
|
|
65
105
|
unmanaged: tableMissing || appliedHashes.size === 0,
|
|
106
|
+
legacy,
|
|
107
|
+
legacyChainLength: legacyChain.length,
|
|
108
|
+
legacyMissing: legacy.length > 0
|
|
109
|
+
? legacyChain.map((e) => e.tag).filter((t) => !legacy.includes(t))
|
|
110
|
+
: [],
|
|
111
|
+
adoptable: legacyChain.length > 0 &&
|
|
112
|
+
legacy.length === legacyChain.length &&
|
|
113
|
+
baseline !== undefined &&
|
|
114
|
+
!appliedTags.has(baseline),
|
|
66
115
|
};
|
|
67
116
|
}
|
|
68
|
-
|
|
117
|
+
/**
|
|
118
|
+
* `schemaExists` is whether the framework's tables are in the database
|
|
119
|
+
* (`SCHEMA_PROBE_SQL`). When the caller did not probe, a database with
|
|
120
|
+
* no records gets the cautious `db:push` wording.
|
|
121
|
+
*/
|
|
122
|
+
export function formatMigrateCheck(r, schemaExists) {
|
|
69
123
|
const lines = [];
|
|
70
|
-
if (r.unmanaged) {
|
|
124
|
+
if (r.unmanaged && schemaExists === false) {
|
|
125
|
+
lines.push(`! This database is empty: no migration records and none of the ` +
|
|
126
|
+
`framework's tables. \`intelligo migrate\` applies all ` +
|
|
127
|
+
`${r.chain.length} migration(s).`);
|
|
128
|
+
}
|
|
129
|
+
else if (r.unmanaged) {
|
|
71
130
|
lines.push(`! This database has no migration records. If it was provisioned with ` +
|
|
72
131
|
`db:push, baseline it before running migrate — otherwise migrate will ` +
|
|
73
|
-
`try to apply all ${r.chain.length} migrations. See ` +
|
|
74
|
-
|
|
132
|
+
`try to apply all ${r.chain.length} migrations. See README.md in ` +
|
|
133
|
+
`@intelligo-dev/core's src/db/migrations.`);
|
|
134
|
+
}
|
|
135
|
+
if (r.adoptable) {
|
|
136
|
+
lines.push(`! This database ran the framework's pre-1.0 migration chain. migrate ` +
|
|
137
|
+
`records ${r.chain[0]} as applied without running it (the schema is ` +
|
|
138
|
+
`already there), then applies what follows. Tables the old chain ` +
|
|
139
|
+
`created that the framework no longer owns are left untouched.`);
|
|
140
|
+
}
|
|
141
|
+
else if (isPartialLegacy(r)) {
|
|
142
|
+
lines.push(`✗ ${partialLegacyMessage(r)}`);
|
|
75
143
|
}
|
|
76
144
|
if (r.unknown.length > 0) {
|
|
77
145
|
lines.push(`✗ Database is ahead: ${r.unknown.length} applied migration(s) are not in ` +
|
|
@@ -89,4 +157,61 @@ export function formatMigrateCheck(r) {
|
|
|
89
157
|
export function migrateCheckExitCode(r) {
|
|
90
158
|
return r.pending.length > 0 || r.unknown.length > 0 ? 1 : 0;
|
|
91
159
|
}
|
|
160
|
+
/** A partial pre-1.0 chain: neither adoptable nor migratable from here. */
|
|
161
|
+
export function isPartialLegacy(r) {
|
|
162
|
+
return r.legacy.length > 0 && r.legacy.length < r.legacyChainLength;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The last pre-1.0 migration any published `@intelligo-dev/core`
|
|
166
|
+
* carries: 1.0.0-beta.6 shipped the chain through it, and the versions
|
|
167
|
+
* that carried the rest were never published.
|
|
168
|
+
*/
|
|
169
|
+
export const LAST_PUBLISHED_LEGACY_TAG = "0042_sessions_active_organization_id";
|
|
170
|
+
/**
|
|
171
|
+
* Why a partial pre-1.0 chain is refused and where the way forward is
|
|
172
|
+
* written down. No published version finishes the chain, so the
|
|
173
|
+
* message names what is missing and points at the README's options
|
|
174
|
+
* instead of at a version to install.
|
|
175
|
+
*/
|
|
176
|
+
export function partialLegacyMessage(r) {
|
|
177
|
+
const shown = r.legacyMissing.slice(0, 6);
|
|
178
|
+
const more = r.legacyMissing.length - shown.length;
|
|
179
|
+
return (`This database ran ${r.legacy.length} of the ${r.legacyChainLength} ` +
|
|
180
|
+
`pre-1.0 migrations; it has not run ${shown.join(", ")}` +
|
|
181
|
+
`${more > 0 ? ` and ${more} more` : ""}. No published ` +
|
|
182
|
+
`@intelligo-dev/core finishes that chain: 1.0.0-beta.6 ships it ` +
|
|
183
|
+
`through ${LAST_PUBLISHED_LEGACY_TAG}, and the versions that carried ` +
|
|
184
|
+
`the rest never reached npm. Apply the missing migrations' SQL from ` +
|
|
185
|
+
`your own copy of it, or bring the schema to the baseline and record ` +
|
|
186
|
+
`it as applied — see "Databases from before 1.0" in README.md in ` +
|
|
187
|
+
`@intelligo-dev/core's src/db/migrations.`);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* One word for what the check found, most urgent first: a database that
|
|
191
|
+
* is ahead or on the pre-1.0 chain is that before it is anything else.
|
|
192
|
+
* `schemaExists` separates an empty database from a push-provisioned one.
|
|
193
|
+
*/
|
|
194
|
+
export function migrateState(r, schemaExists) {
|
|
195
|
+
if (r.unknown.length > 0)
|
|
196
|
+
return "ahead";
|
|
197
|
+
if (r.legacy.length > 0)
|
|
198
|
+
return "legacy";
|
|
199
|
+
if (r.unmanaged)
|
|
200
|
+
return schemaExists ? "unmanaged" : "fresh";
|
|
201
|
+
return r.pending.length > 0 ? "pending" : "up_to_date";
|
|
202
|
+
}
|
|
203
|
+
/** The `--json` report: `state` first, then the detail behind it. */
|
|
204
|
+
export function formatMigrateCheckJson(r, schemaExists) {
|
|
205
|
+
return JSON.stringify({
|
|
206
|
+
state: migrateState(r, schemaExists),
|
|
207
|
+
exitCode: migrateCheckExitCode(r),
|
|
208
|
+
chain: r.chain,
|
|
209
|
+
applied: r.applied,
|
|
210
|
+
pending: r.pending,
|
|
211
|
+
unknown: r.unknown,
|
|
212
|
+
legacy: r.legacy,
|
|
213
|
+
legacyMissing: r.legacyMissing,
|
|
214
|
+
adoptable: r.adoptable,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
92
217
|
//# sourceMappingURL=migrate-check.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-check.js","sourceRoot":"","sources":["../../src/commands/migrate-check.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"migrate-check.js","sourceRoot":"","sources":["../../src/commands/migrate-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intelligo migrate` — apply the framework's migration chain.
|
|
3
|
+
*
|
|
4
|
+
* A consumer application has two migration chains in one database:
|
|
5
|
+
* the framework's, shipped inside `@intelligo-dev/core` (its `.sql`
|
|
6
|
+
* files and journal are in the package's `files`), and its own, which
|
|
7
|
+
* drizzle-kit generates from the tables the application owns. They
|
|
8
|
+
* must not share a journal — drizzle-kit applies by timestamp, so a
|
|
9
|
+
* framework migration published after the consumer generated one of
|
|
10
|
+
* theirs would be silently skipped — and a consumer cannot write into
|
|
11
|
+
* `node_modules` anyway. So the framework chain is applied by this
|
|
12
|
+
* command, into drizzle's default `drizzle.__drizzle_migrations`
|
|
13
|
+
* table, and the consumer's chain by `drizzle-kit migrate` from their
|
|
14
|
+
* own `drizzle.config.ts`, into a table of its own (the scaffold sets
|
|
15
|
+
* `migrations.table` to `__app_migrations`).
|
|
16
|
+
*
|
|
17
|
+
* Migrations are selected by content hash (what `migrate --check`
|
|
18
|
+
* compares), not by drizzle's journal-timestamp rule, and are recorded
|
|
19
|
+
* in the same table drizzle's migrator writes — see
|
|
20
|
+
* `readPendingMigrations` for why.
|
|
21
|
+
*
|
|
22
|
+
* The one thing this refuses to do is guess. A database with the
|
|
23
|
+
* framework's tables but no migration records was provisioned with
|
|
24
|
+
* `db:push`; applying the whole chain to it would fail part-way (not
|
|
25
|
+
* every migration is `IF NOT EXISTS`-guarded) and leave the records
|
|
26
|
+
* half-written. Baselining is the fix, and it is deliberately a manual
|
|
27
|
+
* step — see `packages/core/src/db/migrations/README.md`.
|
|
28
|
+
*/
|
|
29
|
+
import { type MigrateCheckResult } from "./migrate-check.js";
|
|
30
|
+
export type ApplyDecision = {
|
|
31
|
+
action: "apply";
|
|
32
|
+
pending: string[];
|
|
33
|
+
/** Recorded as applied without running: the schema is already there. */
|
|
34
|
+
adopted: string[];
|
|
35
|
+
} | {
|
|
36
|
+
action: "noop";
|
|
37
|
+
} | {
|
|
38
|
+
action: "refuse";
|
|
39
|
+
reason: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* What to do with a database, given the check result and whether the
|
|
43
|
+
* framework's schema already exists in it. Pure, so the three states
|
|
44
|
+
* that matter — empty, push-provisioned, behind — are unit-testable
|
|
45
|
+
* without a database.
|
|
46
|
+
*/
|
|
47
|
+
export declare function decideApply(check: MigrateCheckResult, schemaExists: boolean): ApplyDecision;
|
|
48
|
+
type QueryFn = (sql: string) => Promise<Array<Record<string, unknown>>>;
|
|
49
|
+
/**
|
|
50
|
+
* One migration ready to run: its statements and the journal entry it
|
|
51
|
+
* will be recorded under. `createdAt` is the journal's `when`, which is
|
|
52
|
+
* what drizzle-kit writes to `created_at` too, so records made here and
|
|
53
|
+
* records made by drizzle's own migrator are indistinguishable.
|
|
54
|
+
*/
|
|
55
|
+
export type PendingMigration = {
|
|
56
|
+
tag: string;
|
|
57
|
+
hash: string;
|
|
58
|
+
createdAt: number;
|
|
59
|
+
statements: string[];
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Read the pending migrations off disk, in journal order.
|
|
63
|
+
*
|
|
64
|
+
* The chain is applied by content hash — the same key `migrate --check`
|
|
65
|
+
* compares — and not by drizzle's rule of "every entry whose journal
|
|
66
|
+
* timestamp is greater than the last applied row's". That rule depends
|
|
67
|
+
* on `when` values increasing monotonically, which a hand-numbered
|
|
68
|
+
* journal does not guarantee: an entry numbered below an applied one is
|
|
69
|
+
* skipped silently while the check reports it pending. Selecting by hash makes "pending" mean exactly what the check says.
|
|
70
|
+
*/
|
|
71
|
+
export declare function readPendingMigrations(migrationsDir: string, pendingTags: string[]): PendingMigration[];
|
|
72
|
+
/** The records table drizzle's migrator uses, created the way it creates it. */
|
|
73
|
+
export declare const MIGRATIONS_TABLE_SQL: string[];
|
|
74
|
+
export type ApplyMigrationsOptions = {
|
|
75
|
+
migrationsDir: string;
|
|
76
|
+
/** Runs a read-only query and returns its rows. */
|
|
77
|
+
query: QueryFn;
|
|
78
|
+
/**
|
|
79
|
+
* Applies the given migrations in order, all in one transaction,
|
|
80
|
+
* recording each in `drizzle.__drizzle_migrations` as it goes.
|
|
81
|
+
*/
|
|
82
|
+
run: (pending: PendingMigration[]) => Promise<void>;
|
|
83
|
+
};
|
|
84
|
+
export type ApplyMigrationsResult = ApplyDecision & {
|
|
85
|
+
/** After the run, for the summary line and for `noop` detection. */
|
|
86
|
+
chainLength: number;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* `users` is the first table the framework creates (auth), so its
|
|
90
|
+
* presence with no migration records is the push-provisioned signature.
|
|
91
|
+
*/
|
|
92
|
+
export declare const SCHEMA_PROBE_SQL = "SELECT to_regclass('public.users') AS rel";
|
|
93
|
+
export declare function applyMigrations(options: ApplyMigrationsOptions): Promise<ApplyMigrationsResult>;
|
|
94
|
+
export declare function formatApplyResult(r: ApplyMigrationsResult): string;
|
|
95
|
+
export declare function applyExitCode(r: ApplyMigrationsResult): number;
|
|
96
|
+
export {};
|
|
97
|
+
//# sourceMappingURL=migrate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAKH,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,aAAa,GACrB;IACE,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,wEAAwE;IACxE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,GACD;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,kBAAkB,EACzB,YAAY,EAAE,OAAO,GACpB,aAAa,CAuCf;AAED,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAExE;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EAAE,GACpB,gBAAgB,EAAE,CAqBpB;AAED,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,UAGhC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,KAAK,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,GAAG,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG;IAClD,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,8CAA8C,CAAC;AAE5E,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAwBhC;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAgBlE;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAE9D"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intelligo migrate` — apply the framework's migration chain.
|
|
3
|
+
*
|
|
4
|
+
* A consumer application has two migration chains in one database:
|
|
5
|
+
* the framework's, shipped inside `@intelligo-dev/core` (its `.sql`
|
|
6
|
+
* files and journal are in the package's `files`), and its own, which
|
|
7
|
+
* drizzle-kit generates from the tables the application owns. They
|
|
8
|
+
* must not share a journal — drizzle-kit applies by timestamp, so a
|
|
9
|
+
* framework migration published after the consumer generated one of
|
|
10
|
+
* theirs would be silently skipped — and a consumer cannot write into
|
|
11
|
+
* `node_modules` anyway. So the framework chain is applied by this
|
|
12
|
+
* command, into drizzle's default `drizzle.__drizzle_migrations`
|
|
13
|
+
* table, and the consumer's chain by `drizzle-kit migrate` from their
|
|
14
|
+
* own `drizzle.config.ts`, into a table of its own (the scaffold sets
|
|
15
|
+
* `migrations.table` to `__app_migrations`).
|
|
16
|
+
*
|
|
17
|
+
* Migrations are selected by content hash (what `migrate --check`
|
|
18
|
+
* compares), not by drizzle's journal-timestamp rule, and are recorded
|
|
19
|
+
* in the same table drizzle's migrator writes — see
|
|
20
|
+
* `readPendingMigrations` for why.
|
|
21
|
+
*
|
|
22
|
+
* The one thing this refuses to do is guess. A database with the
|
|
23
|
+
* framework's tables but no migration records was provisioned with
|
|
24
|
+
* `db:push`; applying the whole chain to it would fail part-way (not
|
|
25
|
+
* every migration is `IF NOT EXISTS`-guarded) and leave the records
|
|
26
|
+
* half-written. Baselining is the fix, and it is deliberately a manual
|
|
27
|
+
* step — see `packages/core/src/db/migrations/README.md`.
|
|
28
|
+
*/
|
|
29
|
+
import { readFileSync } from "node:fs";
|
|
30
|
+
import path from "node:path";
|
|
31
|
+
import { hashMigration, isPartialLegacy, migrateCheck, partialLegacyMessage, } from "./migrate-check.js";
|
|
32
|
+
/**
|
|
33
|
+
* What to do with a database, given the check result and whether the
|
|
34
|
+
* framework's schema already exists in it. Pure, so the three states
|
|
35
|
+
* that matter — empty, push-provisioned, behind — are unit-testable
|
|
36
|
+
* without a database.
|
|
37
|
+
*/
|
|
38
|
+
export function decideApply(check, schemaExists) {
|
|
39
|
+
if (check.unknown.length > 0) {
|
|
40
|
+
return {
|
|
41
|
+
action: "refuse",
|
|
42
|
+
reason: `Database is ahead: ${check.unknown.length} applied migration(s) are ` +
|
|
43
|
+
`not in this checkout (${check.unknown.join(", ")}). Upgrade ` +
|
|
44
|
+
`@intelligo-dev/core before migrating, or restore the database.`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (isPartialLegacy(check)) {
|
|
48
|
+
return { action: "refuse", reason: partialLegacyMessage(check) };
|
|
49
|
+
}
|
|
50
|
+
if (check.adoptable) {
|
|
51
|
+
const [baseline, ...rest] = check.pending;
|
|
52
|
+
return {
|
|
53
|
+
action: "apply",
|
|
54
|
+
adopted: baseline ? [baseline] : [],
|
|
55
|
+
pending: rest,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (check.unmanaged && schemaExists) {
|
|
59
|
+
return {
|
|
60
|
+
action: "refuse",
|
|
61
|
+
reason: `This database has the framework's tables but no migration records — ` +
|
|
62
|
+
`it was provisioned with db:push. Baseline it before running migrate, ` +
|
|
63
|
+
`otherwise all ${check.chain.length} migrations would be applied to ` +
|
|
64
|
+
`tables that already exist. See README.md in @intelligo-dev/core's ` +
|
|
65
|
+
`src/db/migrations.`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (check.pending.length === 0)
|
|
69
|
+
return { action: "noop" };
|
|
70
|
+
return { action: "apply", pending: check.pending, adopted: [] };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Read the pending migrations off disk, in journal order.
|
|
74
|
+
*
|
|
75
|
+
* The chain is applied by content hash — the same key `migrate --check`
|
|
76
|
+
* compares — and not by drizzle's rule of "every entry whose journal
|
|
77
|
+
* timestamp is greater than the last applied row's". That rule depends
|
|
78
|
+
* on `when` values increasing monotonically, which a hand-numbered
|
|
79
|
+
* journal does not guarantee: an entry numbered below an applied one is
|
|
80
|
+
* skipped silently while the check reports it pending. Selecting by hash makes "pending" mean exactly what the check says.
|
|
81
|
+
*/
|
|
82
|
+
export function readPendingMigrations(migrationsDir, pendingTags) {
|
|
83
|
+
const journal = JSON.parse(readFileSync(path.join(migrationsDir, "meta", "_journal.json"), "utf8"));
|
|
84
|
+
const byTag = new Map((journal.entries ?? []).map((e) => [e.tag, e]));
|
|
85
|
+
return pendingTags.map((tag) => {
|
|
86
|
+
const entry = byTag.get(tag);
|
|
87
|
+
if (!entry)
|
|
88
|
+
throw new Error(`${tag} is pending but not in the journal`);
|
|
89
|
+
const sql = readFileSync(path.join(migrationsDir, `${tag}.sql`), "utf8");
|
|
90
|
+
const statements = (entry.breakpoints === false
|
|
91
|
+
? [sql]
|
|
92
|
+
: sql.split("--> statement-breakpoint"))
|
|
93
|
+
.map((s) => s.trim())
|
|
94
|
+
.filter((s) => s.length > 0);
|
|
95
|
+
return { tag, hash: hashMigration(sql), createdAt: entry.when, statements };
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/** The records table drizzle's migrator uses, created the way it creates it. */
|
|
99
|
+
export const MIGRATIONS_TABLE_SQL = [
|
|
100
|
+
`CREATE SCHEMA IF NOT EXISTS "drizzle"`,
|
|
101
|
+
`CREATE TABLE IF NOT EXISTS "drizzle"."__drizzle_migrations" (id SERIAL PRIMARY KEY, hash text NOT NULL, created_at bigint)`,
|
|
102
|
+
];
|
|
103
|
+
/**
|
|
104
|
+
* `users` is the first table the framework creates (auth), so its
|
|
105
|
+
* presence with no migration records is the push-provisioned signature.
|
|
106
|
+
*/
|
|
107
|
+
export const SCHEMA_PROBE_SQL = `SELECT to_regclass('public.users') AS rel`;
|
|
108
|
+
export async function applyMigrations(options) {
|
|
109
|
+
const check = await migrateCheck(options.migrationsDir, async (sql) => (await options.query(sql)));
|
|
110
|
+
const probe = await options.query(SCHEMA_PROBE_SQL);
|
|
111
|
+
const schemaExists = probe.length > 0 && probe[0].rel != null;
|
|
112
|
+
const decision = decideApply(check, schemaExists);
|
|
113
|
+
if (decision.action === "apply") {
|
|
114
|
+
// An adopted migration is recorded with no statements: its schema is
|
|
115
|
+
// already in the database.
|
|
116
|
+
const adopted = readPendingMigrations(options.migrationsDir, decision.adopted).map((m) => ({ ...m, statements: [] }));
|
|
117
|
+
await options.run([
|
|
118
|
+
...adopted,
|
|
119
|
+
...readPendingMigrations(options.migrationsDir, decision.pending),
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
return { ...decision, chainLength: check.chain.length };
|
|
123
|
+
}
|
|
124
|
+
export function formatApplyResult(r) {
|
|
125
|
+
switch (r.action) {
|
|
126
|
+
case "refuse":
|
|
127
|
+
return `✗ ${r.reason}`;
|
|
128
|
+
case "noop":
|
|
129
|
+
return `✓ Nothing to apply (${r.chainLength}/${r.chainLength} applied)`;
|
|
130
|
+
case "apply":
|
|
131
|
+
return [
|
|
132
|
+
...r.adopted.map((tag) => `✓ Adopted ${tag}: this database ran the pre-1.0 chain, so its schema is already there`),
|
|
133
|
+
`✓ Applied ${r.pending.length} migration(s):`,
|
|
134
|
+
...r.pending.map((tag) => ` ${tag}`),
|
|
135
|
+
].join("\n");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export function applyExitCode(r) {
|
|
139
|
+
return r.action === "refuse" ? 1 : 0;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,eAAe,EACf,YAAY,EACZ,oBAAoB,GAErB,MAAM,oBAAoB,CAAC;AAY5B;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,KAAyB,EACzB,YAAqB;IAErB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,MAAM,EAAE,QAAQ;YAChB,MAAM,EACJ,sBAAsB,KAAK,CAAC,OAAO,CAAC,MAAM,4BAA4B;gBACtE,yBAAyB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa;gBAC9D,gEAAgE;SACnE,CAAC;IACJ,CAAC;IAED,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;IACnE,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;QAC1C,OAAO;YACL,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;YACnC,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,IAAI,YAAY,EAAE,CAAC;QACpC,OAAO;YACL,MAAM,EAAE,QAAQ;YAChB,MAAM,EACJ,sEAAsE;gBACtE,uEAAuE;gBACvE,iBAAiB,KAAK,CAAC,KAAK,CAAC,MAAM,kCAAkC;gBACrE,oEAAoE;gBACpE,oBAAoB;SACvB,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAE1D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAClE,CAAC;AAiBD;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CACnC,aAAqB,EACrB,WAAqB;IAErB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACxB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAGxE,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtE,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,oCAAoC,CAAC,CAAC;QACxE,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,GAAG,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QACzE,MAAM,UAAU,GAAG,CACjB,KAAK,CAAC,WAAW,KAAK,KAAK;YACzB,CAAC,CAAC,CAAC,GAAG,CAAC;YACP,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAC1C;aACE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,uCAAuC;IACvC,4HAA4H;CAC7H,CAAC;AAkBF;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,2CAA2C,CAAC;AAE5E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA+B;IAE/B,MAAM,KAAK,GAAG,MAAM,YAAY,CAC9B,OAAO,CAAC,aAAa,EACrB,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAA4B,CACrE,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,GAAG,IAAI,IAAI,CAAC;IAE/D,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAClD,IAAI,QAAQ,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAChC,qEAAqE;QACrE,2BAA2B;QAC3B,MAAM,OAAO,GAAG,qBAAqB,CACnC,OAAO,CAAC,aAAa,EACrB,QAAQ,CAAC,OAAO,CACjB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACzC,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,GAAG,OAAO;YACV,GAAG,qBAAqB,CAAC,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,OAAO,CAAC;SAClE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,CAAwB;IACxD,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QACzB,KAAK,MAAM;YACT,OAAO,uBAAuB,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,WAAW,CAAC;QAC1E,KAAK,OAAO;YACV,OAAO;gBACL,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CACd,CAAC,GAAG,EAAE,EAAE,CACN,aAAa,GAAG,uEAAuE,CAC1F;gBACD,aAAa,CAAC,CAAC,OAAO,CAAC,MAAM,gBAAgB;gBAC7C,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC;aACxC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,CAAwB;IACpD,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message files under `intelligo sync`: the registry's keys an app's
|
|
3
|
+
* copy lacks, the merge that keeps the app's values, and the other
|
|
4
|
+
* locales checked against the app's English copy.
|
|
5
|
+
*/
|
|
6
|
+
export type Json = Record<string, unknown>;
|
|
7
|
+
/** Dotted paths of every leaf in `registry` that `app` lacks. */
|
|
8
|
+
export declare function missingMessageKeys(registry: Json, app: Json, prefix?: string): string[];
|
|
9
|
+
/**
|
|
10
|
+
* The registry's messages with the app's copy laid over them: every key
|
|
11
|
+
* the registry has is present, every value the app set wins, and keys
|
|
12
|
+
* only the app has (its own nav entries, product copy) are kept.
|
|
13
|
+
*/
|
|
14
|
+
export declare function mergeMessages(registry: Json, app: Json): Json;
|
|
15
|
+
export declare const isMessages: (target: string) => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* The app's locales, from `locales: [...]` in i18n/routing.ts — the
|
|
18
|
+
* source locale alone when there is no such file or list.
|
|
19
|
+
*/
|
|
20
|
+
export declare function appLocales(appRoot: string): string[];
|
|
21
|
+
export type LocaleEntry = {
|
|
22
|
+
item: string;
|
|
23
|
+
path: string;
|
|
24
|
+
state: "current" | "locale-behind";
|
|
25
|
+
missingKeys?: string[];
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Every other locale's copy of the namespaces the registry ships,
|
|
29
|
+
* against the app's English file on disk — the merged copy, product
|
|
30
|
+
* keys included, which is what the other locales translate. A missing
|
|
31
|
+
* file lacks every key.
|
|
32
|
+
*/
|
|
33
|
+
export declare function localeEntries(appRoot: string, files: readonly {
|
|
34
|
+
item: string;
|
|
35
|
+
target: string;
|
|
36
|
+
}[]): LocaleEntry[];
|
|
37
|
+
//# sourceMappingURL=sync-messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-messages.d.ts","sourceRoot":"","sources":["../../src/commands/sync-messages.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAK3C,iEAAiE;AACjE,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,IAAI,EACd,GAAG,EAAE,IAAI,EACT,MAAM,SAAK,GACV,MAAM,EAAE,CASV;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,CAe7D;AAED,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,YACmB,CAAC;AAK7D;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQpD;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,GAAG,eAAe,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,GACjD,WAAW,EAAE,CAyBf"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message files under `intelligo sync`: the registry's keys an app's
|
|
3
|
+
* copy lacks, the merge that keeps the app's values, and the other
|
|
4
|
+
* locales checked against the app's English copy.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
const isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
9
|
+
/** Dotted paths of every leaf in `registry` that `app` lacks. */
|
|
10
|
+
export function missingMessageKeys(registry, app, prefix = "") {
|
|
11
|
+
return Object.entries(registry).flatMap(([key, value]) => {
|
|
12
|
+
const at = prefix ? `${prefix}.${key}` : key;
|
|
13
|
+
if (!(key in app))
|
|
14
|
+
return [at];
|
|
15
|
+
const mine = app[key];
|
|
16
|
+
return isObject(value) && isObject(mine)
|
|
17
|
+
? missingMessageKeys(value, mine, at)
|
|
18
|
+
: [];
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The registry's messages with the app's copy laid over them: every key
|
|
23
|
+
* the registry has is present, every value the app set wins, and keys
|
|
24
|
+
* only the app has (its own nav entries, product copy) are kept.
|
|
25
|
+
*/
|
|
26
|
+
export function mergeMessages(registry, app) {
|
|
27
|
+
const out = {};
|
|
28
|
+
for (const [key, value] of Object.entries(registry)) {
|
|
29
|
+
const mine = app[key];
|
|
30
|
+
out[key] =
|
|
31
|
+
key in app
|
|
32
|
+
? isObject(value) && isObject(mine)
|
|
33
|
+
? mergeMessages(value, mine)
|
|
34
|
+
: mine
|
|
35
|
+
: value;
|
|
36
|
+
}
|
|
37
|
+
for (const [key, value] of Object.entries(app)) {
|
|
38
|
+
if (!(key in out))
|
|
39
|
+
out[key] = value;
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
export const isMessages = (target) => target.startsWith("messages/") && target.endsWith(".json");
|
|
44
|
+
/** The locale the registry ships messages in. */
|
|
45
|
+
const SOURCE_LOCALE = "en";
|
|
46
|
+
/**
|
|
47
|
+
* The app's locales, from `locales: [...]` in i18n/routing.ts — the
|
|
48
|
+
* source locale alone when there is no such file or list.
|
|
49
|
+
*/
|
|
50
|
+
export function appLocales(appRoot) {
|
|
51
|
+
const file = path.join(appRoot, "i18n", "routing.ts");
|
|
52
|
+
if (!existsSync(file))
|
|
53
|
+
return [SOURCE_LOCALE];
|
|
54
|
+
const list = /\blocales\s*:\s*\[([^\]]*)\]/.exec(readFileSync(file, "utf8"));
|
|
55
|
+
const locales = [...(list?.[1] ?? "").matchAll(/["'`]([^"'`]+)["'`]/g)].map((m) => m[1]);
|
|
56
|
+
return locales.length > 0 ? locales : [SOURCE_LOCALE];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Every other locale's copy of the namespaces the registry ships,
|
|
60
|
+
* against the app's English file on disk — the merged copy, product
|
|
61
|
+
* keys included, which is what the other locales translate. A missing
|
|
62
|
+
* file lacks every key.
|
|
63
|
+
*/
|
|
64
|
+
export function localeEntries(appRoot, files) {
|
|
65
|
+
const others = appLocales(appRoot).filter((l) => l !== SOURCE_LOCALE);
|
|
66
|
+
if (others.length === 0)
|
|
67
|
+
return [];
|
|
68
|
+
const prefix = `messages/${SOURCE_LOCALE}/`;
|
|
69
|
+
const entries = [];
|
|
70
|
+
for (const { item, target } of files) {
|
|
71
|
+
if (!target.startsWith(prefix) || !target.endsWith(".json"))
|
|
72
|
+
continue;
|
|
73
|
+
const english = path.join(appRoot, target);
|
|
74
|
+
if (!existsSync(english))
|
|
75
|
+
continue;
|
|
76
|
+
const source = JSON.parse(readFileSync(english, "utf8"));
|
|
77
|
+
for (const locale of others) {
|
|
78
|
+
const rel = `messages/${locale}/${target.slice(prefix.length)}`;
|
|
79
|
+
const abs = path.join(appRoot, rel);
|
|
80
|
+
const missingKeys = missingMessageKeys(source, existsSync(abs) ? JSON.parse(readFileSync(abs, "utf8")) : {});
|
|
81
|
+
entries.push(missingKeys.length > 0
|
|
82
|
+
? { item, path: rel, state: "locale-behind", missingKeys }
|
|
83
|
+
: { item, path: rel, state: "current" });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return entries;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=sync-messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-messages.js","sourceRoot":"","sources":["../../src/commands/sync-messages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffold files a registry install replaces. `intelligo create`
|
|
3
|
+
* writes app/globals.css, the theme provider and lib/utils.ts; the
|
|
4
|
+
* design-system base and the items overwrite them, and the scaffold's
|
|
5
|
+
* record has to let go of them or `upgrade --check` reports them as
|
|
6
|
+
* the app's own edits forever.
|
|
7
|
+
*/
|
|
8
|
+
/** The `intelligo create` feature whose files an install may replace. */
|
|
9
|
+
export declare const SCAFFOLD_FEATURE = "app-scaffold";
|
|
10
|
+
/**
|
|
11
|
+
* The scaffold files an install has made the registry's: a file an
|
|
12
|
+
* installed item ships, the Tailwind stylesheet once the design-system
|
|
13
|
+
* base is in (it rewrites the tokens), or any scaffold file the install
|
|
14
|
+
* changed (shadcn's own `utils`, `sonner`). Seams stay the app's, and
|
|
15
|
+
* so do the files shadcn only extends. Left in the scaffold's record,
|
|
16
|
+
* each would read `customized` in `upgrade --check` forever.
|
|
17
|
+
*/
|
|
18
|
+
export declare function scaffoldHandover(input: {
|
|
19
|
+
scaffold: readonly string[];
|
|
20
|
+
changed: ReadonlySet<string>;
|
|
21
|
+
shipped: ReadonlySet<string>;
|
|
22
|
+
seams: Readonly<Record<string, string>>;
|
|
23
|
+
css: string | null;
|
|
24
|
+
}): string[];
|
|
25
|
+
/**
|
|
26
|
+
* The scaffold's recorded files as they are before an install, and
|
|
27
|
+
* afterwards the ones the install made the registry's.
|
|
28
|
+
*/
|
|
29
|
+
export declare function snapshotScaffold(appRoot: string): {
|
|
30
|
+
handedOver: (input: {
|
|
31
|
+
shipped: ReadonlySet<string>;
|
|
32
|
+
seams: Readonly<Record<string, string>>;
|
|
33
|
+
css: string | null;
|
|
34
|
+
}) => string[];
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=sync-scaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-scaffold.d.ts","sourceRoot":"","sources":["../../src/commands/sync-scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAY/C;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7B,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB,GAAG,MAAM,EAAE,CAOX;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IACjD,UAAU,EAAE,CAAC,KAAK,EAAE;QAClB,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAC7B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACxC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;KACpB,KAAK,MAAM,EAAE,CAAC;CAChB,CAmBA"}
|