@devdogsuga/devtools 0.1.51-next.544 → 0.1.51-next.547
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/README.md +6 -3
- package/dist/{cli-D98LfCHU.js → cli-CJtevyVy.js} +148 -33
- package/dist/launch.js +8 -7
- package/dist/{load-yn7JCcS2.js → load-aeN4iX1h.js} +1 -1
- package/dist/{load-Z2CXCpyx.js → load-lrgJ5Kz7.js} +1 -1
- package/dist/{menu-oQE5IqAI.js → menu-CZK0L1Vf.js} +3 -3
- package/dist/{root-DfH38DFq.js → root-IVsv7i8N.js} +1 -1
- package/dist/{root-PA8K5G2d.js → root-RaJ8ECCO.js} +13 -1
- package/dist/{run-CRBte7p0.js → run-D5iI9zve.js} +3 -3
- package/dist/{session-DzgtIg6K.js → session-DdF8eqv3.js} +1 -1
- package/dist/{session-CuexI1f9.js → session-bPPOkolU.js} +1 -1
- package/dist/{stack-BRevXgI3.js → stack-CzNe6rxl.js} +1 -1
- package/dist/stack-VZ-1SmuM.js +2 -0
- package/dist/{telemetry-BDTAGquh.js → telemetry-BDOwjuoC.js} +4 -3
- package/dist/telemetry.js +1 -1
- package/dist/with-env.js +2 -2
- package/package.json +2 -2
- package/dist/stack-Cl_B_dt7.js +0 -2
package/README.md
CHANGED
|
@@ -97,12 +97,15 @@ name `devdogs-monorepo` or `backstage`; the layout code is
|
|
|
97
97
|
|
|
98
98
|
A repository with a `devtools.config.json` at its root is a **product** (DogDays, DogPack): devtools
|
|
99
99
|
reads the file and serves a smaller command set that needs no tiers, no env registry and no workspace.
|
|
100
|
-
|
|
100
|
+
Both products carry a `package.json` whose `devtools` script is a `pnpm dlx` run of the published CLI, so
|
|
101
|
+
inside a checkout:
|
|
101
102
|
|
|
102
103
|
```sh
|
|
103
|
-
|
|
104
|
+
pnpm devtools setup
|
|
104
105
|
```
|
|
105
106
|
|
|
107
|
+
Anywhere else, the one-off form is `pnpm dlx @devdogsuga/devtools@next setup`.
|
|
108
|
+
|
|
106
109
|
| Command | What it does |
|
|
107
110
|
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
108
111
|
| `setup [--local \| --hosted]` | Writes `.env` from `.env.example`; starts the Docker stack (or takes your own hosted project's URL, keys and session-pooler `DB_URL`); `db sync`; the types; then `oauth`. |
|
|
@@ -136,7 +139,7 @@ How it works, in short:
|
|
|
136
139
|
`oauth` (the tooling file) check that they are git-ignored and add them to the repo's `.gitignore`
|
|
137
140
|
when they are not (Flutter's default ignore file leaves them out).
|
|
138
141
|
- **The pinned CLI.** devtools finds `supabase` in `node_modules/.bin` or on PATH when its version is the
|
|
139
|
-
pin, and otherwise runs `npx --yes supabase@<pin
|
|
142
|
+
pin, and otherwise runs `pnpm dlx supabase@<pin>` (`npx --yes supabase@<pin>` only when pnpm is not on PATH).
|
|
140
143
|
- **A hosted project** needs custom OAuth providers turned on and the app's return addresses allowed.
|
|
141
144
|
`setup` does both through the Management API when `SUPABASE_ACCESS_TOKEN` is set, and prints the two
|
|
142
145
|
dashboard steps when it is not.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as execSync, r as spawnProcess } from "./spawn-BvLQzc_K.js";
|
|
2
|
-
import { n as discoverRepoRoot, r as findRepoRoot } from "./root-
|
|
3
|
-
import { A as findApp, M as listApps, N as resolveAppPath, O as appWorkspaceRoot, P as resolveLayout, _ as dryRunKind, c as supabaseRoot, d as loadEnvLoad, f as loadEnvSession, g as runInGroup, h as reportRan, i as runWithStderr, j as layoutAt, k as devdogsugaRootOrNull, l as getEnvSync, n as reportRuns, o as supabase, p as repoPeerUrl, r as run$1, t as dbPush, u as loadEnv, v as isDryRun, x as wouldRunLine } from "./run-
|
|
4
|
-
import { A as renderHelp, C as loadProductConfig, D as catalog, M as probeEnvironment, O as helpPath, T as isProductMode, _ as explain, a as recordEnteredTier, b as ProductConfigError, c as nonEmpty, d as sessionLabel, g as errorMessage, h as bail, i as beginInvocation, j as describeEnvironment, k as renderCommandList, l as resolveDbConnection, n as bareGroupStartPath, o as recordResolved, r as runMenu, s as reproducibleCommand, t as bareGroupStartFlags, u as sessionIsLocal, v as explainError, w as activeCatalog, x as currentProduct, y as unwrap } from "./menu-
|
|
2
|
+
import { n as discoverRepoRoot, r as findRepoRoot } from "./root-RaJ8ECCO.js";
|
|
3
|
+
import { A as findApp, M as listApps, N as resolveAppPath, O as appWorkspaceRoot, P as resolveLayout, _ as dryRunKind, c as supabaseRoot, d as loadEnvLoad, f as loadEnvSession, g as runInGroup, h as reportRan, i as runWithStderr, j as layoutAt, k as devdogsugaRootOrNull, l as getEnvSync, n as reportRuns, o as supabase, p as repoPeerUrl, r as run$1, t as dbPush, u as loadEnv, v as isDryRun, x as wouldRunLine } from "./run-D5iI9zve.js";
|
|
4
|
+
import { A as renderHelp, C as loadProductConfig, D as catalog, M as probeEnvironment, O as helpPath, T as isProductMode, _ as explain, a as recordEnteredTier, b as ProductConfigError, c as nonEmpty, d as sessionLabel, g as errorMessage, h as bail, i as beginInvocation, j as describeEnvironment, k as renderCommandList, l as resolveDbConnection, n as bareGroupStartPath, o as recordResolved, r as runMenu, s as reproducibleCommand, t as bareGroupStartFlags, u as sessionIsLocal, v as explainError, w as activeCatalog, x as currentProduct, y as unwrap } from "./menu-CZK0L1Vf.js";
|
|
5
5
|
import { a as isVersionRequest, c as cliName, m as positionals, o as ownPackageDir, p as flagValue, s as ownVersion } from "./failure-log-MSdCgvLc.js";
|
|
6
|
-
import { f as hasYes, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive } from "./telemetry-
|
|
7
|
-
import { t as runStackCommand } from "./stack-
|
|
6
|
+
import { f as hasYes, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive } from "./telemetry-BDOwjuoC.js";
|
|
7
|
+
import { t as runStackCommand } from "./stack-CzNe6rxl.js";
|
|
8
8
|
import { register } from "node:module";
|
|
9
9
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
@@ -4920,7 +4920,7 @@ function productPin(cwd) {
|
|
|
4920
4920
|
* a sibling project, where the Supabase CLI is normally installed globally;
|
|
4921
4921
|
* this monorepo, where it is a workspace devDependency and not on PATH at all;
|
|
4922
4922
|
* and a product repo (`devtools.config.json`), where `devtools setup` ran the
|
|
4923
|
-
* pinned CLI through `
|
|
4923
|
+
* pinned CLI through `pnpm dlx` and a new member has none installed. A global install
|
|
4924
4924
|
* wins, since `pnpm exec` in a non-pnpm project would fail for reasons that have
|
|
4925
4925
|
* nothing to do with Supabase.
|
|
4926
4926
|
*/
|
|
@@ -4942,19 +4942,32 @@ function detectLocalSupabase(cwd) {
|
|
|
4942
4942
|
...status
|
|
4943
4943
|
]];
|
|
4944
4944
|
const pin = productPin(cwd);
|
|
4945
|
-
if (pin !== null)
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4945
|
+
if (pin !== null) {
|
|
4946
|
+
attempts.push([
|
|
4947
|
+
"pnpm",
|
|
4948
|
+
"dlx",
|
|
4949
|
+
`supabase@${pin}`,
|
|
4950
|
+
...status
|
|
4951
|
+
]);
|
|
4952
|
+
attempts.push([
|
|
4953
|
+
"npx",
|
|
4954
|
+
"--yes",
|
|
4955
|
+
`supabase@${pin}`,
|
|
4956
|
+
...status
|
|
4957
|
+
]);
|
|
4958
|
+
}
|
|
4951
4959
|
let output;
|
|
4952
4960
|
let first;
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4961
|
+
let pnpmMissing = false;
|
|
4962
|
+
for (const argv of attempts) {
|
|
4963
|
+
if (argv[0] === "npx" && !pnpmMissing) continue;
|
|
4964
|
+
try {
|
|
4965
|
+
output = runStatus(argv, cwd);
|
|
4966
|
+
break;
|
|
4967
|
+
} catch (error) {
|
|
4968
|
+
first ??= error;
|
|
4969
|
+
if (argv[0] === "pnpm" && error.code === "ENOENT") pnpmMissing = true;
|
|
4970
|
+
}
|
|
4958
4971
|
}
|
|
4959
4972
|
if (output === void 0) {
|
|
4960
4973
|
if (first.code === "ENOENT") throw new Error("supabase CLI not found — install it from https://supabase.com/docs/guides/cli");
|
|
@@ -7034,7 +7047,9 @@ function commandLine(command, args) {
|
|
|
7034
7047
|
*
|
|
7035
7048
|
* 1. `node_modules/.bin/supabase` in the repo, when its version is the pin;
|
|
7036
7049
|
* 2. a `supabase` on PATH whose version is the pin;
|
|
7037
|
-
* 3. `
|
|
7050
|
+
* 3. `pnpm dlx supabase@<pin>`, which downloads and caches the right one.
|
|
7051
|
+
* Members are expected to have pnpm (both product repos pin it);
|
|
7052
|
+
* 4. `npx --yes supabase@<pin>`, only when pnpm is not on PATH.
|
|
7038
7053
|
*
|
|
7039
7054
|
* The pin is also part of the generated-types hash, so a contributor on a
|
|
7040
7055
|
* different CLI would generate different types than CI; matching it is not
|
|
@@ -7043,7 +7058,7 @@ function commandLine(command, args) {
|
|
|
7043
7058
|
function cliLine(cli, args) {
|
|
7044
7059
|
return commandLine(cli.command, [...cli.prefix, ...args]);
|
|
7045
7060
|
}
|
|
7046
|
-
function versionOf(output) {
|
|
7061
|
+
function versionOf$1(output) {
|
|
7047
7062
|
return /\b(\d+\.\d+\.\d+)\b/.exec(output)?.[1] ?? null;
|
|
7048
7063
|
}
|
|
7049
7064
|
async function resolveSupabaseCli(root, pin, run, fileExists = existsSync) {
|
|
@@ -7061,7 +7076,14 @@ async function resolveSupabaseCli(root, pin, run, fileExists = existsSync) {
|
|
|
7061
7076
|
});
|
|
7062
7077
|
for (const candidate of candidates) try {
|
|
7063
7078
|
const result = await run(candidate.command, ["--version"], { cwd: root });
|
|
7064
|
-
if (result.code === 0 && versionOf(result.stdout) === pin) return candidate;
|
|
7079
|
+
if (result.code === 0 && versionOf$1(result.stdout) === pin) return candidate;
|
|
7080
|
+
} catch {}
|
|
7081
|
+
try {
|
|
7082
|
+
if ((await run("pnpm", ["--version"], { cwd: root })).code === 0) return {
|
|
7083
|
+
command: "pnpm",
|
|
7084
|
+
prefix: ["dlx", `supabase@${pin}`],
|
|
7085
|
+
source: "pnpm"
|
|
7086
|
+
};
|
|
7065
7087
|
} catch {}
|
|
7066
7088
|
return {
|
|
7067
7089
|
command: "npx",
|
|
@@ -7207,19 +7229,27 @@ async function resolveTarget(product, cli, run, preference) {
|
|
|
7207
7229
|
* project, and the SQL runs in one transaction.
|
|
7208
7230
|
*/
|
|
7209
7231
|
var DevDataError = class extends Error {
|
|
7232
|
+
/** A failure the contributor or the product's SQL caused, not a devtools bug: never sent to Sentry. */
|
|
7233
|
+
expected = true;
|
|
7210
7234
|
constructor(message) {
|
|
7211
7235
|
super(message);
|
|
7212
7236
|
this.name = "DevDataError";
|
|
7213
7237
|
}
|
|
7214
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);
|
|
7242
|
+
}
|
|
7215
7243
|
/**
|
|
7216
|
-
*
|
|
7217
|
-
*
|
|
7218
|
-
* has not had the product's schema applied yet.
|
|
7244
|
+
* The line of `text` a Postgres error points at, from the error's 1-based
|
|
7245
|
+
* character `position`, or null when it carries none.
|
|
7219
7246
|
*/
|
|
7220
|
-
function
|
|
7221
|
-
const
|
|
7222
|
-
|
|
7247
|
+
function errorLine(err, text) {
|
|
7248
|
+
const raw = err?.position;
|
|
7249
|
+
const position = typeof raw === "string" ? Number(raw) : raw;
|
|
7250
|
+
if (typeof position !== "number" || !Number.isInteger(position)) return null;
|
|
7251
|
+
if (position < 1 || position > text.length + 1) return null;
|
|
7252
|
+
return text.slice(0, position - 1).split("\n").length;
|
|
7223
7253
|
}
|
|
7224
7254
|
function postgresSession(dbUrl) {
|
|
7225
7255
|
const sql = postgres(dbUrl, {
|
|
@@ -7251,6 +7281,19 @@ function postgresSession(dbUrl) {
|
|
|
7251
7281
|
lastSignInAt: row.last_sign_in_at?.toISOString() ?? null
|
|
7252
7282
|
} : null;
|
|
7253
7283
|
},
|
|
7284
|
+
async appliedMigrations() {
|
|
7285
|
+
const [table] = await sql`
|
|
7286
|
+
select to_regclass('supabase_migrations.schema_migrations')::text as present`;
|
|
7287
|
+
if (!table?.present) return null;
|
|
7288
|
+
return (await sql`
|
|
7289
|
+
select version from supabase_migrations.schema_migrations`).map((r) => r.version);
|
|
7290
|
+
},
|
|
7291
|
+
async missingSchemas(schemas) {
|
|
7292
|
+
const rows = await sql`
|
|
7293
|
+
select nspname from pg_namespace where nspname = any(${[...schemas]})`;
|
|
7294
|
+
const present = new Set(rows.map((r) => r.nspname));
|
|
7295
|
+
return schemas.filter((name) => !present.has(name));
|
|
7296
|
+
},
|
|
7254
7297
|
async runAs(memberId, text) {
|
|
7255
7298
|
await sql.begin(async (tx) => {
|
|
7256
7299
|
await tx`select set_config('devtools.member_id', ${memberId}, true)`;
|
|
@@ -7274,10 +7317,9 @@ async function runDevData(product, target, open, options) {
|
|
|
7274
7317
|
const text = readFileSync(file, "utf8");
|
|
7275
7318
|
const session = open(target.dbUrl);
|
|
7276
7319
|
try {
|
|
7320
|
+
const missing = await session.missingSchemas(product.config.supabase.schemas);
|
|
7321
|
+
if (missing.length > 0) throw new DevDataError(`This database does not have ${product.config.name}'s ${missing.length === 1 ? "schema" : "schemas"} yet (missing: ${missing.join(", ")}). Run \`devtools setup\` first, or \`devtools db sync\` if you have already set up.`);
|
|
7277
7322
|
return await seed(session, devData.file, text, options, log);
|
|
7278
|
-
} catch (err) {
|
|
7279
|
-
if (isMissingSchemaError(err)) throw new DevDataError(`This database does not have ${product.config.name}'s tables yet (${err.message}). Run \`devtools setup\` first, or \`devtools db sync\` if you have already set up.`);
|
|
7280
|
-
throw err;
|
|
7281
7323
|
} finally {
|
|
7282
7324
|
await session.close();
|
|
7283
7325
|
}
|
|
@@ -7290,7 +7332,13 @@ async function seed(session, file, text, options, log) {
|
|
|
7290
7332
|
log(`Would run ${file} (${text.split("\n").length} lines) in one transaction.`);
|
|
7291
7333
|
return null;
|
|
7292
7334
|
}
|
|
7293
|
-
|
|
7335
|
+
try {
|
|
7336
|
+
await session.runAs(member.id, text);
|
|
7337
|
+
} catch (err) {
|
|
7338
|
+
if (!isSqlState(err?.code)) throw err;
|
|
7339
|
+
const line = errorLine(err, text);
|
|
7340
|
+
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
|
+
}
|
|
7294
7342
|
return {
|
|
7295
7343
|
member,
|
|
7296
7344
|
file
|
|
@@ -7598,6 +7646,7 @@ async function dbSync(product, cli, target, run, options) {
|
|
|
7598
7646
|
const restored = migrationFiles(migrationsDir).length;
|
|
7599
7647
|
if (fetched.code === 0 && restored > 0) log(`Restored ${restored} applied migration${restored === 1 ? "" : "s"} from the project's history.`);
|
|
7600
7648
|
}
|
|
7649
|
+
await reconcileRecord(product, cli, target, run, options, log);
|
|
7601
7650
|
const before = new Set(migrationFiles(migrationsDir));
|
|
7602
7651
|
let generated = await run(cli.command, generateArgs, { cwd: product.root });
|
|
7603
7652
|
if (generated.code !== 0 && isContainerFailure(generated)) {
|
|
@@ -7648,6 +7697,70 @@ async function dbSync(product, cli, target, run, options) {
|
|
|
7648
7697
|
destructive
|
|
7649
7698
|
};
|
|
7650
7699
|
}
|
|
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
|
+
}
|
|
7651
7764
|
function isContainerFailure(result) {
|
|
7652
7765
|
return /docker|container|image/i.test(result.stderr + result.stdout);
|
|
7653
7766
|
}
|
|
@@ -7910,7 +8023,8 @@ async function runSync(product, deps, rest) {
|
|
|
7910
8023
|
yes: hasYes(rest),
|
|
7911
8024
|
confirmDestructive: deps.interactive() ? confirmDestructive : void 0,
|
|
7912
8025
|
dryRun,
|
|
7913
|
-
log: (line) => log.info(line)
|
|
8026
|
+
log: (line) => log.info(line),
|
|
8027
|
+
open: deps.openSql
|
|
7914
8028
|
});
|
|
7915
8029
|
if (rest.includes("--rebuild") && !dryRun) try {
|
|
7916
8030
|
const row = await reRegisterSavedProvider(product.paths.toolingFile, target);
|
|
@@ -8051,7 +8165,7 @@ async function runDoctor(product, deps) {
|
|
|
8051
8165
|
const info = (message) => void lines.push(`INFO ${message}`);
|
|
8052
8166
|
ok(`${product.config.name} (${product.config.product}), Supabase CLI pinned at ${product.config.supabase.version}`);
|
|
8053
8167
|
const cli = await cliFor(product, deps);
|
|
8054
|
-
if (cli.source === "npx") info(`The pinned Supabase CLI is fetched with
|
|
8168
|
+
if (cli.source === "pnpm" || cli.source === "npx") info(`The pinned Supabase CLI is fetched with ${cli.command} on first use (${cliLine(cli, ["--version"])}).`);
|
|
8055
8169
|
else ok(`Supabase CLI ${product.config.supabase.version} (${cli.source})`);
|
|
8056
8170
|
const docker = await deps.run("docker", [
|
|
8057
8171
|
"info",
|
|
@@ -8211,7 +8325,8 @@ async function runSetup(product, deps, rest) {
|
|
|
8211
8325
|
const result = await dbSync(product, cli, target, deps.run, {
|
|
8212
8326
|
yes: hasYes(rest),
|
|
8213
8327
|
confirmDestructive: deps.interactive() ? confirmDestructive : void 0,
|
|
8214
|
-
log: (line) => log.info(line)
|
|
8328
|
+
log: (line) => log.info(line),
|
|
8329
|
+
open: deps.openSql
|
|
8215
8330
|
});
|
|
8216
8331
|
log.success(result.migration ? "Applied supabase/schemas to your database." : "Your database already matched supabase/schemas.");
|
|
8217
8332
|
if (target.kind === "local") await waitForRest(target, deps, product);
|
package/dist/launch.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as discoverRepoRoot, r as findRepoRoot, t as RepoNotFoundError } from "./root-
|
|
2
|
-
import { b as setDryRun, d as loadEnvLoad, f as loadEnvSession, m as formatCommand, v as isDryRun, y as resolveDryRun } from "./run-
|
|
3
|
-
import { D as catalog, E as setProductMode, N as setEnvironmentRoot, O as helpPath, S as findProductRoot, c as nonEmpty, f as enterSessionEnvironment, g as errorMessage, h as bail, m as setMenuEnvHook, n as bareGroupStartPath, p as realEnvEntryDeps, y as unwrap } from "./menu-
|
|
1
|
+
import { i as markOutsideCheckout, n as discoverRepoRoot, r as findRepoRoot, t as RepoNotFoundError } from "./root-RaJ8ECCO.js";
|
|
2
|
+
import { b as setDryRun, d as loadEnvLoad, f as loadEnvSession, m as formatCommand, v as isDryRun, y as resolveDryRun } from "./run-D5iI9zve.js";
|
|
3
|
+
import { D as catalog, E as setProductMode, N as setEnvironmentRoot, O as helpPath, S as findProductRoot, c as nonEmpty, f as enterSessionEnvironment, g as errorMessage, h as bail, m as setMenuEnvHook, n as bareGroupStartPath, p as realEnvEntryDeps, y as unwrap } from "./menu-CZK0L1Vf.js";
|
|
4
4
|
import { a as isVersionRequest, c as cliName, t as installFailureLog } from "./failure-log-MSdCgvLc.js";
|
|
5
|
-
import { c as lastSentryEventId, f as hasYes, h as stripTierFlag, m as stripNoEnvFlag, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive } from "./telemetry-
|
|
5
|
+
import { c as lastSentryEventId, f as hasYes, h as stripTierFlag, m as stripNoEnvFlag, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive } from "./telemetry-BDOwjuoC.js";
|
|
6
6
|
import { confirm, select } from "@clack/prompts";
|
|
7
7
|
//#region ../cli-core/src/session.ts
|
|
8
8
|
/**
|
|
@@ -172,7 +172,7 @@ function outsideRepoMessage(rest) {
|
|
|
172
172
|
/** The offer's stack start (`env-entry.ts` holds the TTY prompt, this holds
|
|
173
173
|
* the lifecycle command), imported lazily like the rest of the commands. */
|
|
174
174
|
async function startStack() {
|
|
175
|
-
const { runStackCommand } = await import("./stack-
|
|
175
|
+
const { runStackCommand } = await import("./stack-VZ-1SmuM.js");
|
|
176
176
|
return runStackCommand("start");
|
|
177
177
|
}
|
|
178
178
|
/**
|
|
@@ -183,11 +183,12 @@ 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-CJtevyVy.js");
|
|
187
187
|
try {
|
|
188
188
|
await main(argv);
|
|
189
189
|
} catch (err) {
|
|
190
|
-
|
|
190
|
+
const outside = markOutsideCheckout(err);
|
|
191
|
+
process.stderr.write(`devtools: ${outside ? outsideRepoMessage(argv) : errorMessage(err)}\n`);
|
|
191
192
|
await captureDevtoolsError(err);
|
|
192
193
|
process.exit(1);
|
|
193
194
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as LocalStackOfflineError, c as applyDeployTierAliases, d as loadEnvironment, f as locateRepoRoot, h as selectEnvFiles, i as LOCAL_STACK_PORT, l as applyWranglerLocalDatabaseAlias, m as probeLocalStack, n as GENERATED_FILE, o as MissingEnvFileError, p as parseRawAssignments, r as HYPERDRIVE_LOCAL_CONNECTION_ENV, s as SHELL_KEYS_ENV, t as DEV_DB_ENV, u as isDevDatabase } from "./load-
|
|
1
|
+
import { a as LocalStackOfflineError, c as applyDeployTierAliases, d as loadEnvironment, f as locateRepoRoot, h as selectEnvFiles, i as LOCAL_STACK_PORT, l as applyWranglerLocalDatabaseAlias, m as probeLocalStack, n as GENERATED_FILE, o as MissingEnvFileError, p as parseRawAssignments, r as HYPERDRIVE_LOCAL_CONNECTION_ENV, s as SHELL_KEYS_ENV, t as DEV_DB_ENV, u as isDevDatabase } from "./load-lrgJ5Kz7.js";
|
|
2
2
|
export { DEV_DB_ENV, GENERATED_FILE, HYPERDRIVE_LOCAL_CONNECTION_ENV, LOCAL_STACK_PORT, LocalStackOfflineError, MissingEnvFileError, SHELL_KEYS_ENV, applyDeployTierAliases, applyWranglerLocalDatabaseAlias, isDevDatabase, loadEnvironment, locateRepoRoot, parseRawAssignments, probeLocalStack, selectEnvFiles };
|
|
@@ -521,7 +521,7 @@ async function probeLocalStack(port = LOCAL_STACK_PORT, timeoutMs = 250) {
|
|
|
521
521
|
* worse failure than a rejected promise.
|
|
522
522
|
*/
|
|
523
523
|
async function locateRepoRoot() {
|
|
524
|
-
const { discoverRepoRoot, RepoNotFoundError } = await import("./root-
|
|
524
|
+
const { discoverRepoRoot, RepoNotFoundError } = await import("./root-IVsv7i8N.js");
|
|
525
525
|
const fromCwd = discoverRepoRoot();
|
|
526
526
|
if (fromCwd !== null) return fromCwd;
|
|
527
527
|
const { existsSync } = await import("node:fs");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as execSync } from "./spawn-BvLQzc_K.js";
|
|
2
|
-
import { n as discoverRepoRoot } from "./root-
|
|
3
|
-
import { C as containerPrefix, D as readProjectId, E as listContainerNames, P as resolveLayout, S as STACK_API_PORT, T as foreignStackProjectId, d as loadEnvLoad, k as devdogsugaRootOrNull, s as supabaseCapture, u as loadEnv, w as foreignStackMessage } from "./run-
|
|
2
|
+
import { n as discoverRepoRoot } from "./root-RaJ8ECCO.js";
|
|
3
|
+
import { C as containerPrefix, D as readProjectId, E as listContainerNames, P as resolveLayout, S as STACK_API_PORT, T as foreignStackProjectId, d as loadEnvLoad, k as devdogsugaRootOrNull, s as supabaseCapture, u as loadEnv, w as foreignStackMessage } from "./run-D5iI9zve.js";
|
|
4
4
|
import { d as YES, f as createCatalog, i as suppressFailureLog, l as JSON_FLAG, m as positionals, u as SCOPES } from "./failure-log-MSdCgvLc.js";
|
|
5
|
-
import { l as reportDevtoolsError, p as isNonInteractive } from "./telemetry-
|
|
5
|
+
import { l as reportDevtoolsError, p as isNonInteractive } from "./telemetry-BDOwjuoC.js";
|
|
6
6
|
import { existsSync, readFileSync } from "node:fs";
|
|
7
7
|
import { dirname, join, resolve } from "node:path";
|
|
8
8
|
import { z } from "zod";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as discoverRepoRoot, t as RepoNotFoundError } from "./root-
|
|
1
|
+
import { n as discoverRepoRoot, t as RepoNotFoundError } from "./root-RaJ8ECCO.js";
|
|
2
2
|
export { RepoNotFoundError, discoverRepoRoot };
|
|
@@ -73,5 +73,17 @@ function findRepoRoot() {
|
|
|
73
73
|
if (cachedRoot === null) throw new RepoNotFoundError();
|
|
74
74
|
return cachedRoot;
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Whether `err` is the user running a checkout-requiring command with no
|
|
78
|
+
* DevDogsUGA checkout above the working directory, and if so marks it
|
|
79
|
+
* `expected` so telemetry drops it. A `RepoNotFoundError` raised while a
|
|
80
|
+
* checkout does exist (a `findRepoRoot()` call that should not have needed
|
|
81
|
+
* one, as in DEVTOOLS-D) is a bug and stays reportable.
|
|
82
|
+
*/
|
|
83
|
+
function markOutsideCheckout(err, startDir = process.cwd()) {
|
|
84
|
+
if (!(err instanceof RepoNotFoundError) || discoverRepoRoot(startDir) !== null) return false;
|
|
85
|
+
Object.assign(err, { expected: true });
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
76
88
|
//#endregion
|
|
77
|
-
export { discoverRepoRoot as n, findRepoRoot as r, RepoNotFoundError as t };
|
|
89
|
+
export { markOutsideCheckout as i, discoverRepoRoot as n, findRepoRoot as r, RepoNotFoundError as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as execSync, r as spawnProcess, t as exec } from "./spawn-BvLQzc_K.js";
|
|
2
|
-
import { r as findRepoRoot, t as RepoNotFoundError } from "./root-
|
|
2
|
+
import { r as findRepoRoot, t as RepoNotFoundError } from "./root-RaJ8ECCO.js";
|
|
3
3
|
import { c as cliName, r as noteRan } from "./failure-log-MSdCgvLc.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
@@ -631,11 +631,11 @@ function getEnvSync() {
|
|
|
631
631
|
}
|
|
632
632
|
/** The env loader (`loadEnvironment` and the tier/file selection). Bundled. */
|
|
633
633
|
function loadEnvLoad() {
|
|
634
|
-
return import("./load-
|
|
634
|
+
return import("./load-aeN4iX1h.js");
|
|
635
635
|
}
|
|
636
636
|
/** The session policy (tier resolution, `enterEnvironment`). Bundled. */
|
|
637
637
|
function loadEnvSession() {
|
|
638
|
-
return import("./session-
|
|
638
|
+
return import("./session-DdF8eqv3.js");
|
|
639
639
|
}
|
|
640
640
|
//#endregion
|
|
641
641
|
//#region ../cli-core/src/db/run.ts
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as parseSessionSelector, c as rememberDevDatabase, i as enterEnvironment, l as rememberedDevDatabase, n as availableTiers, o as resolveSessionTier, r as developmentRemoteCandidate, s as askSession, t as SESSION_SELECTORS } from "./session-
|
|
1
|
+
import { a as parseSessionSelector, c as rememberDevDatabase, i as enterEnvironment, l as rememberedDevDatabase, n as availableTiers, o as resolveSessionTier, r as developmentRemoteCandidate, s as askSession, t as SESSION_SELECTORS } from "./session-bPPOkolU.js";
|
|
2
2
|
export { SESSION_SELECTORS, askSession, availableTiers, developmentRemoteCandidate, enterEnvironment, parseSessionSelector, rememberDevDatabase, rememberedDevDatabase, resolveSessionTier };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as loadEnvironment, g as DEPLOY_ENVIRONMENTS, m as probeLocalStack, p as parseRawAssignments, t as DEV_DB_ENV, u as isDevDatabase, v as fileFor, y as isDeployEnvironment } from "./load-
|
|
1
|
+
import { d as loadEnvironment, g as DEPLOY_ENVIRONMENTS, m as probeLocalStack, p as parseRawAssignments, t as DEV_DB_ENV, u as isDevDatabase, v as fileFor, y as isDeployEnvironment } from "./load-lrgJ5Kz7.js";
|
|
2
2
|
//#region ../cli-core/src/env-runtime/ask.ts
|
|
3
3
|
/**
|
|
4
4
|
* The interactive half of session resolution, shared by `with-env` and the
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as readProjectId, E as listContainerNames, P as resolveLayout, S as STACK_API_PORT, T as foreignStackProjectId, a as seedBuckets, d as loadEnvLoad, f as loadEnvSession, o as supabase, s as supabaseCapture, v as isDryRun, w as foreignStackMessage } from "./run-
|
|
1
|
+
import { D as readProjectId, E as listContainerNames, P as resolveLayout, S as STACK_API_PORT, T as foreignStackProjectId, a as seedBuckets, d as loadEnvLoad, f as loadEnvSession, o as supabase, s as supabaseCapture, v as isDryRun, w as foreignStackMessage } from "./run-D5iI9zve.js";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { writeFile } from "node:fs/promises";
|
|
4
4
|
//#region src/db/session-refresh.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as discoverRepoRoot
|
|
1
|
+
import { n as discoverRepoRoot } from "./root-RaJ8ECCO.js";
|
|
2
2
|
import { c as cliName, n as noteError, s as ownVersion } from "./failure-log-MSdCgvLc.js";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import * as Sentry from "@sentry/node";
|
|
@@ -301,7 +301,9 @@ function hasRealCaller(inRepo, isTTY) {
|
|
|
301
301
|
}
|
|
302
302
|
/**
|
|
303
303
|
* A failure the person caused and can fix without anyone's help: the wrong
|
|
304
|
-
* directory, a bad flag, a database that has not been set up.
|
|
304
|
+
* directory, a bad flag, a database that has not been set up. A `RepoNotFoundError` is
|
|
305
|
+
* not on this list by class: only the dispatcher marks the genuine
|
|
306
|
+
* outside-a-checkout case `expected` (`markOutsideCheckout`). These are
|
|
305
307
|
* printed and exit non-zero but are not bugs, so they are never sent to Sentry
|
|
306
308
|
* (the failure log still records them). Matched by name as well as class so
|
|
307
309
|
* that `UsageError` (`ui.ts`, which imports this module) and the product
|
|
@@ -309,7 +311,6 @@ function hasRealCaller(inRepo, isTTY) {
|
|
|
309
311
|
* opts in by setting `expected = true`.
|
|
310
312
|
*/
|
|
311
313
|
function isExpectedFailure(err) {
|
|
312
|
-
if (err instanceof RepoNotFoundError) return true;
|
|
313
314
|
if (!(err instanceof Error)) return false;
|
|
314
315
|
return err.name === "UsageError" || err.expected === true;
|
|
315
316
|
}
|
package/dist/telemetry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as hasRealCaller, c as lastSentryEventId, d as resolveDevtoolsDsn, i as devtoolsTelemetryEnabled, l as reportDevtoolsError, n as captureDevtoolsError, o as initDevtoolsTelemetry, r as devtoolsEnvironment, s as isExpectedFailure, t as captureDevtoolsDeprecation, u as reportDevtoolsFailure } from "./telemetry-
|
|
1
|
+
import { a as hasRealCaller, c as lastSentryEventId, d as resolveDevtoolsDsn, i as devtoolsTelemetryEnabled, l as reportDevtoolsError, n as captureDevtoolsError, o as initDevtoolsTelemetry, r as devtoolsEnvironment, s as isExpectedFailure, t as captureDevtoolsDeprecation, u as reportDevtoolsFailure } from "./telemetry-BDOwjuoC.js";
|
|
2
2
|
export { captureDevtoolsDeprecation, captureDevtoolsError, devtoolsEnvironment, devtoolsTelemetryEnabled, hasRealCaller, initDevtoolsTelemetry, isExpectedFailure, lastSentryEventId, reportDevtoolsError, reportDevtoolsFailure, resolveDevtoolsDsn };
|
package/dist/with-env.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { r as spawnProcess, t as exec } from "./spawn-BvLQzc_K.js";
|
|
2
|
-
import { _ as UnknownEnvironmentError, a as LocalStackOfflineError, c as applyDeployTierAliases, d as loadEnvironment, l as applyWranglerLocalDatabaseAlias, m as probeLocalStack, n as GENERATED_FILE, o as MissingEnvFileError } from "./load-
|
|
3
|
-
import { n as availableTiers, s as askSession, t as SESSION_SELECTORS } from "./session-
|
|
2
|
+
import { _ as UnknownEnvironmentError, a as LocalStackOfflineError, c as applyDeployTierAliases, d as loadEnvironment, l as applyWranglerLocalDatabaseAlias, m as probeLocalStack, n as GENERATED_FILE, o as MissingEnvFileError } from "./load-lrgJ5Kz7.js";
|
|
3
|
+
import { n as availableTiers, s as askSession, t as SESSION_SELECTORS } from "./session-bPPOkolU.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { existsSync, statSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { dirname, join, resolve } from "node:path";
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devdogsuga/devtools",
|
|
3
|
-
"version": "0.1.51-next.
|
|
3
|
+
"version": "0.1.51-next.547",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
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
|
|
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.",
|
|
7
7
|
"license": "BSD-3-Clause",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
package/dist/stack-Cl_B_dt7.js
DELETED