@devdogsuga/devtools 0.1.51-next.547 → 0.1.51-next.549
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.
|
@@ -7058,7 +7058,7 @@ function commandLine(command, args) {
|
|
|
7058
7058
|
function cliLine(cli, args) {
|
|
7059
7059
|
return commandLine(cli.command, [...cli.prefix, ...args]);
|
|
7060
7060
|
}
|
|
7061
|
-
function versionOf
|
|
7061
|
+
function versionOf(output) {
|
|
7062
7062
|
return /\b(\d+\.\d+\.\d+)\b/.exec(output)?.[1] ?? null;
|
|
7063
7063
|
}
|
|
7064
7064
|
async function resolveSupabaseCli(root, pin, run, fileExists = existsSync) {
|
|
@@ -7076,7 +7076,7 @@ async function resolveSupabaseCli(root, pin, run, fileExists = existsSync) {
|
|
|
7076
7076
|
});
|
|
7077
7077
|
for (const candidate of candidates) try {
|
|
7078
7078
|
const result = await run(candidate.command, ["--version"], { cwd: root });
|
|
7079
|
-
if (result.code === 0 && versionOf
|
|
7079
|
+
if (result.code === 0 && versionOf(result.stdout) === pin) return candidate;
|
|
7080
7080
|
} catch {}
|
|
7081
7081
|
try {
|
|
7082
7082
|
if ((await run("pnpm", ["--version"], { cwd: root })).code === 0) return {
|
|
@@ -7236,9 +7236,18 @@ var DevDataError = class extends Error {
|
|
|
7236
7236
|
this.name = "DevDataError";
|
|
7237
7237
|
}
|
|
7238
7238
|
};
|
|
7239
|
-
/**
|
|
7240
|
-
|
|
7241
|
-
|
|
7239
|
+
/**
|
|
7240
|
+
* Whether `err` is the product's own SQL being wrong: a Postgres error whose
|
|
7241
|
+
* SQLSTATE class is a cardinality violation (21), data exception (22),
|
|
7242
|
+
* integrity constraint violation (23) or syntax error or access rule
|
|
7243
|
+
* violation (42). Everything else is not the file's fault and reports as a
|
|
7244
|
+
* normal failure: a refused or dropped connection (class 08 and
|
|
7245
|
+
* `ECONNREFUSED`), an operator shutdown (57, `admin_shutdown`), a server out
|
|
7246
|
+
* of resources (53), a transaction that was rolled back (40), and so on.
|
|
7247
|
+
*/
|
|
7248
|
+
function isSqlFileError(err) {
|
|
7249
|
+
const code = err?.code;
|
|
7250
|
+
return typeof code === "string" && /^(21|22|23|42)[0-9A-Z]{3}$/.test(code);
|
|
7242
7251
|
}
|
|
7243
7252
|
/**
|
|
7244
7253
|
* The line of `text` a Postgres error points at, from the error's 1-based
|
|
@@ -7294,6 +7303,11 @@ function postgresSession(dbUrl) {
|
|
|
7294
7303
|
const present = new Set(rows.map((r) => r.nspname));
|
|
7295
7304
|
return schemas.filter((name) => !present.has(name));
|
|
7296
7305
|
},
|
|
7306
|
+
async exec(text) {
|
|
7307
|
+
await sql.begin(async (tx) => {
|
|
7308
|
+
await tx.unsafe(text);
|
|
7309
|
+
});
|
|
7310
|
+
},
|
|
7297
7311
|
async runAs(memberId, text) {
|
|
7298
7312
|
await sql.begin(async (tx) => {
|
|
7299
7313
|
await tx`select set_config('devtools.member_id', ${memberId}, true)`;
|
|
@@ -7335,7 +7349,7 @@ async function seed(session, file, text, options, log) {
|
|
|
7335
7349
|
try {
|
|
7336
7350
|
await session.runAs(member.id, text);
|
|
7337
7351
|
} catch (err) {
|
|
7338
|
-
if (!
|
|
7352
|
+
if (!isSqlFileError(err)) throw err;
|
|
7339
7353
|
const line = errorLine(err, text);
|
|
7340
7354
|
throw new DevDataError(`${file}${line === null ? "" : `:${line}`}: ${err.message}. This is a problem in the product's dev-data SQL, not in devtools; nothing was seeded (the file runs in one transaction).`);
|
|
7341
7355
|
}
|
|
@@ -7646,7 +7660,6 @@ async function dbSync(product, cli, target, run, options) {
|
|
|
7646
7660
|
const restored = migrationFiles(migrationsDir).length;
|
|
7647
7661
|
if (fetched.code === 0 && restored > 0) log(`Restored ${restored} applied migration${restored === 1 ? "" : "s"} from the project's history.`);
|
|
7648
7662
|
}
|
|
7649
|
-
await reconcileRecord(product, cli, target, run, options, log);
|
|
7650
7663
|
const before = new Set(migrationFiles(migrationsDir));
|
|
7651
7664
|
let generated = await run(cli.command, generateArgs, { cwd: product.root });
|
|
7652
7665
|
if (generated.code !== 0 && isContainerFailure(generated)) {
|
|
@@ -7697,70 +7710,6 @@ async function dbSync(product, cli, target, run, options) {
|
|
|
7697
7710
|
destructive
|
|
7698
7711
|
};
|
|
7699
7712
|
}
|
|
7700
|
-
/** `20261011120000` from `20261011120000_devtools_sync.sql`. */
|
|
7701
|
-
function versionOf(file) {
|
|
7702
|
-
return file.split("_")[0] ?? file;
|
|
7703
|
-
}
|
|
7704
|
-
/**
|
|
7705
|
-
* Makes the local record agree with the database. The declarative diff only
|
|
7706
|
-
* compares `supabase/schemas` with `supabase/migrations`, so a database that
|
|
7707
|
-
* lost its contents behind the record's back (a hosted project reset from the
|
|
7708
|
-
* dashboard, a checkout switched from the local stack to a hosted project)
|
|
7709
|
-
* would read as "already matches". This asks the target:
|
|
7710
|
-
*
|
|
7711
|
-
* - a migration in the record that is not in the database's ledger was never
|
|
7712
|
-
* applied there: it is dropped from the record, so the diff re-creates it;
|
|
7713
|
-
* - a configured schema that does not exist means the ledger is stale too:
|
|
7714
|
-
* its entries are reverted and the whole record dropped, so the diff
|
|
7715
|
-
* writes the full schema again.
|
|
7716
|
-
*
|
|
7717
|
-
* Nothing is reset or dropped in the database; only ledger rows of schemas
|
|
7718
|
-
* that are already gone are removed. A database that cannot be reached is
|
|
7719
|
-
* left to the apply step to report.
|
|
7720
|
-
*/
|
|
7721
|
-
async function reconcileRecord(product, cli, target, run, options, log) {
|
|
7722
|
-
if (!options.open) return;
|
|
7723
|
-
const { migrationsDir } = product.paths;
|
|
7724
|
-
const files = migrationFiles(migrationsDir);
|
|
7725
|
-
let ledger;
|
|
7726
|
-
let missing;
|
|
7727
|
-
let session;
|
|
7728
|
-
try {
|
|
7729
|
-
session = options.open(target.dbUrl);
|
|
7730
|
-
ledger = await session.appliedMigrations();
|
|
7731
|
-
missing = await session.missingSchemas(product.config.supabase.schemas);
|
|
7732
|
-
} catch (err) {
|
|
7733
|
-
log(`Could not check what the database has applied (${err.message}); trusting the local record.`);
|
|
7734
|
-
return;
|
|
7735
|
-
} finally {
|
|
7736
|
-
await session?.close().catch(() => void 0);
|
|
7737
|
-
}
|
|
7738
|
-
if (missing.length > 0) {
|
|
7739
|
-
const stale = ledger ?? [];
|
|
7740
|
-
log(`The database is missing ${missing.length === 1 ? "schema" : "schemas"} ${missing.join(", ")}, so the record of applied migrations is out of date; rebuilding it from supabase/schemas.`);
|
|
7741
|
-
if (stale.length > 0) {
|
|
7742
|
-
const reverted = await run(cli.command, [
|
|
7743
|
-
...cli.prefix,
|
|
7744
|
-
"migration",
|
|
7745
|
-
"repair",
|
|
7746
|
-
"--status",
|
|
7747
|
-
"reverted",
|
|
7748
|
-
"--db-url",
|
|
7749
|
-
target.dbUrl,
|
|
7750
|
-
...stale
|
|
7751
|
-
], { cwd: product.root });
|
|
7752
|
-
if (reverted.code !== 0) throw new SyncError("The database lost its schema but its migration history still lists migrations as applied, and clearing that history failed.", reverted.stderr || reverted.stdout);
|
|
7753
|
-
}
|
|
7754
|
-
for (const file of files) rmSync(join(migrationsDir, file));
|
|
7755
|
-
return;
|
|
7756
|
-
}
|
|
7757
|
-
const applied = new Set(ledger ?? []);
|
|
7758
|
-
const unapplied = files.filter((file) => !applied.has(versionOf(file)));
|
|
7759
|
-
if (unapplied.length > 0) {
|
|
7760
|
-
log(`${unapplied.length} migration${unapplied.length === 1 ? "" : "s"} in the local record ${unapplied.length === 1 ? "is" : "are"} not in this database's history (it was reset, or this checkout switched databases); re-applying ${unapplied.length === 1 ? "it" : "them"}.`);
|
|
7761
|
-
for (const file of unapplied) rmSync(join(migrationsDir, file));
|
|
7762
|
-
}
|
|
7763
|
-
}
|
|
7764
7713
|
function isContainerFailure(result) {
|
|
7765
7714
|
return /docker|container|image/i.test(result.stderr + result.stdout);
|
|
7766
7715
|
}
|
|
@@ -8023,8 +7972,7 @@ async function runSync(product, deps, rest) {
|
|
|
8023
7972
|
yes: hasYes(rest),
|
|
8024
7973
|
confirmDestructive: deps.interactive() ? confirmDestructive : void 0,
|
|
8025
7974
|
dryRun,
|
|
8026
|
-
log: (line) => log.info(line)
|
|
8027
|
-
open: deps.openSql
|
|
7975
|
+
log: (line) => log.info(line)
|
|
8028
7976
|
});
|
|
8029
7977
|
if (rest.includes("--rebuild") && !dryRun) try {
|
|
8030
7978
|
const row = await reRegisterSavedProvider(product.paths.toolingFile, target);
|
|
@@ -8325,8 +8273,7 @@ async function runSetup(product, deps, rest) {
|
|
|
8325
8273
|
const result = await dbSync(product, cli, target, deps.run, {
|
|
8326
8274
|
yes: hasYes(rest),
|
|
8327
8275
|
confirmDestructive: deps.interactive() ? confirmDestructive : void 0,
|
|
8328
|
-
log: (line) => log.info(line)
|
|
8329
|
-
open: deps.openSql
|
|
8276
|
+
log: (line) => log.info(line)
|
|
8330
8277
|
});
|
|
8331
8278
|
log.success(result.migration ? "Applied supabase/schemas to your database." : "Your database already matched supabase/schemas.");
|
|
8332
8279
|
if (target.kind === "local") await waitForRest(target, deps, product);
|
package/dist/launch.js
CHANGED
|
@@ -183,7 +183,7 @@ async function startStack() {
|
|
|
183
183
|
* post-tier-resolution path.
|
|
184
184
|
*/
|
|
185
185
|
async function dispatch(argv) {
|
|
186
|
-
const { main } = await import("./cli-
|
|
186
|
+
const { main } = await import("./cli-Doy2BzCQ.js");
|
|
187
187
|
try {
|
|
188
188
|
await main(argv);
|
|
189
189
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devdogsuga/devtools",
|
|
3
|
-
"version": "0.1.51-next.
|
|
3
|
+
"version": "0.1.51-next.549",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Contributor CLI for DevDogs repositories (the platform monorepo, DogDays, DogPack): the real tools with the session's tier filled in, `setup`, `db sync`, `db types`, `dev-data`, a menu over them, the checks CI runs, and the `with-env` launcher. Ships built JS; run via `pnpm devtools` in a product repo, `pnpm dlx @devdogsuga/devtools` (or the `devtools` bin once installed) from inside a clone.",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"tsdown": "^0.23.0",
|
|
48
48
|
"vitest": "^4.1.11",
|
|
49
49
|
"@devdogsuga/cli-core": "0.0.0",
|
|
50
|
-
"@devdogsuga/
|
|
51
|
-
"@devdogsuga/
|
|
50
|
+
"@devdogsuga/config": "0.1.4-next.526",
|
|
51
|
+
"@devdogsuga/sdk": "0.1.0"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "tsdown && node scripts/write-build-info.mjs && node ../../scripts/check-bundle-imports.mjs",
|