@devdogsuga/devtools 0.1.41 → 0.1.43
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 +18 -0
- package/dist/{cli-CeCAuSJd.js → cli-B_AiECh4.js} +190 -90
- package/dist/{failure-log-B5GG_8T1.js → failure-log-DOt6E3hS.js} +1 -1
- package/dist/launch.js +8 -8
- package/dist/{local-env-hH4encfD.js → local-env-BuHU5Ckd.js} +84 -23
- package/dist/local-env-MqH18s-N.js +2 -0
- package/dist/{menu-Craj11Sn.js → menu-DYQ-Dd-O.js} +15 -11
- package/dist/{peers-RBplwovA.js → peers-DvUH5VxX.js} +128 -3
- package/dist/{root-C2OmZDwD.js → root-CjPWNkBu.js} +12 -7
- package/dist/{stack-7PuRcaI2.js → stack-C_50FafG.js} +5 -5
- package/dist/stack-o1Kml3V0.js +2 -0
- package/dist/{supabase-project-Bw8sBFcE.js → supabase-project-C93xRFkN.js} +22 -14
- package/dist/{telemetry-Do13RFhc.js → telemetry-C07-ioHm.js} +139 -3
- package/dist/telemetry.js +1 -1
- package/env.ts +1 -1
- package/package.json +6 -5
- package/dist/local-env-CR3McKHZ.js +0 -2
- package/dist/stack-B5UHASY2.js +0 -2
package/README.md
CHANGED
|
@@ -74,6 +74,24 @@ rather than a table here. Its first screen lists every interactive command
|
|
|
74
74
|
under a plain-English title ("Restart local Supabase") with the command to
|
|
75
75
|
type beside it (`restart-stack`).
|
|
76
76
|
|
|
77
|
+
## Which repo it runs in
|
|
78
|
+
|
|
79
|
+
Both CLIs run from a DevDogsUGA checkout or from Backstage's (`package.json`
|
|
80
|
+
name `devdogs-monorepo` or `backstage`; the layout code is
|
|
81
|
+
`packages/cli-core/src/repo/layout.ts`). From Backstage, DevDogsUGA is
|
|
82
|
+
`<root>/devdogsuga`: a gitignored symlink to the sibling clone locally
|
|
83
|
+
(`pnpm devdogsuga`), a real checkout at the pinned SHA in CI.
|
|
84
|
+
|
|
85
|
+
| What | Where |
|
|
86
|
+
| ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
87
|
+
| `supabase/` (CLI cwd, config, migrations, seeds, avatars, env manifest), `database.types.ts`, `docs/` | DevDogsUGA's root (`devdogsuga/` from Backstage) |
|
|
88
|
+
| `workers.json`, `.github/` | the repo you are in; DevDogsUGA without one manages no Workers |
|
|
89
|
+
| apps (`cron`, `run`, `deploy <app>`, env manifests) | the repo you are in plus DevDogsUGA's `apps/`; on a name clash the repo you are in wins |
|
|
90
|
+
| `.env`, `.env.<tier>`, `.env.generated` | the root of the repo you are in; `deploy write-env` and the local stack's `.env.generated` also write DevDogsUGA's root, because schedule-builder reads its own repo root. `env pull\|push\|reset` touch only the root you are in. |
|
|
91
|
+
|
|
92
|
+
`pnpm exec supabase` and `wrangler` run inside DevDogsUGA's workspace, so
|
|
93
|
+
`devdogsuga/` needs its own `pnpm install` before the commands that use them.
|
|
94
|
+
|
|
77
95
|
## Telemetry disclosure
|
|
78
96
|
|
|
79
97
|
This CLI reports its own crashes to Sentry (see `src/telemetry.ts`), on by
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { a as cliName, d as positionals, u as flagValue } from "./failure-log-
|
|
2
|
-
import { C as helpPath, S as catalog, T as renderHelp, _ as bail, a as recordEnteredTier, b as explainError, c as describeEnvironment, d as resolveDbConnection, f as sessionIsLocal, i as beginInvocation, l as probeEnvironment, n as bareGroupStartPath, o as recordResolved, p as sessionLabel, r as runMenu, s as reproducibleCommand, t as bareGroupStartFlags, u as nonEmpty, v as errorMessage, w as renderCommandList, x as unwrap, y as explain } from "./menu-
|
|
3
|
-
import { _ as
|
|
4
|
-
import { a as ownVersion, n as discoverRepoRoot, r as findRepoRoot } from "./root-
|
|
5
|
-
import { i as loadEnvSession, n as loadEnv, r as loadEnvLoad, t as getEnvSync } from "./peers-
|
|
6
|
-
import { d as hasYes, f as isNonInteractive, n as captureDevtoolsError, o as initDevtoolsTelemetry, r as devtoolsEnvironment, t as captureDevtoolsDeprecation } from "./telemetry-
|
|
7
|
-
import { n as assertRegistryLoaded, r as loadRegistry, t as scopedProcessEnv } from "./local-env-
|
|
8
|
-
import { t as runStackCommand } from "./stack-
|
|
1
|
+
import { a as cliName, d as positionals, u as flagValue } from "./failure-log-DOt6E3hS.js";
|
|
2
|
+
import { C as helpPath, S as catalog, T as renderHelp, _ as bail, a as recordEnteredTier, b as explainError, c as describeEnvironment, d as resolveDbConnection, f as sessionIsLocal, i as beginInvocation, l as probeEnvironment, n as bareGroupStartPath, o as recordResolved, p as sessionLabel, r as runMenu, s as reproducibleCommand, t as bareGroupStartFlags, u as nonEmpty, v as errorMessage, w as renderCommandList, x as unwrap, y as explain } from "./menu-DYQ-Dd-O.js";
|
|
3
|
+
import { S as wouldRunLine, _ as runInGroup, c as reportRuns, f as supabase, g as reportRan, l as run$1, m as supabaseRoot, s as dbPush, u as runWithStderr, v as dryRunKind, y as isDryRun } from "./supabase-project-C93xRFkN.js";
|
|
4
|
+
import { a as ownVersion, n as discoverRepoRoot, r as findRepoRoot } from "./root-CjPWNkBu.js";
|
|
5
|
+
import { c as devdogsugaRootOrNull, d as listApps, f as resolveAppPath, i as loadEnvSession, l as findApp, n as loadEnv, p as resolveLayout, r as loadEnvLoad, s as appWorkspaceRoot, t as getEnvSync, u as layoutAt } from "./peers-DvUH5VxX.js";
|
|
6
|
+
import { d as hasYes, f as isNonInteractive, n as captureDevtoolsError, o as initDevtoolsTelemetry, r as devtoolsEnvironment, t as captureDevtoolsDeprecation } from "./telemetry-C07-ioHm.js";
|
|
7
|
+
import { n as assertRegistryLoaded, r as loadRegistry, t as scopedProcessEnv } from "./local-env-BuHU5Ckd.js";
|
|
8
|
+
import { t as runStackCommand } from "./stack-C_50FafG.js";
|
|
9
9
|
import { cancel, confirm, intro, isCancel, log, multiselect, note, outro, password, select, spinner, text } from "@clack/prompts";
|
|
10
10
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { chmod, readFile, writeFile } from "node:fs/promises";
|
|
@@ -112,6 +112,19 @@ async function checkEnv(root) {
|
|
|
112
112
|
]
|
|
113
113
|
];
|
|
114
114
|
for (const [label, actual, expected] of pins) if (JSON.stringify(actual) !== JSON.stringify(expected)) problems.push(`The ${label} set is [${actual.join(", ")}]; expected exactly [${expected.join(", ")}]. A change here re-routes a credential: update this pin deliberately.`);
|
|
115
|
+
if (typeof env.buildKeys === "function") {
|
|
116
|
+
const build = env.buildKeys();
|
|
117
|
+
const expectedBuild = [
|
|
118
|
+
"API_URL",
|
|
119
|
+
"BASE_URL",
|
|
120
|
+
"NEXT_PUBLIC_TURNSTILE_SITE_KEY",
|
|
121
|
+
"PLATFORM_SENTRY_DSN",
|
|
122
|
+
"PUBLISHABLE_KEY",
|
|
123
|
+
"SCHEDULE_BUILDER_SENTRY_DSN"
|
|
124
|
+
];
|
|
125
|
+
if (JSON.stringify(build) !== JSON.stringify(expectedBuild)) problems.push(`The build set is [${build.join(", ")}]; expected exactly [${expectedBuild.join(", ")}]. A change here changes what the build workflows read from \`<tier>-build\`: update both deliberately.`);
|
|
126
|
+
for (const key of build) if (!variableSet.has(key)) problems.push(`${key} is build: true but is not in variableKeys(), so push cannot write it to the build environment.`);
|
|
127
|
+
}
|
|
115
128
|
for (const key of narrowed) for (const entry of registry.get(key) ?? []) if (entry.meta.scope !== "environment") problems.push(`${key} is narrowed with scope "${entry.meta.scope}".`);
|
|
116
129
|
let routed = 0;
|
|
117
130
|
for (const [key, entries] of registry) {
|
|
@@ -245,7 +258,7 @@ function checkMigrationOrder(root, baseRef) {
|
|
|
245
258
|
//#endregion
|
|
246
259
|
//#region ../cli-core/src/workers.ts
|
|
247
260
|
/**
|
|
248
|
-
* The one list of Worker apps, read from
|
|
261
|
+
* The one list of Worker apps, read from `workers.json` at the root of the repo you are in.
|
|
249
262
|
*
|
|
250
263
|
* Six call sites across `devtools` and `env` used to carry their own copy of
|
|
251
264
|
* `["platform", "sandbox", "schedule-builder"]` — a CLI's app-choice list, a
|
|
@@ -270,11 +283,27 @@ function parseWorkerEntries(json) {
|
|
|
270
283
|
throw new Error(`workers.json entry ${index} must be a path string or an object with a "path".`);
|
|
271
284
|
});
|
|
272
285
|
}
|
|
273
|
-
/**
|
|
286
|
+
/**
|
|
287
|
+
* Every entry in `workers.json` at the root of the repo you are in. DevDogsUGA
|
|
288
|
+
* after the platform moved to Backstage has no such file: no Worker apps are
|
|
289
|
+
* managed there, so the list is empty rather than an error. A Backstage
|
|
290
|
+
* checkout always has one, so a missing file there is still an error.
|
|
291
|
+
*/
|
|
274
292
|
function workerEntries() {
|
|
275
|
-
cachedWorkerEntries
|
|
293
|
+
if (cachedWorkerEntries === void 0) {
|
|
294
|
+
const layout = resolveLayout();
|
|
295
|
+
const file = join(layout.root, "workers.json");
|
|
296
|
+
cachedWorkerEntries = layout.kind === "devdogsuga" && !existsSync(file) ? [] : parseWorkerEntries(JSON.parse(readFileSync(file, "utf8")));
|
|
297
|
+
}
|
|
276
298
|
return cachedWorkerEntries;
|
|
277
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* The directory of a Worker app by its `workers.json` path: under the repo
|
|
302
|
+
* you are in, else under DevDogsUGA's (schedule-builder, from Backstage).
|
|
303
|
+
*/
|
|
304
|
+
function workerAppDir(entryPath) {
|
|
305
|
+
return resolveAppPath(entryPath);
|
|
306
|
+
}
|
|
278
307
|
/** Workspace-relative paths, exactly as listed in root `workers.json`. */
|
|
279
308
|
function workerPaths() {
|
|
280
309
|
return workerEntries().map((entry) => entry.path);
|
|
@@ -353,17 +382,37 @@ function deployMatrixApps(yamlText) {
|
|
|
353
382
|
function sameSet(a, b) {
|
|
354
383
|
return a.length === b.length && a.every((item) => b.includes(item));
|
|
355
384
|
}
|
|
356
|
-
/**
|
|
357
|
-
*
|
|
358
|
-
|
|
385
|
+
/**
|
|
386
|
+
* Every drift between `workers.json`, the workspace and the deploy matrix,
|
|
387
|
+
* as one readable line each. Empty means in step.
|
|
388
|
+
*
|
|
389
|
+
* `workers.json` lives at the root of the repo being checked. DevDogsUGA
|
|
390
|
+
* without one manages no Worker apps (the platform moved to Backstage), so
|
|
391
|
+
* there is nothing to check. From a Backstage checkout the apps are looked up
|
|
392
|
+
* in both repos, since schedule-builder is deployed from Backstage but stays in
|
|
393
|
+
* DevDogsUGA's `apps/`.
|
|
394
|
+
*/
|
|
395
|
+
function checkWorkers(root, layout = layoutAt(root)) {
|
|
359
396
|
const problems = [];
|
|
360
|
-
const
|
|
397
|
+
const workersFile = join(root, "workers.json");
|
|
398
|
+
if (!existsSync(workersFile)) {
|
|
399
|
+
if (layout.kind === "devdogsuga") return [];
|
|
400
|
+
return ["workers.json does not exist."];
|
|
401
|
+
}
|
|
402
|
+
const paths = parseWorkerEntries(JSON.parse(readFileSync(workersFile, "utf8"))).map((entry) => entry.path);
|
|
361
403
|
const apps = paths.map((path) => basename(path));
|
|
362
|
-
const
|
|
404
|
+
const roots = [root];
|
|
405
|
+
if (layout.kind === "backstage" && layout.hasDevdogsuga) roots.push(layout.devdogsugaRoot);
|
|
406
|
+
const scanned = [...new Set(roots.flatMap((dir) => {
|
|
407
|
+
const workspace = join(dir, "pnpm-workspace.yaml");
|
|
408
|
+
return existsSync(workspace) ? expandWorkspacePackages(dir, workspaceGlobs(readFileSync(workspace, "utf8"))) : [];
|
|
409
|
+
}))];
|
|
410
|
+
const dirOf = (relative) => join(roots.find((dir) => existsSync(join(dir, relative))) ?? root, relative);
|
|
411
|
+
const withWrangler = scanned.filter((relative) => existsSync(join(dirOf(relative), "wrangler.jsonc")));
|
|
363
412
|
for (const path of withWrangler.filter((p) => !paths.includes(p))) problems.push(`${path} has a wrangler.jsonc but is not in workers.json.`);
|
|
364
413
|
for (const path of paths.filter((p) => !withWrangler.includes(p))) problems.push(`workers.json lists ${path}, which has no wrangler.jsonc.`);
|
|
365
414
|
for (const path of paths) {
|
|
366
|
-
const manifest = join(
|
|
415
|
+
const manifest = join(dirOf(path), "package.json");
|
|
367
416
|
if (!existsSync(manifest)) continue;
|
|
368
417
|
const name = JSON.parse(readFileSync(manifest, "utf8")).name;
|
|
369
418
|
const slug = path.split("/").pop();
|
|
@@ -371,6 +420,7 @@ function checkWorkers(root) {
|
|
|
371
420
|
}
|
|
372
421
|
const deployApp = join(root, ".github", "workflows", "deploy-app.yaml");
|
|
373
422
|
if (!existsSync(deployApp)) {
|
|
423
|
+
if (layout.kind === "backstage") return problems;
|
|
374
424
|
problems.push(".github/workflows/deploy-app.yaml does not exist.");
|
|
375
425
|
return problems;
|
|
376
426
|
}
|
|
@@ -511,7 +561,7 @@ function report(name, problems, ok) {
|
|
|
511
561
|
}
|
|
512
562
|
function migrations(rest) {
|
|
513
563
|
const base = flagValue(rest, "--base") ?? DEFAULT_BASE;
|
|
514
|
-
const { baseLatest, violations } = checkMigrationOrder(
|
|
564
|
+
const { baseLatest, violations } = checkMigrationOrder(resolveLayout().devdogsugaRoot, base);
|
|
515
565
|
return report("migrations", violations.map((v) => `${v.filename} (${v.timestamp}) sorts before ${base}'s newest migration (${baseLatest}). Recreate it with a fresh timestamp (\`devtools new-migration\`) and regenerate types.`), `in order (${base}'s newest: ${baseLatest ?? "none"}).`);
|
|
516
566
|
}
|
|
517
567
|
async function run(rest) {
|
|
@@ -1201,10 +1251,11 @@ async function runEnvironmentDoctor(opts) {
|
|
|
1201
1251
|
fix: machine.stack === "no" && machine.docker === "yes" ? "Start it with `pnpm devtools supabase start`." : void 0
|
|
1202
1252
|
});
|
|
1203
1253
|
}
|
|
1204
|
-
|
|
1254
|
+
const supabaseRoot = repoRoot ? devdogsugaRootOrNull(layoutAt(repoRoot)) : null;
|
|
1255
|
+
if (supabaseRoot) checks.push(typesFreshness(supabaseRoot));
|
|
1205
1256
|
const sessionDbUrl = process.env.DB_URL;
|
|
1206
|
-
if (
|
|
1207
|
-
checks.push(...databaseChecks(await probeDatabase(sessionDbUrl), readDeclaredBuckets(
|
|
1257
|
+
if (supabaseRoot && sessionDbUrl) try {
|
|
1258
|
+
checks.push(...databaseChecks(await probeDatabase(sessionDbUrl), readDeclaredBuckets(supabaseRoot)));
|
|
1208
1259
|
} catch (err) {
|
|
1209
1260
|
checks.push({
|
|
1210
1261
|
id: "database-unreachable",
|
|
@@ -1931,7 +1982,7 @@ function targetHeader(target, count) {
|
|
|
1931
1982
|
"#",
|
|
1932
1983
|
...comment(`The ${count} key${count === 1 ? "" : "s"} a \`pnpm devtools env push --target ${target}\` routes, and nothing else. The committed defaults and the per-developer values go nowhere, and a minted credential is signed at deploy time rather than stored, so none of the three has a line here to fill in.`),
|
|
1933
1984
|
"#",
|
|
1934
|
-
...comment(target === "production" ? "The apply-tier credential IS here — SUPABASE_ACCESS_TOKEN reaches the production
|
|
1985
|
+
...comment(target === "production" ? "The apply-tier credential IS here — SUPABASE_ACCESS_TOKEN reaches the production GitHub environment, and no other target carries it." : `The apply-tier credential is NOT here. It exists to reshape production, so a copy in ${target} would be a second write-capable token to rotate for no benefit — and \`env push\` skips it outside production anyway.`),
|
|
1935
1986
|
"#",
|
|
1936
1987
|
...comment(`Fill the values in, or run \`pnpm devtools env pull --target ${target}\` to fetch what Bitwarden already holds. Nothing is commented out: push reads assignments, and a commented line is not one — a value typed on it would be silently skipped.`),
|
|
1937
1988
|
"#",
|
|
@@ -2328,9 +2379,8 @@ function workflowsForTier(config, tier) {
|
|
|
2328
2379
|
}
|
|
2329
2380
|
/** Every app that actually carries a Wrangler configuration. */
|
|
2330
2381
|
function discoverWranglerConfigs() {
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
const path = join(appsRoot, entry.name, "wrangler.jsonc");
|
|
2382
|
+
return listApps().flatMap((entry) => {
|
|
2383
|
+
const path = join(entry.dir, "wrangler.jsonc");
|
|
2334
2384
|
return existsSync(path) ? [{
|
|
2335
2385
|
app: entry.name,
|
|
2336
2386
|
path,
|
|
@@ -2347,7 +2397,7 @@ function discoverWranglerConfigs() {
|
|
|
2347
2397
|
async function discoverCronMaps() {
|
|
2348
2398
|
const results = [];
|
|
2349
2399
|
for (const { app } of discoverWranglerConfigs()) {
|
|
2350
|
-
const scheduledPath = join(findRepoRoot(), "apps", app, "cloudflare", "scheduled.ts");
|
|
2400
|
+
const scheduledPath = join(findApp(app) ?? join(findRepoRoot(), "apps", app), "cloudflare", "scheduled.ts");
|
|
2351
2401
|
if (!existsSync(scheduledPath)) continue;
|
|
2352
2402
|
const mod = await import(pathToFileURL(scheduledPath).href);
|
|
2353
2403
|
const parsed = CronRoutes.safeParse(mod.CRON_ROUTES);
|
|
@@ -2560,7 +2610,7 @@ function readEnvFile(path) {
|
|
|
2560
2610
|
/** Resolve the selected app's origin without assuming every app uses port 3000. */
|
|
2561
2611
|
function resolveBaseUrl(app, tier, config, tierEnv) {
|
|
2562
2612
|
if (tier === "development" && app) {
|
|
2563
|
-
const appRoot = join(findRepoRoot(), "apps", app);
|
|
2613
|
+
const appRoot = findApp(app) ?? join(findRepoRoot(), "apps", app);
|
|
2564
2614
|
const local = {
|
|
2565
2615
|
...readEnvFile(join(appRoot, ".dev.vars.example")),
|
|
2566
2616
|
...readEnvFile(join(appRoot, ".dev.vars"))
|
|
@@ -2630,7 +2680,7 @@ function workspaceDepsBuildCommand(app) {
|
|
|
2630
2680
|
/** Build only `app`'s workspace dependencies — all `vinext dev` needs, since
|
|
2631
2681
|
* it compiles the app itself on demand. */
|
|
2632
2682
|
function buildWorkspaceDeps(app) {
|
|
2633
|
-
return run$1(workspaceDepsBuildCommand(app));
|
|
2683
|
+
return run$1(workspaceDepsBuildCommand(app), void 0, appWorkspaceRoot(app));
|
|
2634
2684
|
}
|
|
2635
2685
|
//#endregion
|
|
2636
2686
|
//#region src/workflows/commands.ts
|
|
@@ -2770,7 +2820,7 @@ function pidIsAlive(pid) {
|
|
|
2770
2820
|
}
|
|
2771
2821
|
function appDir(app) {
|
|
2772
2822
|
const path = workerPaths().find((candidate) => basename(candidate) === app);
|
|
2773
|
-
return path === void 0 ? void 0 :
|
|
2823
|
+
return path === void 0 ? void 0 : workerAppDir(path);
|
|
2774
2824
|
}
|
|
2775
2825
|
/** Probe Wrangler's Workflow explorer API, rather than merely checking a port. */
|
|
2776
2826
|
async function isWranglerDevRunning(port, timeoutMs = 1e3, fetcher = fetch) {
|
|
@@ -2853,7 +2903,7 @@ async function startTemporaryWrangler(app, requestedPort) {
|
|
|
2853
2903
|
return null;
|
|
2854
2904
|
}
|
|
2855
2905
|
const child = spawn("pnpm", vinextDevArgs(app, port), {
|
|
2856
|
-
cwd:
|
|
2906
|
+
cwd: appWorkspaceRoot(app),
|
|
2857
2907
|
stdio: "inherit",
|
|
2858
2908
|
detached: process.platform !== "win32",
|
|
2859
2909
|
env: await scopedProcessEnv(app, loaded.env, "development")
|
|
@@ -3060,7 +3110,7 @@ async function runWorkflowsRun(argv) {
|
|
|
3060
3110
|
if (givenPort === void 0 && options.port && options.port !== "8787") recordResolved("--port", options.port);
|
|
3061
3111
|
process.stdout.write(`→ ${choice.name} (${choice.app}, ${tier})\n`);
|
|
3062
3112
|
try {
|
|
3063
|
-
const result = await runWithStderr(workflowTriggerArgs(choice, options), triggerEnv);
|
|
3113
|
+
const result = await runWithStderr(workflowTriggerArgs(choice, options), triggerEnv, appWorkspaceRoot(choice.app));
|
|
3064
3114
|
if (result.code !== 0 && tier === "development" && isWranglerDevConnectionFailure(result.stderr)) process.stderr.write(wranglerDevConnectionHint(choice.app, options.port ?? "8787"));
|
|
3065
3115
|
if (result.code === 0 && tier === "development" && options.instanceId) try {
|
|
3066
3116
|
return await waitForLocalWorkflow(choice.name, options.instanceId, options.port ?? "8787");
|
|
@@ -3980,6 +4030,11 @@ function runStatus(argv, cwd) {
|
|
|
3980
4030
|
* reasons that have nothing to do with Supabase.
|
|
3981
4031
|
*/
|
|
3982
4032
|
function detectLocalSupabase(cwd) {
|
|
4033
|
+
const repoRoot = discoverRepoRoot(cwd);
|
|
4034
|
+
if (repoRoot !== null) {
|
|
4035
|
+
const layout = layoutAt(repoRoot);
|
|
4036
|
+
if (layout.kind === "backstage" && layout.hasDevdogsuga) cwd = layout.devdogsugaRoot;
|
|
4037
|
+
}
|
|
3983
4038
|
let output;
|
|
3984
4039
|
try {
|
|
3985
4040
|
output = runStatus([
|
|
@@ -5408,7 +5463,7 @@ async function runSupabaseRaw(args) {
|
|
|
5408
5463
|
"supabase",
|
|
5409
5464
|
...args
|
|
5410
5465
|
];
|
|
5411
|
-
const result = await runInGroup("pnpm", full, { cwd:
|
|
5466
|
+
const result = await runInGroup("pnpm", full, { cwd: supabaseRoot() });
|
|
5412
5467
|
reportRan("pnpm", full, result);
|
|
5413
5468
|
return result.code;
|
|
5414
5469
|
}
|
|
@@ -5482,7 +5537,7 @@ async function regenerateTypes() {
|
|
|
5482
5537
|
"run",
|
|
5483
5538
|
"types:db"
|
|
5484
5539
|
];
|
|
5485
|
-
const result = await runInGroup("pnpm", args, { cwd:
|
|
5540
|
+
const result = await runInGroup("pnpm", args, { cwd: supabaseRoot() });
|
|
5486
5541
|
reportRan("pnpm", args, result);
|
|
5487
5542
|
return result.code;
|
|
5488
5543
|
}
|
|
@@ -5710,6 +5765,28 @@ const NEEDS_DEPS_BUILT = /* @__PURE__ */ new Set([
|
|
|
5710
5765
|
"lint:fix",
|
|
5711
5766
|
"test"
|
|
5712
5767
|
]);
|
|
5768
|
+
/** The workspace root an app lives in: `<root>/apps/<name>` gives `<root>`. */
|
|
5769
|
+
function workspaceRootOfApp(dir) {
|
|
5770
|
+
return dirname(dirname(dir));
|
|
5771
|
+
}
|
|
5772
|
+
/**
|
|
5773
|
+
* Splits `filters` by the workspace that holds the app each one names. From a
|
|
5774
|
+
* Backstage checkout `schedule-builder` belongs to DevDogsUGA's workspace, and
|
|
5775
|
+
* a `pnpm --filter` run from Backstage's root would match nothing. A filter
|
|
5776
|
+
* naming no known app (a glob, a path) stays with the repo you are in. No
|
|
5777
|
+
* filters means the whole workspace of the repo you are in.
|
|
5778
|
+
*/
|
|
5779
|
+
function groupFiltersByRoot(filters, apps = appsWith(), repoRoot = findRepoRoot()) {
|
|
5780
|
+
const groups = /* @__PURE__ */ new Map([[repoRoot, []]]);
|
|
5781
|
+
for (const filter of filters) {
|
|
5782
|
+
const root = apps.find((app) => app.name === filter)?.root ?? repoRoot;
|
|
5783
|
+
const group = groups.get(root) ?? [];
|
|
5784
|
+
group.push(filter);
|
|
5785
|
+
groups.set(root, group);
|
|
5786
|
+
}
|
|
5787
|
+
if (filters.length > 0 && groups.get(repoRoot)?.length === 0) groups.delete(repoRoot);
|
|
5788
|
+
return groups;
|
|
5789
|
+
}
|
|
5713
5790
|
/**
|
|
5714
5791
|
* Runs one `pnpm` invocation to completion, reporting its own exit the way
|
|
5715
5792
|
* `passthroughApps` needs to: it returns to keep going, and exits the process
|
|
@@ -5727,9 +5804,9 @@ const NEEDS_DEPS_BUILT = /* @__PURE__ */ new Set([
|
|
|
5727
5804
|
* `packages/devtools`, and a `pnpm -r`/`--filter` invoked there would scope
|
|
5728
5805
|
* itself relative to that one package rather than the workspace root.
|
|
5729
5806
|
*/
|
|
5730
|
-
async function runOne(args, extraEnv, { final }) {
|
|
5807
|
+
async function runOne({ args, cwd }, extraEnv, { final }) {
|
|
5731
5808
|
const result = await runInGroup("pnpm", args, {
|
|
5732
|
-
cwd
|
|
5809
|
+
cwd,
|
|
5733
5810
|
env: {
|
|
5734
5811
|
...process.env,
|
|
5735
5812
|
...extraEnv,
|
|
@@ -5749,7 +5826,7 @@ async function runOne(args, extraEnv, { final }) {
|
|
|
5749
5826
|
* Never returns: `runOne` exits on a failure and on the final command.
|
|
5750
5827
|
*/
|
|
5751
5828
|
async function passthrough(commands, extraEnv) {
|
|
5752
|
-
for (const [index,
|
|
5829
|
+
for (const [index, command] of commands.entries()) await runOne(command, extraEnv, { final: index === commands.length - 1 });
|
|
5753
5830
|
process.exit(1);
|
|
5754
5831
|
}
|
|
5755
5832
|
/**
|
|
@@ -5820,19 +5897,31 @@ function extractFilters(args) {
|
|
|
5820
5897
|
* `packages/*`/`docs` package is reachable from at least one app's
|
|
5821
5898
|
* dependency graph, and no app depends on another app).
|
|
5822
5899
|
*/
|
|
5823
|
-
function allAppNames() {
|
|
5824
|
-
const dir = join(findRepoRoot(), "apps");
|
|
5825
|
-
if (!existsSync(dir)) return [];
|
|
5900
|
+
function allAppNames(root = findRepoRoot()) {
|
|
5826
5901
|
const names = [];
|
|
5827
|
-
for (const
|
|
5828
|
-
|
|
5902
|
+
for (const app of appManifests(root)) if (app.pkg.name) names.push(app.pkg.name);
|
|
5903
|
+
return names;
|
|
5904
|
+
}
|
|
5905
|
+
/**
|
|
5906
|
+
* The parsed `package.json` of every app in the repo you are in, plus DevDogsUGA's
|
|
5907
|
+
* from a Backstage checkout (`repo/layout.ts`). With `root`, only that
|
|
5908
|
+
* workspace's. An unparsable manifest is one we cannot use, so it is skipped.
|
|
5909
|
+
*/
|
|
5910
|
+
function appManifests(root) {
|
|
5911
|
+
const found = [];
|
|
5912
|
+
for (const app of listApps(resolveLayout())) {
|
|
5913
|
+
const appRoot = workspaceRootOfApp(app.dir);
|
|
5914
|
+
if (root !== void 0 && appRoot !== root) continue;
|
|
5915
|
+
const manifest = join(app.dir, "package.json");
|
|
5829
5916
|
if (!existsSync(manifest)) continue;
|
|
5830
5917
|
try {
|
|
5831
|
-
|
|
5832
|
-
|
|
5918
|
+
found.push({
|
|
5919
|
+
root: appRoot,
|
|
5920
|
+
pkg: JSON.parse(readFileSync(manifest, "utf8"))
|
|
5921
|
+
});
|
|
5833
5922
|
} catch {}
|
|
5834
5923
|
}
|
|
5835
|
-
return
|
|
5924
|
+
return found;
|
|
5836
5925
|
}
|
|
5837
5926
|
/**
|
|
5838
5927
|
* Builds the `pnpm run <task>` invocation(s) for a set of package filters (or
|
|
@@ -5885,27 +5974,35 @@ function allAppNames() {
|
|
|
5885
5974
|
*/
|
|
5886
5975
|
async function passthroughApps(task, filters, rest, extraEnv) {
|
|
5887
5976
|
const commands = [];
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5977
|
+
for (const [cwd, groupFilters] of groupFiltersByRoot(filters)) {
|
|
5978
|
+
if (NEEDS_DEPS_BUILT.has(task) && (task !== "build" || filters.length > 0)) {
|
|
5979
|
+
const depsFilters = (groupFilters.length > 0 ? groupFilters : allAppNames(cwd)).flatMap((f) => ["--filter", `${f}^...`]);
|
|
5980
|
+
commands.push({
|
|
5981
|
+
args: [
|
|
5982
|
+
"-r",
|
|
5983
|
+
"--if-present",
|
|
5984
|
+
...depsFilters,
|
|
5985
|
+
"run",
|
|
5986
|
+
"build"
|
|
5987
|
+
],
|
|
5988
|
+
cwd
|
|
5989
|
+
});
|
|
5990
|
+
}
|
|
5991
|
+
const ownFilters = groupFilters.flatMap((f) => ["--filter", f]);
|
|
5992
|
+
const parallel = task === "dev" ? ["--parallel"] : [];
|
|
5993
|
+
commands.push({
|
|
5994
|
+
args: [
|
|
5995
|
+
"-r",
|
|
5996
|
+
"--if-present",
|
|
5997
|
+
...parallel,
|
|
5998
|
+
...ownFilters,
|
|
5999
|
+
"run",
|
|
6000
|
+
task,
|
|
6001
|
+
...rest
|
|
6002
|
+
],
|
|
6003
|
+
cwd
|
|
6004
|
+
});
|
|
5897
6005
|
}
|
|
5898
|
-
const ownFilters = filters.flatMap((f) => ["--filter", f]);
|
|
5899
|
-
const parallel = task === "dev" ? ["--parallel"] : [];
|
|
5900
|
-
commands.push([
|
|
5901
|
-
"-r",
|
|
5902
|
-
"--if-present",
|
|
5903
|
-
...parallel,
|
|
5904
|
-
...ownFilters,
|
|
5905
|
-
"run",
|
|
5906
|
-
task,
|
|
5907
|
-
...rest
|
|
5908
|
-
]);
|
|
5909
6006
|
return passthrough(commands, extraEnv);
|
|
5910
6007
|
}
|
|
5911
6008
|
/** A `dev` script that starts `vinext dev` (platform's `with-env vinext dev`). */
|
|
@@ -5954,15 +6051,18 @@ function planDev(apps, filters, rest) {
|
|
|
5954
6051
|
* The env is the session's: `launch.ts` has already entered the tier into
|
|
5955
6052
|
* `process.env` (or `--tier` loaded one into `tierEnv`).
|
|
5956
6053
|
*/
|
|
5957
|
-
async function runDev(plan, filters, rest, tierEnv) {
|
|
5958
|
-
await runOne(
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
6054
|
+
async function runDev(plan, filters, rest, tierEnv, root) {
|
|
6055
|
+
await runOne({
|
|
6056
|
+
args: [
|
|
6057
|
+
"-r",
|
|
6058
|
+
"--if-present",
|
|
6059
|
+
...(filters.length > 0 ? filters : allAppNames(root)).flatMap((f) => ["--filter", `${f}^...`]),
|
|
6060
|
+
"run",
|
|
6061
|
+
"build"
|
|
6062
|
+
],
|
|
6063
|
+
cwd: root
|
|
6064
|
+
}, tierEnv, { final: false });
|
|
6065
|
+
const { scopedProcessEnv } = await import("./local-env-MqH18s-N.js");
|
|
5966
6066
|
const environment = {
|
|
5967
6067
|
...process.env,
|
|
5968
6068
|
...tierEnv
|
|
@@ -5986,7 +6086,7 @@ async function runDev(plan, filters, rest, tierEnv) {
|
|
|
5986
6086
|
let first;
|
|
5987
6087
|
const runs = children.map(async ({ args, env }) => {
|
|
5988
6088
|
const result = await runInGroup("pnpm", args, {
|
|
5989
|
-
cwd:
|
|
6089
|
+
cwd: root,
|
|
5990
6090
|
env: {
|
|
5991
6091
|
...env,
|
|
5992
6092
|
DEVDOGS_PICK: "0"
|
|
@@ -6004,8 +6104,14 @@ async function runDev(plan, filters, rest, tierEnv) {
|
|
|
6004
6104
|
* `runDev`. */
|
|
6005
6105
|
async function dispatch$1(task, filters, rest, tierEnv) {
|
|
6006
6106
|
if (task === "dev") {
|
|
6007
|
-
const
|
|
6008
|
-
if (
|
|
6107
|
+
const groups = groupFiltersByRoot(filters);
|
|
6108
|
+
if (groups.size > 1) {
|
|
6109
|
+
process.stderr.write("devtools run: dev servers from DevDogsUGA and Backstage cannot be started together; start them from their own checkouts.\n");
|
|
6110
|
+
process.exit(1);
|
|
6111
|
+
}
|
|
6112
|
+
const root = [...groups.keys()][0];
|
|
6113
|
+
const plan = planDev(appsWith("dev", root), filters, rest);
|
|
6114
|
+
if (plan.vinext.length > 0) return runDev(plan, filters, rest, tierEnv, root);
|
|
6009
6115
|
}
|
|
6010
6116
|
return passthroughApps(task, filters, rest, tierEnv);
|
|
6011
6117
|
}
|
|
@@ -6053,21 +6159,15 @@ function parseTierArg(args) {
|
|
|
6053
6159
|
* out to a dry-run equivalent, which costs about a second before the first
|
|
6054
6160
|
* question.
|
|
6055
6161
|
*/
|
|
6056
|
-
function appsWith(task) {
|
|
6057
|
-
const dir = join(findRepoRoot(), "apps");
|
|
6058
|
-
if (!existsSync(dir)) return [];
|
|
6162
|
+
function appsWith(task, root) {
|
|
6059
6163
|
const found = [];
|
|
6060
|
-
for (const
|
|
6061
|
-
const
|
|
6062
|
-
if (
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
name: pkg.name,
|
|
6068
|
-
script
|
|
6069
|
-
});
|
|
6070
|
-
} catch {}
|
|
6164
|
+
for (const app of appManifests(root)) {
|
|
6165
|
+
const script = task === void 0 ? "" : app.pkg.scripts?.[task];
|
|
6166
|
+
if (app.pkg.name && (task === void 0 || script)) found.push({
|
|
6167
|
+
name: app.pkg.name,
|
|
6168
|
+
script: script ?? "",
|
|
6169
|
+
root: app.root
|
|
6170
|
+
});
|
|
6071
6171
|
}
|
|
6072
6172
|
return found;
|
|
6073
6173
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ownVersion } from "./root-
|
|
1
|
+
import { a as ownVersion } from "./root-CjPWNkBu.js";
|
|
2
2
|
import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { homedir, platform, release } from "node:os";
|
package/dist/launch.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as cliName, t as installFailureLog } from "./failure-log-
|
|
2
|
-
import { C as helpPath, S as catalog, _ as bail, g as setMenuEnvHook, h as realEnvEntryDeps, m as enterSessionEnvironment, n as bareGroupStartPath, u as nonEmpty, v as errorMessage, x as unwrap } from "./menu-
|
|
3
|
-
import { b as
|
|
4
|
-
import { n as discoverRepoRoot, r as findRepoRoot, t as RepoNotFoundError } from "./root-
|
|
5
|
-
import { i as loadEnvSession, r as loadEnvLoad } from "./peers-
|
|
6
|
-
import { d as hasYes, f as isNonInteractive, m as stripTierFlag, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as stripNoEnvFlag, s as lastSentryEventId } from "./telemetry-
|
|
1
|
+
import { a as cliName, t as installFailureLog } from "./failure-log-DOt6E3hS.js";
|
|
2
|
+
import { C as helpPath, S as catalog, _ as bail, g as setMenuEnvHook, h as realEnvEntryDeps, m as enterSessionEnvironment, n as bareGroupStartPath, u as nonEmpty, v as errorMessage, x as unwrap } from "./menu-DYQ-Dd-O.js";
|
|
3
|
+
import { b as resolveDryRun, h as formatCommand, x as setDryRun, y as isDryRun } from "./supabase-project-C93xRFkN.js";
|
|
4
|
+
import { n as discoverRepoRoot, r as findRepoRoot, t as RepoNotFoundError } from "./root-CjPWNkBu.js";
|
|
5
|
+
import { i as loadEnvSession, r as loadEnvLoad } from "./peers-DvUH5VxX.js";
|
|
6
|
+
import { d as hasYes, f as isNonInteractive, m as stripTierFlag, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as stripNoEnvFlag, s as lastSentryEventId } from "./telemetry-C07-ioHm.js";
|
|
7
7
|
import { confirm, select } from "@clack/prompts";
|
|
8
8
|
//#region ../cli-core/src/session.ts
|
|
9
9
|
/**
|
|
@@ -155,7 +155,7 @@ function skipsEnvEntry(rest) {
|
|
|
155
155
|
/** The offer's stack start (`env-entry.ts` holds the TTY prompt, this holds
|
|
156
156
|
* the lifecycle command), imported lazily like the rest of the commands. */
|
|
157
157
|
async function startStack() {
|
|
158
|
-
const { runStackCommand } = await import("./stack-
|
|
158
|
+
const { runStackCommand } = await import("./stack-o1Kml3V0.js");
|
|
159
159
|
return runStackCommand("start");
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
@@ -166,7 +166,7 @@ async function startStack() {
|
|
|
166
166
|
* post-tier-resolution path.
|
|
167
167
|
*/
|
|
168
168
|
async function dispatch(argv) {
|
|
169
|
-
const { main } = await import("./cli-
|
|
169
|
+
const { main } = await import("./cli-B_AiECh4.js");
|
|
170
170
|
try {
|
|
171
171
|
await main(argv);
|
|
172
172
|
} catch (err) {
|