@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$1(output) {
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$1(result.stdout) === pin) return candidate;
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
- /** A Postgres SQLSTATE: five characters, digits and capitals. Connection errors (`ECONNREFUSED`) are not. */
7240
- function isSqlState(code) {
7241
- return typeof code === "string" && /^[0-9A-Z]{5}$/.test(code);
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 (!isSqlState(err?.code)) throw err;
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-CJtevyVy.js");
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.547",
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/sdk": "0.1.0",
51
- "@devdogsuga/config": "0.1.4-next.526"
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",