@devdogsuga/devtools 0.1.42 → 0.1.44
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-BkHyIT5V.js → cli-B_AiECh4.js} +189 -89
- 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-DXT1ICTI.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-xNMpvX5K.js → telemetry-C07-ioHm.js} +2 -2
- package/dist/telemetry.js +1 -1
- package/package.json +4 -4
- 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",
|
|
@@ -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) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { i as ownPackageDir
|
|
2
|
-
import { a as repoPeerUrl, n as loadEnv, t as getEnvSync } from "./peers-
|
|
1
|
+
import { i as ownPackageDir } from "./root-CjPWNkBu.js";
|
|
2
|
+
import { a as repoPeerUrl, n as loadEnv, o as resolveRepoPeerUrl, p as resolveLayout, t as getEnvSync } from "./peers-DvUH5VxX.js";
|
|
3
3
|
import { register } from "node:module";
|
|
4
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
4
|
+
import { existsSync, readdirSync, realpathSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
7
|
//#region ../cli-core/src/repo/peer-redirect.ts
|
|
@@ -23,10 +23,10 @@ import { pathToFileURL } from "node:url";
|
|
|
23
23
|
* manifest also imports `zod`, which has to keep resolving from devtools'
|
|
24
24
|
* own location, and a copy written anywhere else would lose that.
|
|
25
25
|
*/
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
function
|
|
29
|
-
register("./peer-redirect-hooks.js", import.meta.url, { data:
|
|
26
|
+
/** `redirectPeer` for several at once: the hooks keep one table per
|
|
27
|
+
* registration, so everything that needs redirecting goes in one call. */
|
|
28
|
+
function redirectPeers(redirects) {
|
|
29
|
+
register("./peer-redirect-hooks.js", import.meta.url, { data: redirects });
|
|
30
30
|
}
|
|
31
31
|
//#endregion
|
|
32
32
|
//#region ../cli-core/src/repo/tsx-loader.ts
|
|
@@ -85,7 +85,11 @@ async function importRepoTs(absolutePath) {
|
|
|
85
85
|
* filename (`tsconfig.json`, `wrangler.jsonc`, `supadart.yaml`), and a pointer
|
|
86
86
|
* would be the only one of its kind.
|
|
87
87
|
*
|
|
88
|
-
*
|
|
88
|
+
* From a Backstage checkout the scan covers BOTH repos (`repo/layout.ts`):
|
|
89
|
+
* Backstage's `apps/*` and `packages/*`, then DevDogsUGA's through
|
|
90
|
+
* `devdogsuga/`, de-duplicated by directory name with Backstage first.
|
|
91
|
+
*
|
|
92
|
+
* One special case: `supabase/env.ts` sits at DevDogsUGA's root, OUTSIDE the
|
|
89
93
|
* workspace globs. Its variables belong to `config.toml` and the Supabase
|
|
90
94
|
* CLI, not to any package, so it lives next to the config that reads them.
|
|
91
95
|
*
|
|
@@ -157,12 +161,17 @@ function assertRegistryLoaded() {
|
|
|
157
161
|
}
|
|
158
162
|
async function importManifests() {
|
|
159
163
|
await loadEnv();
|
|
164
|
+
const redirects = [];
|
|
160
165
|
const envUrl = repoPeerUrl("@devdogsuga/env");
|
|
161
|
-
if (envUrl)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
+
if (envUrl) {
|
|
167
|
+
redirects.push({
|
|
168
|
+
parentURL: pathToFileURL(ownManifestPath()).href,
|
|
169
|
+
specifier: "@devdogsuga/env",
|
|
170
|
+
url: envUrl
|
|
171
|
+
});
|
|
172
|
+
redirects.push(...siblingRedirects(envUrl));
|
|
173
|
+
}
|
|
174
|
+
if (redirects.length > 0) redirectPeers(redirects);
|
|
166
175
|
const previous = process.env.SKIP_ENV_VALIDATION;
|
|
167
176
|
process.env.SKIP_ENV_VALIDATION = "1";
|
|
168
177
|
try {
|
|
@@ -177,6 +186,36 @@ async function importManifests() {
|
|
|
177
186
|
}
|
|
178
187
|
}
|
|
179
188
|
/**
|
|
189
|
+
* From a Backstage checkout, the manifests under `devdogsuga/` import
|
|
190
|
+
* `@devdogsuga/env` through THAT checkout's `node_modules` (or not at all, when
|
|
191
|
+
* it has none): a second copy of the package, and so a second registry that
|
|
192
|
+
* every `declare()` there would populate instead of the one this process
|
|
193
|
+
* reads. Point their imports at the copy `loadEnv()` resolved. Resolved
|
|
194
|
+
* through `realpath`, because the loader sees the module's real location, not
|
|
195
|
+
* the `devdogsuga` symlink.
|
|
196
|
+
*/
|
|
197
|
+
function siblingRedirects(envUrl) {
|
|
198
|
+
const layout = resolveLayout();
|
|
199
|
+
if (layout.kind !== "backstage" || !layout.hasDevdogsuga) return [];
|
|
200
|
+
const nextjs = resolveRepoPeerUrl("@devdogsuga/env/nextjs");
|
|
201
|
+
const redirects = [];
|
|
202
|
+
for (const path of manifestPaths()) {
|
|
203
|
+
if (!path.startsWith(layout.devdogsugaRoot)) continue;
|
|
204
|
+
const parentURL = pathToFileURL(realpathSync(path)).href;
|
|
205
|
+
redirects.push({
|
|
206
|
+
parentURL,
|
|
207
|
+
specifier: "@devdogsuga/env",
|
|
208
|
+
url: envUrl
|
|
209
|
+
});
|
|
210
|
+
if (nextjs) redirects.push({
|
|
211
|
+
parentURL,
|
|
212
|
+
specifier: "@devdogsuga/env/nextjs",
|
|
213
|
+
url: nextjs
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return redirects;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
180
219
|
* Every manifest file, in a stable order.
|
|
181
220
|
*
|
|
182
221
|
* The workspace members are enumerated by scanning `apps/*` and `packages/*`
|
|
@@ -192,7 +231,8 @@ function manifestPaths() {
|
|
|
192
231
|
const manifest = manifestIn(dir);
|
|
193
232
|
if (manifest) paths.push(manifest);
|
|
194
233
|
}
|
|
195
|
-
const
|
|
234
|
+
const layout = resolveLayout();
|
|
235
|
+
const supabase = layout.hasDevdogsuga ? manifestIn(join(layout.devdogsugaRoot, "supabase")) : null;
|
|
196
236
|
if (supabase) paths.push(supabase);
|
|
197
237
|
paths.push(ownManifestPath());
|
|
198
238
|
return paths;
|
|
@@ -213,20 +253,41 @@ function manifestPaths() {
|
|
|
213
253
|
function ownManifestPath() {
|
|
214
254
|
return join(ownPackageDir(), "env.ts");
|
|
215
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* The CLIs' own packages: each loads its own operator manifest through
|
|
258
|
+
* `ownManifestPath()`, so scanning them from a Backstage checkout would
|
|
259
|
+
* declare the same keys twice.
|
|
260
|
+
*/
|
|
261
|
+
const CLI_PACKAGES = /* @__PURE__ */ new Set(["devtools", "backstage"]);
|
|
262
|
+
/**
|
|
263
|
+
* `apps/*` and `packages/*` of every repo in the layout (the repo you are in
|
|
264
|
+
* first, so it wins a name clash: before the cutover both repos carry
|
|
265
|
+
* `apps/platform` and `packages/email`), then DevDogsUGA's `docs`.
|
|
266
|
+
*/
|
|
216
267
|
function workspaceDirs() {
|
|
268
|
+
const layout = resolveLayout();
|
|
269
|
+
const roots = [layout.root];
|
|
270
|
+
if (layout.kind === "backstage" && layout.hasDevdogsuga) roots.push(layout.devdogsugaRoot);
|
|
217
271
|
const dirs = [];
|
|
218
|
-
const repoRoot = findRepoRoot();
|
|
219
272
|
for (const parent of ["apps", "packages"]) {
|
|
220
|
-
const
|
|
221
|
-
for (const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
273
|
+
const found = /* @__PURE__ */ new Map();
|
|
274
|
+
for (const root of roots) {
|
|
275
|
+
let entries;
|
|
276
|
+
try {
|
|
277
|
+
entries = readdirSync(join(root, parent), { withFileTypes: true });
|
|
278
|
+
} catch {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
for (const entry of entries) {
|
|
282
|
+
if (!entry.isDirectory()) continue;
|
|
283
|
+
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
284
|
+
if (layout.kind === "backstage" && parent === "packages" && CLI_PACKAGES.has(entry.name)) continue;
|
|
285
|
+
if (!found.has(entry.name)) found.set(entry.name, join(root, parent, entry.name));
|
|
286
|
+
}
|
|
225
287
|
}
|
|
226
|
-
|
|
227
|
-
for (const name of names) dirs.push(join(repoRoot, parent, name));
|
|
288
|
+
for (const name of [...found.keys()].sort()) dirs.push(found.get(name));
|
|
228
289
|
}
|
|
229
|
-
dirs.push(join(
|
|
290
|
+
if (layout.hasDevdogsuga) dirs.push(join(layout.devdogsugaRoot, "docs"));
|
|
230
291
|
return dirs;
|
|
231
292
|
}
|
|
232
293
|
/** `src/env.ts`, then `env.ts`; both present in one package is a hard error. */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as YES, d as positionals, i as suppressFailureLog, l as createCatalog, o as JSON_FLAG, s as SCOPES } from "./failure-log-
|
|
2
|
-
import { a as listContainerNames, i as foreignStackProjectId, n as containerPrefix, o as readProjectId, p as supabaseCapture, r as foreignStackMessage, t as STACK_API_PORT } from "./supabase-project-
|
|
3
|
-
import { r as findRepoRoot } from "./root-
|
|
4
|
-
import { n as loadEnv, r as loadEnvLoad } from "./peers-
|
|
5
|
-
import { c as reportDevtoolsError, f as isNonInteractive } from "./telemetry-
|
|
1
|
+
import { c as YES, d as positionals, i as suppressFailureLog, l as createCatalog, o as JSON_FLAG, s as SCOPES } from "./failure-log-DOt6E3hS.js";
|
|
2
|
+
import { a as listContainerNames, i as foreignStackProjectId, n as containerPrefix, o as readProjectId, p as supabaseCapture, r as foreignStackMessage, t as STACK_API_PORT } from "./supabase-project-C93xRFkN.js";
|
|
3
|
+
import { r as findRepoRoot } from "./root-CjPWNkBu.js";
|
|
4
|
+
import { c as devdogsugaRootOrNull, n as loadEnv, p as resolveLayout, r as loadEnvLoad } from "./peers-DvUH5VxX.js";
|
|
5
|
+
import { c as reportDevtoolsError, f as isNonInteractive } from "./telemetry-C07-ioHm.js";
|
|
6
6
|
import { cancel, confirm, isCancel, log, note, select, text } from "@clack/prompts";
|
|
7
7
|
import { existsSync } from "node:fs";
|
|
8
8
|
import { writeFile } from "node:fs/promises";
|
|
@@ -826,7 +826,7 @@ async function ensureGeneratedEnvFile(tier, devDatabase, deps) {
|
|
|
826
826
|
if (!await deps.probeLocalStack()) return { outcome: "skipped" };
|
|
827
827
|
try {
|
|
828
828
|
const env = await deps.captureStatus();
|
|
829
|
-
await deps.write(join(
|
|
829
|
+
for (const dir of [deps.repoRoot, ...deps.mirrorRoots ?? []]) await deps.write(join(dir, GENERATED_FILE), env);
|
|
830
830
|
return {
|
|
831
831
|
outcome: "wrote",
|
|
832
832
|
line: "devtools: wrote .env.generated from the running local stack"
|
|
@@ -851,15 +851,18 @@ async function ensureGeneratedEnvFile(tier, devDatabase, deps) {
|
|
|
851
851
|
* different copies of the same optional peer in play.
|
|
852
852
|
*/
|
|
853
853
|
function realEnsureGeneratedEnvDeps(probeLocalStack) {
|
|
854
|
-
const
|
|
854
|
+
const layout = resolveLayout();
|
|
855
|
+
const repoRoot = layout.root;
|
|
856
|
+
const supabaseRoot = devdogsugaRootOrNull(layout);
|
|
855
857
|
return {
|
|
856
858
|
probeLocalStack,
|
|
857
|
-
exists: (file) => existsSync(join(
|
|
859
|
+
exists: (file) => [repoRoot, ...layout.envMirrors].every((dir) => existsSync(join(dir, file))),
|
|
858
860
|
captureStatus: () => supabaseCapture("status", "-o", "env"),
|
|
859
861
|
write: (path, contents) => writeFile(path, contents),
|
|
860
862
|
listContainerNames: () => listContainerNames(STACK_API_PORT),
|
|
861
|
-
projectId: () => readProjectId(
|
|
862
|
-
repoRoot
|
|
863
|
+
projectId: () => supabaseRoot === null ? null : readProjectId(supabaseRoot),
|
|
864
|
+
repoRoot,
|
|
865
|
+
mirrorRoots: layout.envMirrors
|
|
863
866
|
};
|
|
864
867
|
}
|
|
865
868
|
//#endregion
|
|
@@ -1276,7 +1279,8 @@ function probeEnvironment(execute = run) {
|
|
|
1276
1279
|
stack: "unknown",
|
|
1277
1280
|
envFile
|
|
1278
1281
|
};
|
|
1279
|
-
const
|
|
1282
|
+
const supabaseRoot = devdogsugaRootOrNull(resolveLayout());
|
|
1283
|
+
const prefix = containerPrefix(supabaseRoot === null ? null : readProjectId(supabaseRoot));
|
|
1280
1284
|
return {
|
|
1281
1285
|
docker,
|
|
1282
1286
|
stack: names.split("\n").some((name) => name.trim().startsWith(prefix)) ? "yes" : "no",
|
|
@@ -1,8 +1,114 @@
|
|
|
1
|
-
import { r as findRepoRoot, t as RepoNotFoundError } from "./root-
|
|
1
|
+
import { r as findRepoRoot, t as RepoNotFoundError } from "./root-CjPWNkBu.js";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
|
+
/** The directory (relative to a Backstage root) holding the DevDogsUGA checkout. */
|
|
7
|
+
const DEVDOGSUGA_LINK = "devdogsuga";
|
|
8
|
+
var DevdogsugaMissingError = class extends Error {
|
|
9
|
+
constructor(path) {
|
|
10
|
+
super(`The DevDogsUGA checkout is missing at ${path}. Run \`pnpm devdogsuga\` (links the sibling clone, or \$DEVDOGSUGA_DIR) or \`pnpm install\` in the Backstage root first.`);
|
|
11
|
+
this.name = "DevdogsugaMissingError";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
/** The kind of repo `dir` is the root of, by its `package.json` name; null if neither. */
|
|
15
|
+
function repoKindOf(dir) {
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
18
|
+
if (pkg.name === "devdogs-monorepo") return "devdogsuga";
|
|
19
|
+
if (pkg.name === "backstage") return "backstage";
|
|
20
|
+
} catch {}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
function isDir(path) {
|
|
24
|
+
try {
|
|
25
|
+
return statSync(path).isDirectory();
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The layout of the repo rooted at `root`. Pure: nothing is memoized, so tests
|
|
32
|
+
* can build fixtures freely. An unrecognised package name is treated as
|
|
33
|
+
* DevDogsUGA (the contract fixtures and every pre-Backstage caller).
|
|
34
|
+
*/
|
|
35
|
+
function layoutAt(root) {
|
|
36
|
+
const kind = repoKindOf(root) === "backstage" ? "backstage" : "devdogsuga";
|
|
37
|
+
const sibling = join(root, DEVDOGSUGA_LINK);
|
|
38
|
+
const hasDevdogsuga = kind === "devdogsuga" || isDir(sibling);
|
|
39
|
+
const devdogsugaRoot = kind === "devdogsuga" ? root : sibling;
|
|
40
|
+
const appsDirs = [join(root, "apps")];
|
|
41
|
+
if (kind === "backstage" && hasDevdogsuga) appsDirs.push(join(devdogsugaRoot, "apps"));
|
|
42
|
+
return {
|
|
43
|
+
kind,
|
|
44
|
+
root,
|
|
45
|
+
get devdogsugaRoot() {
|
|
46
|
+
if (!hasDevdogsuga) throw new DevdogsugaMissingError(sibling);
|
|
47
|
+
return devdogsugaRoot;
|
|
48
|
+
},
|
|
49
|
+
...kind === "backstage" ? { backstageRoot: root } : {},
|
|
50
|
+
hasDevdogsuga,
|
|
51
|
+
appsDirs: appsDirs.filter(isDir),
|
|
52
|
+
envMirrors: kind === "backstage" && hasDevdogsuga ? [devdogsugaRoot] : []
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** `layout.devdogsugaRoot`, or null instead of a throw when the checkout is missing. */
|
|
56
|
+
function devdogsugaRootOrNull(layout) {
|
|
57
|
+
return layout.hasDevdogsuga ? layout.devdogsugaRoot : null;
|
|
58
|
+
}
|
|
59
|
+
let cached;
|
|
60
|
+
let cachedFor;
|
|
61
|
+
/** The layout of the repo the process is in (`findRepoRoot()`), memoized per root. */
|
|
62
|
+
function resolveLayout() {
|
|
63
|
+
const root = findRepoRoot();
|
|
64
|
+
if (cached === void 0 || cachedFor !== root) {
|
|
65
|
+
cached = layoutAt(root);
|
|
66
|
+
cachedFor = root;
|
|
67
|
+
}
|
|
68
|
+
return cached;
|
|
69
|
+
}
|
|
70
|
+
/** Every directory under `appsDirs` (one app each), de-duplicated by name, sorted by name. */
|
|
71
|
+
function listApps(layout = resolveLayout()) {
|
|
72
|
+
const seen = /* @__PURE__ */ new Map();
|
|
73
|
+
for (const parent of layout.appsDirs) for (const entry of readdirSync(parent, { withFileTypes: true })) {
|
|
74
|
+
if (!entry.isDirectory()) continue;
|
|
75
|
+
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
76
|
+
if (!seen.has(entry.name)) seen.set(entry.name, {
|
|
77
|
+
name: entry.name,
|
|
78
|
+
dir: join(parent, entry.name)
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return [...seen.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
82
|
+
}
|
|
83
|
+
/** The directory of the app called `name`, or undefined when no repo has it. */
|
|
84
|
+
function findApp(name, layout = resolveLayout()) {
|
|
85
|
+
return listApps(layout).find((app) => app.name === name)?.dir;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Resolves a workspace-relative path such as `workers.json`'s
|
|
89
|
+
* `apps/schedule-builder` to a directory: the repo you are in first, then
|
|
90
|
+
* DevDogsUGA's. When neither has it the first candidate is returned, so
|
|
91
|
+
* callers get an ordinary ENOENT naming the path rather than a second error.
|
|
92
|
+
*/
|
|
93
|
+
function resolveAppPath(relative, layout = resolveLayout()) {
|
|
94
|
+
const first = join(layout.root, relative);
|
|
95
|
+
if (existsSync(first)) return first;
|
|
96
|
+
if (layout.kind === "backstage" && layout.hasDevdogsuga) {
|
|
97
|
+
const second = join(layout.devdogsugaRoot, relative);
|
|
98
|
+
if (existsSync(second)) return second;
|
|
99
|
+
}
|
|
100
|
+
return first;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The pnpm workspace root holding the app called `name`: where
|
|
104
|
+
* `pnpm --filter <name>` has to run. DevDogsUGA's root for its apps seen from a
|
|
105
|
+
* Backstage checkout, `layout.root` otherwise.
|
|
106
|
+
*/
|
|
107
|
+
function appWorkspaceRoot(name, layout = resolveLayout()) {
|
|
108
|
+
const dir = findApp(name, layout);
|
|
109
|
+
return dir === void 0 ? layout.root : dirname(dirname(dir));
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
6
112
|
//#region ../cli-core/src/repo/resolve.ts
|
|
7
113
|
/**
|
|
8
114
|
* Resolves an `@devdogsuga/*` package FROM the target repo, not from
|
|
@@ -199,6 +305,25 @@ function loadPeer(specifier) {
|
|
|
199
305
|
function repoPeerUrl(specifier) {
|
|
200
306
|
return resolvedUrls.get(specifier);
|
|
201
307
|
}
|
|
308
|
+
/**
|
|
309
|
+
* Like `repoPeerUrl`, but for any specifier a package of the repo you are in
|
|
310
|
+
* can resolve, subpaths included (`@devdogsuga/env/nextjs`), without having
|
|
311
|
+
* loaded it. Undefined outside a real repo or when nothing depends on it.
|
|
312
|
+
*/
|
|
313
|
+
function resolveRepoPeerUrl(specifier) {
|
|
314
|
+
const known = resolvedUrls.get(specifier);
|
|
315
|
+
if (known) return known;
|
|
316
|
+
if (process.env.DEVTOOLS_TEST_REPO_ROOT) return void 0;
|
|
317
|
+
try {
|
|
318
|
+
const repoRoot = findRepoRoot();
|
|
319
|
+
const base = findDependent(repoRoot, specifier);
|
|
320
|
+
if (!base) return void 0;
|
|
321
|
+
const { resolvedPath } = resolveFromRepo(repoRoot, base, specifier);
|
|
322
|
+
return pathToFileURL(resolvedPath).href;
|
|
323
|
+
} catch {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
202
327
|
let resolvedEnvModule;
|
|
203
328
|
function loadEnv() {
|
|
204
329
|
return loadPeer("@devdogsuga/env").then((mod) => {
|
|
@@ -226,4 +351,4 @@ function loadEnvSession() {
|
|
|
226
351
|
return loadPeer("@devdogsuga/env/session");
|
|
227
352
|
}
|
|
228
353
|
//#endregion
|
|
229
|
-
export { repoPeerUrl as a, loadEnvSession as i, loadEnv as n, loadEnvLoad as r, getEnvSync as t };
|
|
354
|
+
export { repoPeerUrl as a, devdogsugaRootOrNull as c, listApps as d, resolveAppPath as f, loadEnvSession as i, findApp as l, loadEnv as n, resolveRepoPeerUrl as o, resolveLayout as p, loadEnvLoad as r, appWorkspaceRoot as s, getEnvSync as t, layoutAt as u };
|
|
@@ -38,13 +38,17 @@ function ownVersion() {
|
|
|
38
38
|
* marker validated in the `devtools-dlx` prototype
|
|
39
39
|
* (`/home/sloan/scratchpad/devdogs/prototypes/devtools-dlx/FINDINGS.md`,
|
|
40
40
|
* experiment 1): a directory containing `pnpm-workspace.yaml` AND whose
|
|
41
|
-
* `package.json` has `"name": "devdogs-monorepo"
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
41
|
+
* `package.json` has `"name": "devdogs-monorepo"` (DevDogsUGA) or
|
|
42
|
+
* `"backstage"` (Backstage, which the CLIs also run from; `layout.ts` says
|
|
43
|
+
* what differs). The name check is not redundant — a bare
|
|
44
|
+
* `pnpm-workspace.yaml` matches any pnpm workspace, which devtools should
|
|
45
|
+
* refuse rather than silently "find".
|
|
45
46
|
*/
|
|
46
|
-
/**
|
|
47
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The `package.json` names a repo root may carry: DevDogsUGA's, and Backstage's
|
|
49
|
+
* (the CLIs run from both; see `layout.ts`).
|
|
50
|
+
*/
|
|
51
|
+
const REPO_MARKER_NAMES = ["devdogs-monorepo", "backstage"];
|
|
48
52
|
var RepoNotFoundError = class extends Error {
|
|
49
53
|
constructor() {
|
|
50
54
|
super("run this from inside a DevDogsUGA clone");
|
|
@@ -54,7 +58,8 @@ var RepoNotFoundError = class extends Error {
|
|
|
54
58
|
function looksLikeRepoRoot(dir) {
|
|
55
59
|
if (!existsSync(join(dir, "pnpm-workspace.yaml"))) return false;
|
|
56
60
|
try {
|
|
57
|
-
|
|
61
|
+
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
62
|
+
return REPO_MARKER_NAMES.includes(pkg.name);
|
|
58
63
|
} catch {
|
|
59
64
|
return false;
|
|
60
65
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { a as listContainerNames, d as seedBuckets, f as supabase, i as foreignStackProjectId, o as readProjectId, p as supabaseCapture, r as foreignStackMessage, t as STACK_API_PORT,
|
|
2
|
-
import { r as
|
|
3
|
-
import { i as loadEnvSession, r as loadEnvLoad } from "./peers-RBplwovA.js";
|
|
1
|
+
import { a as listContainerNames, d as seedBuckets, f as supabase, i as foreignStackProjectId, o as readProjectId, p as supabaseCapture, r as foreignStackMessage, t as STACK_API_PORT, y as isDryRun } from "./supabase-project-C93xRFkN.js";
|
|
2
|
+
import { i as loadEnvSession, p as resolveLayout, r as loadEnvLoad } from "./peers-DvUH5VxX.js";
|
|
4
3
|
import { writeFile } from "node:fs/promises";
|
|
5
4
|
import { join } from "node:path";
|
|
6
5
|
//#region src/db/session-refresh.ts
|
|
@@ -52,7 +51,7 @@ async function refreshSessionEnv(opts = {}) {
|
|
|
52
51
|
function foreignStackHint() {
|
|
53
52
|
const names = listContainerNames(STACK_API_PORT);
|
|
54
53
|
if (names === null) return void 0;
|
|
55
|
-
const foreign = foreignStackProjectId(names, readProjectId(
|
|
54
|
+
const foreign = foreignStackProjectId(names, readProjectId(resolveLayout().devdogsugaRoot));
|
|
56
55
|
return foreign === null ? void 0 : foreignStackMessage(foreign);
|
|
57
56
|
}
|
|
58
57
|
/**
|
|
@@ -101,7 +100,8 @@ async function startLocalStack() {
|
|
|
101
100
|
wroteEnvFile: false
|
|
102
101
|
};
|
|
103
102
|
}
|
|
104
|
-
|
|
103
|
+
const layout = resolveLayout();
|
|
104
|
+
for (const dir of [layout.root, ...layout.envMirrors]) await writeFile(join(dir, ".env.generated"), env);
|
|
105
105
|
return {
|
|
106
106
|
code: await seedBuckets({ kind: "local" }),
|
|
107
107
|
wroteEnvFile: true
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as cliName, r as noteRan } from "./failure-log-
|
|
2
|
-
import { r as findRepoRoot } from "./root-
|
|
1
|
+
import { a as cliName, r as noteRan } from "./failure-log-DOt6E3hS.js";
|
|
2
|
+
import { r as findRepoRoot } from "./root-CjPWNkBu.js";
|
|
3
|
+
import { p as resolveLayout } from "./peers-DvUH5VxX.js";
|
|
3
4
|
import { readFileSync } from "node:fs";
|
|
4
5
|
import { join } from "node:path";
|
|
5
6
|
import { execFile, execFileSync, spawn } from "node:child_process";
|
|
@@ -190,20 +191,27 @@ function reportRan(command, args, result) {
|
|
|
190
191
|
//#endregion
|
|
191
192
|
//#region ../cli-core/src/db/run.ts
|
|
192
193
|
/**
|
|
193
|
-
* Shared helpers for running supabase CLI and pnpm commands
|
|
194
|
+
* Shared helpers for running supabase CLI and pnpm commands.
|
|
194
195
|
*
|
|
195
196
|
* The supabase CLI is a workspace devDependency (not a global install), so
|
|
196
|
-
* every invocation goes through `pnpm exec supabase`.
|
|
197
|
-
* findRepoRoot()
|
|
197
|
+
* every invocation goes through `pnpm exec supabase`. Plain pnpm commands run
|
|
198
|
+
* in `findRepoRoot()`; the supabase ones run in DevDogsUGA's root
|
|
199
|
+
* (`supabaseRoot()`), where `supabase/config.toml` lives and where the CLI is
|
|
200
|
+
* installed. From a Backstage checkout that is `<root>/devdogsuga`, so it needs
|
|
201
|
+
* its own `pnpm install` there before any of these work.
|
|
198
202
|
*/
|
|
199
203
|
const runFile = promisify(execFile);
|
|
204
|
+
/** Where `supabase/` lives, and so the cwd of every supabase CLI call. */
|
|
205
|
+
function supabaseRoot() {
|
|
206
|
+
return resolveLayout().devdogsugaRoot;
|
|
207
|
+
}
|
|
200
208
|
/** Spawn a pnpm command with inherited stdio; resolves to the exit code. Pass
|
|
201
209
|
* `env` to run the child against a loaded tier rather than process.env. The
|
|
202
210
|
* child runs in its own process group, so stopping this process stops
|
|
203
211
|
* whatever it started (see `process-group.ts`). */
|
|
204
|
-
async function run(args, env) {
|
|
212
|
+
async function run(args, env, cwd = findRepoRoot()) {
|
|
205
213
|
const result = await runInGroup("pnpm", args, {
|
|
206
|
-
cwd
|
|
214
|
+
cwd,
|
|
207
215
|
...env ? { env } : {}
|
|
208
216
|
});
|
|
209
217
|
if (reporting) reportRan("pnpm", args, result);
|
|
@@ -221,7 +229,7 @@ function reportRuns(enabled) {
|
|
|
221
229
|
}
|
|
222
230
|
/** Spawn a pnpm command while echoing and retaining stderr for diagnostics.
|
|
223
231
|
* Pass `env` to run the child against a loaded tier rather than process.env. */
|
|
224
|
-
function runWithStderr(args, env) {
|
|
232
|
+
function runWithStderr(args, env, cwd = findRepoRoot()) {
|
|
225
233
|
return new Promise((resolve) => {
|
|
226
234
|
const child = spawn("pnpm", args, {
|
|
227
235
|
stdio: [
|
|
@@ -229,7 +237,7 @@ function runWithStderr(args, env) {
|
|
|
229
237
|
"inherit",
|
|
230
238
|
"pipe"
|
|
231
239
|
],
|
|
232
|
-
cwd
|
|
240
|
+
cwd,
|
|
233
241
|
...env ? { env } : {}
|
|
234
242
|
});
|
|
235
243
|
let stderr = "";
|
|
@@ -254,9 +262,9 @@ function runWithStderr(args, env) {
|
|
|
254
262
|
});
|
|
255
263
|
}
|
|
256
264
|
/** Spawn a pnpm command, capture stdout, throw on non-zero exit. */
|
|
257
|
-
async function capture(args) {
|
|
265
|
+
async function capture(args, cwd = findRepoRoot()) {
|
|
258
266
|
const { stdout } = await runFile("pnpm", args, {
|
|
259
|
-
cwd
|
|
267
|
+
cwd,
|
|
260
268
|
encoding: "utf8"
|
|
261
269
|
});
|
|
262
270
|
return stdout;
|
|
@@ -266,13 +274,13 @@ const supabase = (...args) => run([
|
|
|
266
274
|
"exec",
|
|
267
275
|
"supabase",
|
|
268
276
|
...args
|
|
269
|
-
]);
|
|
277
|
+
], void 0, supabaseRoot());
|
|
270
278
|
/** `pnpm exec supabase …` with captured stdout. */
|
|
271
279
|
const supabaseCapture = (...args) => capture([
|
|
272
280
|
"exec",
|
|
273
281
|
"supabase",
|
|
274
282
|
...args
|
|
275
|
-
]);
|
|
283
|
+
], supabaseRoot());
|
|
276
284
|
/**
|
|
277
285
|
* `supabase db push` over `dbUrl`, inherited stdio, resolving to the exit code.
|
|
278
286
|
*
|
|
@@ -425,4 +433,4 @@ function foreignStackMessage(foreignProjectId) {
|
|
|
425
433
|
return `The stack on port ${STACK_API_PORT} belongs to project "${foreignProjectId}", not this checkout's. Stop it with \`supabase stop --project-id ${foreignProjectId}\` then \`pnpm devtools supabase start\`.`;
|
|
426
434
|
}
|
|
427
435
|
//#endregion
|
|
428
|
-
export {
|
|
436
|
+
export { wouldRunLine as S, runInGroup as _, listContainerNames as a, resolveDryRun as b, reportRuns as c, seedBuckets as d, supabase as f, reportRan as g, formatCommand as h, foreignStackProjectId as i, run as l, supabaseRoot as m, containerPrefix as n, readProjectId as o, supabaseCapture as p, foreignStackMessage as r, dbPush as s, STACK_API_PORT as t, runWithStderr as u, dryRunKind as v, setDryRun as x, isDryRun as y };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as cliName, n as noteError } from "./failure-log-
|
|
2
|
-
import { a as ownVersion, n as discoverRepoRoot } from "./root-
|
|
1
|
+
import { a as cliName, n as noteError } from "./failure-log-DOt6E3hS.js";
|
|
2
|
+
import { a as ownVersion, n as discoverRepoRoot } from "./root-CjPWNkBu.js";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import * as Sentry from "@sentry/node";
|
|
5
5
|
import "@sentry/core";
|
package/dist/telemetry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as hasRealCaller, c as reportDevtoolsError, i as devtoolsTelemetryEnabled, l as reportDevtoolsFailure, n as captureDevtoolsError, o as initDevtoolsTelemetry, r as devtoolsEnvironment, s as lastSentryEventId, t as captureDevtoolsDeprecation, u as resolveDevtoolsDsn } from "./telemetry-
|
|
1
|
+
import { a as hasRealCaller, c as reportDevtoolsError, i as devtoolsTelemetryEnabled, l as reportDevtoolsFailure, n as captureDevtoolsError, o as initDevtoolsTelemetry, r as devtoolsEnvironment, s as lastSentryEventId, t as captureDevtoolsDeprecation, u as resolveDevtoolsDsn } from "./telemetry-C07-ioHm.js";
|
|
2
2
|
export { captureDevtoolsDeprecation, captureDevtoolsError, devtoolsEnvironment, devtoolsTelemetryEnabled, hasRealCaller, initDevtoolsTelemetry, lastSentryEventId, reportDevtoolsError, reportDevtoolsFailure, resolveDevtoolsDsn };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devdogsuga/devtools",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.44",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Contributor CLI for a DevDogsUGA checkout: the real tools with the session's tier filled in, a menu over them, and the checks CI runs. Ships built JS; run via `pnpm dlx @devdogsuga/devtools` (or the `devtools` bin once installed) from inside a DevDogsUGA clone.",
|
|
@@ -51,10 +51,10 @@
|
|
|
51
51
|
"eslint": "^9.39.5",
|
|
52
52
|
"tsdown": "^0.23.0",
|
|
53
53
|
"vitest": "^4.1.11",
|
|
54
|
-
"@devdogsuga/cli-core": "0.0.0",
|
|
55
|
-
"@devdogsuga/env": "0.1.6",
|
|
56
|
-
"@devdogsuga/db": "0.1.4",
|
|
57
54
|
"@devdogsuga/config": "0.1.3",
|
|
55
|
+
"@devdogsuga/cli-core": "0.0.0",
|
|
56
|
+
"@devdogsuga/db": "0.1.5",
|
|
57
|
+
"@devdogsuga/env": "0.1.8",
|
|
58
58
|
"@devdogsuga/telemetry": "0.1.5"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
package/dist/stack-B5UHASY2.js
DELETED