@devdogsuga/devtools 0.1.11 → 0.1.13
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/bin/devtools-ci.mjs +15 -1
- package/bin/devtools.mjs +15 -1
- package/dist/catalog.d.ts +7 -5
- package/dist/catalog.js +1 -25
- package/dist/cf/build.d.ts +13 -0
- package/dist/cf/build.js +65 -0
- package/dist/cf/commands.js +6 -16
- package/dist/cf/local-env.d.ts +14 -0
- package/dist/cf/local-env.js +29 -0
- package/dist/ci.js +8 -1
- package/dist/cli.js +134 -138
- package/dist/commands.d.ts +10 -4
- package/dist/commands.js +40 -30
- package/dist/db/generated-env.d.ts +69 -0
- package/dist/db/generated-env.js +113 -0
- package/dist/db/seed-production.js +12 -6
- package/dist/docs/index-pages.js +2 -2
- package/dist/emails/commands.js +3 -3
- package/dist/env/discovery.js +19 -6
- package/dist/env-entry.d.ts +49 -0
- package/dist/env-entry.js +204 -0
- package/dist/environment-doctor.d.ts +9 -0
- package/dist/environment-doctor.js +18 -5
- package/dist/environment.d.ts +2 -2
- package/dist/environment.js +5 -28
- package/dist/images/commands.d.ts +3 -6
- package/dist/images/commands.js +26 -30
- package/dist/images/events.d.ts +27 -16
- package/dist/images/events.js +32 -68
- package/dist/images/graphics.js +2 -1
- package/dist/images/prompts.js +2 -2
- package/dist/instance.d.ts +29 -27
- package/dist/instance.js +49 -76
- package/dist/launch-ci.js +5 -5
- package/dist/launch.d.ts +2 -1
- package/dist/launch.js +74 -111
- package/dist/menu.d.ts +17 -5
- package/dist/menu.js +34 -11
- package/dist/moderation.d.ts +48 -40
- package/dist/moderation.js +95 -194
- package/dist/oauth/wizard.d.ts +2 -2
- package/dist/oauth/wizard.js +6 -26
- package/dist/persona.d.ts +18 -0
- package/dist/persona.js +221 -0
- package/dist/repo/peer-redirect-hooks.d.ts +16 -0
- package/dist/repo/peer-redirect-hooks.js +10 -0
- package/dist/repo/peer-redirect.d.ts +4 -0
- package/dist/repo/peer-redirect.js +26 -0
- package/dist/repo/peers.d.ts +15 -0
- package/dist/repo/peers.js +26 -1
- package/dist/repo/supabase-project.d.ts +60 -0
- package/dist/repo/supabase-project.js +124 -0
- package/dist/setup.js +2 -2
- package/dist/stack.js +142 -29
- package/dist/telemetry.d.ts +18 -5
- package/dist/telemetry.js +26 -5
- package/dist/ui.d.ts +15 -0
- package/dist/ui.js +20 -0
- package/dist/workflows/commands.d.ts +10 -0
- package/dist/workflows/commands.js +119 -25
- package/package.json +10 -5
package/dist/ui.d.ts
CHANGED
|
@@ -9,6 +9,21 @@ export declare function unwrap<T>(value: T | symbol): T;
|
|
|
9
9
|
* contributor asking in Discord.
|
|
10
10
|
*/
|
|
11
11
|
export declare function explain(summary: string, detail: string, hints?: string[]): void;
|
|
12
|
+
/**
|
|
13
|
+
* A refusal the reader can fix themselves — a name that matches nothing, a
|
|
14
|
+
* flag missing where there is no terminal to ask. Thrown from deep enough
|
|
15
|
+
* that the command's catch can't tell it from a real failure any other way;
|
|
16
|
+
* `explainError` prints it like any other error but keeps it out of Sentry.
|
|
17
|
+
*/
|
|
18
|
+
export declare class UsageError extends Error {
|
|
19
|
+
name: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* `explain()` for a caught error rather than a refusal: prints the same way,
|
|
23
|
+
* with `err`'s message as the detail, and reports `err` to Sentry unless it
|
|
24
|
+
* is a {@link UsageError}. Only failures nobody anticipated belong there.
|
|
25
|
+
*/
|
|
26
|
+
export declare function explainError(summary: string, err: unknown, hints?: string[]): void;
|
|
12
27
|
export declare function errorMessage(err: unknown): string;
|
|
13
28
|
export interface CheckResult {
|
|
14
29
|
name: string;
|
package/dist/ui.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* ends at a stack trace.
|
|
11
11
|
*/
|
|
12
12
|
import { cancel, isCancel, log, note } from "@clack/prompts";
|
|
13
|
+
import { reportDevtoolsError } from "./telemetry.js";
|
|
13
14
|
export function bail(message = "Cancelled.") {
|
|
14
15
|
cancel(message);
|
|
15
16
|
process.exit(1);
|
|
@@ -34,6 +35,25 @@ export function explain(summary, detail, hints = []) {
|
|
|
34
35
|
if (hints.length > 0)
|
|
35
36
|
note(hints.join("\n"), "Try this");
|
|
36
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* A refusal the reader can fix themselves — a name that matches nothing, a
|
|
40
|
+
* flag missing where there is no terminal to ask. Thrown from deep enough
|
|
41
|
+
* that the command's catch can't tell it from a real failure any other way;
|
|
42
|
+
* `explainError` prints it like any other error but keeps it out of Sentry.
|
|
43
|
+
*/
|
|
44
|
+
export class UsageError extends Error {
|
|
45
|
+
name = "UsageError";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `explain()` for a caught error rather than a refusal: prints the same way,
|
|
49
|
+
* with `err`'s message as the detail, and reports `err` to Sentry unless it
|
|
50
|
+
* is a {@link UsageError}. Only failures nobody anticipated belong there.
|
|
51
|
+
*/
|
|
52
|
+
export function explainError(summary, err, hints = []) {
|
|
53
|
+
if (!(err instanceof UsageError))
|
|
54
|
+
reportDevtoolsError(err);
|
|
55
|
+
explain(summary, errorMessage(err), hints);
|
|
56
|
+
}
|
|
37
57
|
export function errorMessage(err) {
|
|
38
58
|
return err instanceof Error ? err.message : String(err);
|
|
39
59
|
}
|
|
@@ -26,6 +26,16 @@ export declare function waitForLocalWorkflow(workflowName: string, instanceId: s
|
|
|
26
26
|
fetcher?: typeof fetch;
|
|
27
27
|
}): Promise<number>;
|
|
28
28
|
export declare function wranglerDevArgs(app: string, port: string): string[];
|
|
29
|
+
/** `vinext dev` bound to loopback, where `isWranglerDevRunning` probes. */
|
|
30
|
+
export declare function vinextDevArgs(app: string, port: string): string[];
|
|
31
|
+
/**
|
|
32
|
+
* The port of a `vinext dev` already running for `app`, from the lock file
|
|
33
|
+
* vinext keeps at `<app>/.vinext/dev/lock.json` — or undefined when there is
|
|
34
|
+
* none, or its process is gone. vinext refuses a second dev server in the same
|
|
35
|
+
* app directory, so starting one beside it fails ("Another vinext dev server
|
|
36
|
+
* is already running"); reusing it is the only way through.
|
|
37
|
+
*/
|
|
38
|
+
export declare function runningVinextDevPort(appDir: string, isAlive?: (pid: number) => boolean): string | undefined;
|
|
29
39
|
/** Probe Wrangler's Workflow explorer API, rather than merely checking a port. */
|
|
30
40
|
export declare function isWranglerDevRunning(port: string, timeoutMs?: number, fetcher?: typeof fetch): Promise<boolean>;
|
|
31
41
|
/** Whether nothing is bound to `port` on loopback — a real bind test, not a
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
/** Config-derived listing and manual triggering for Cloudflare Workflows. */
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
4
5
|
import { createServer } from "node:net";
|
|
6
|
+
import { basename, join } from "node:path";
|
|
5
7
|
import { setTimeout as delay } from "node:timers/promises";
|
|
6
8
|
import { confirm, select, text } from "@clack/prompts";
|
|
7
9
|
import { loadEnvLoad } from "../repo/peers.js";
|
|
8
|
-
import { createTemporaryWranglerEnv, renderWranglerEnvFile, } from "../cf/local-env.js";
|
|
10
|
+
import { createTemporaryWranglerEnv, renderWranglerEnvFile, scopedProcessEnv, } from "../cf/local-env.js";
|
|
11
|
+
import { buildWorkspaceDeps, needsFrameworkBuild } from "../cf/build.js";
|
|
9
12
|
import { runWithStderr } from "../db/run.js";
|
|
10
13
|
import { findRepoRoot } from "../repo/root.js";
|
|
14
|
+
import { workerPaths } from "../workers.js";
|
|
11
15
|
import { recordResolved } from "../invocation.js";
|
|
12
16
|
import { resolveTier } from "../tier.js";
|
|
13
17
|
import { unwrap } from "../ui.js";
|
|
14
18
|
import { CRON_TIERS, discoverWranglerConfigs, isCronTier, workflowsForTier, } from "../cron/discovery.js";
|
|
15
19
|
export { renderWranglerEnvFile } from "../cf/local-env.js";
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
|
|
20
|
+
// Covers `vinext dev`'s first-run dependency optimization and workerd boot. It
|
|
21
|
+
// also bounds how long a broken bundle stalls the command: both runtimes report
|
|
22
|
+
// a bundling error but keep watching for changes instead of exiting.
|
|
23
|
+
const WRANGLER_READY_TIMEOUT_MS = 3 * 60_000;
|
|
19
24
|
const LOCAL_WORKFLOW_TIMEOUT_MS = 60 * 60_000;
|
|
20
25
|
const WRANGLER_PROBE_PATH = "/cdn-cgi/local/explorer/api/workflows";
|
|
21
26
|
export function workflowChoices(configs, tiers = CRON_TIERS) {
|
|
@@ -162,6 +167,53 @@ export function wranglerDevArgs(app, port) {
|
|
|
162
167
|
"--show-interactive-dev-session=false",
|
|
163
168
|
];
|
|
164
169
|
}
|
|
170
|
+
/** `vinext dev` bound to loopback, where `isWranglerDevRunning` probes. */
|
|
171
|
+
export function vinextDevArgs(app, port) {
|
|
172
|
+
return [
|
|
173
|
+
"--filter",
|
|
174
|
+
app,
|
|
175
|
+
"exec",
|
|
176
|
+
"vinext",
|
|
177
|
+
"dev",
|
|
178
|
+
"--port",
|
|
179
|
+
port,
|
|
180
|
+
"--hostname",
|
|
181
|
+
"127.0.0.1",
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The port of a `vinext dev` already running for `app`, from the lock file
|
|
186
|
+
* vinext keeps at `<app>/.vinext/dev/lock.json` — or undefined when there is
|
|
187
|
+
* none, or its process is gone. vinext refuses a second dev server in the same
|
|
188
|
+
* app directory, so starting one beside it fails ("Another vinext dev server
|
|
189
|
+
* is already running"); reusing it is the only way through.
|
|
190
|
+
*/
|
|
191
|
+
export function runningVinextDevPort(appDir, isAlive = pidIsAlive) {
|
|
192
|
+
try {
|
|
193
|
+
const lock = JSON.parse(readFileSync(join(appDir, ".vinext", "dev", "lock.json"), "utf8"));
|
|
194
|
+
if (typeof lock.pid !== "number" || typeof lock.port !== "number") {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
return isAlive(lock.pid) ? String(lock.port) : undefined;
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function pidIsAlive(pid) {
|
|
204
|
+
try {
|
|
205
|
+
process.kill(pid, 0);
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
// EPERM: alive, just not ours to signal.
|
|
210
|
+
return error.code === "EPERM";
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function appDir(app) {
|
|
214
|
+
const path = workerPaths().find((candidate) => basename(candidate) === app);
|
|
215
|
+
return path === undefined ? undefined : join(findRepoRoot(), path);
|
|
216
|
+
}
|
|
165
217
|
/** Probe Wrangler's Workflow explorer API, rather than merely checking a port. */
|
|
166
218
|
export async function isWranglerDevRunning(port, timeoutMs = 1_000, fetcher = fetch) {
|
|
167
219
|
try {
|
|
@@ -241,13 +293,14 @@ async function startTemporaryWrangler(app, requestedPort) {
|
|
|
241
293
|
const free = await findFreePort(Number(port) + 1);
|
|
242
294
|
if (free === null) {
|
|
243
295
|
process.stderr.write(`devtools workflows: port ${requestedPort} is in use and no free port ` +
|
|
244
|
-
`was found near it for a temporary
|
|
296
|
+
`was found near it for a temporary dev session.\n`);
|
|
245
297
|
return null;
|
|
246
298
|
}
|
|
247
|
-
process.stdout.write(`Port ${requestedPort} is in use; starting the temporary
|
|
299
|
+
process.stdout.write(`Port ${requestedPort} is in use; starting the temporary dev session on ${free} instead.\n`);
|
|
248
300
|
port = String(free);
|
|
249
301
|
}
|
|
250
|
-
|
|
302
|
+
const runtime = needsFrameworkBuild(app) ? "vinext dev" : "Wrangler";
|
|
303
|
+
process.stdout.write(`Preparing and starting a temporary ${runtime} session for ${app} on port ${port}…\n`);
|
|
251
304
|
// Both callers of this function (`workflows serve`, `workflows run --tier
|
|
252
305
|
// development`) are local-only, so the tier is always development — but
|
|
253
306
|
// load it explicitly rather than letting the scoped `.dev.vars` fall back
|
|
@@ -265,11 +318,30 @@ async function startTemporaryWrangler(app, requestedPort) {
|
|
|
265
318
|
}
|
|
266
319
|
throw err;
|
|
267
320
|
}
|
|
268
|
-
|
|
269
|
-
|
|
321
|
+
// Their `exports` point at gitignored `dist/`, so on a fresh clone the
|
|
322
|
+
// app's `next.config.ts` can't load without this (see `cf/build.ts`).
|
|
323
|
+
const buildCode = await buildWorkspaceDeps(app);
|
|
324
|
+
if (buildCode !== 0) {
|
|
325
|
+
process.stderr.write(`devtools workflows: building ${app}'s workspace dependencies failed (exit ${buildCode}); not starting ${runtime}.\n`);
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
// A vinext app runs on `vinext dev`: the Cloudflare Vite plugin serves the
|
|
329
|
+
// same Workflow bindings and local explorer API as `wrangler dev`, straight
|
|
330
|
+
// from source. A bare `wrangler dev` against its pre-build wrangler.jsonc
|
|
331
|
+
// cannot bundle it at all (see `cf/build.ts`). The plugin takes no env file,
|
|
332
|
+
// so the scoped env rides the child's own environment instead.
|
|
333
|
+
const runtimeEnv = needsFrameworkBuild(app)
|
|
334
|
+
? undefined
|
|
335
|
+
: await createTemporaryWranglerEnv(app, loaded.env);
|
|
336
|
+
const child = spawn("pnpm", runtimeEnv
|
|
337
|
+
? [...wranglerDevArgs(app, port), "--env-file", runtimeEnv.path]
|
|
338
|
+
: vinextDevArgs(app, port), {
|
|
270
339
|
cwd: findRepoRoot(),
|
|
271
340
|
stdio: "inherit",
|
|
272
341
|
detached: process.platform !== "win32",
|
|
342
|
+
...(runtimeEnv
|
|
343
|
+
? {}
|
|
344
|
+
: { env: await scopedProcessEnv(app, loaded.env, "development") }),
|
|
273
345
|
});
|
|
274
346
|
let startupError;
|
|
275
347
|
child.once("error", (error) => {
|
|
@@ -278,57 +350,72 @@ async function startTemporaryWrangler(app, requestedPort) {
|
|
|
278
350
|
const deadline = Date.now() + WRANGLER_READY_TIMEOUT_MS;
|
|
279
351
|
while (Date.now() < deadline) {
|
|
280
352
|
if (await isWranglerDevRunning(port)) {
|
|
281
|
-
process.stdout.write(
|
|
353
|
+
process.stdout.write(`${runtime} is ready.\n`);
|
|
282
354
|
const stopOnParentExit = () => {
|
|
283
355
|
signalProcessGroup(child, "SIGTERM");
|
|
284
|
-
runtimeEnv
|
|
356
|
+
runtimeEnv?.remove();
|
|
285
357
|
};
|
|
286
358
|
process.once("exit", stopOnParentExit);
|
|
287
359
|
return {
|
|
288
360
|
stop: async () => {
|
|
289
361
|
process.off("exit", stopOnParentExit);
|
|
290
362
|
await stopTemporaryWrangler(child);
|
|
291
|
-
runtimeEnv
|
|
363
|
+
runtimeEnv?.remove();
|
|
292
364
|
},
|
|
293
365
|
forceStop: () => {
|
|
294
366
|
process.off("exit", stopOnParentExit);
|
|
295
367
|
signalProcessGroup(child, "SIGKILL");
|
|
296
|
-
runtimeEnv
|
|
368
|
+
runtimeEnv?.remove();
|
|
297
369
|
},
|
|
298
370
|
port,
|
|
299
371
|
};
|
|
300
372
|
}
|
|
301
373
|
if (startupError || child.exitCode !== null || child.signalCode !== null) {
|
|
302
|
-
|
|
303
|
-
|
|
374
|
+
// Name the exit status: a silent early exit is otherwise undiagnosable,
|
|
375
|
+
// since the runtime itself may print nothing on the way out.
|
|
376
|
+
const how = startupError
|
|
377
|
+
? `: ${startupError.message}`
|
|
378
|
+
: child.signalCode !== null
|
|
379
|
+
? ` (killed by ${child.signalCode}).`
|
|
380
|
+
: ` (exit ${child.exitCode}).`;
|
|
381
|
+
process.stderr.write(`devtools workflows run: ${runtime} stopped before it became ready${how}\n`);
|
|
382
|
+
runtimeEnv?.remove();
|
|
304
383
|
return null;
|
|
305
384
|
}
|
|
306
385
|
await delay(250);
|
|
307
386
|
}
|
|
308
387
|
await stopTemporaryWrangler(child);
|
|
309
|
-
runtimeEnv
|
|
310
|
-
process.stderr.write(`devtools workflows run:
|
|
388
|
+
runtimeEnv?.remove();
|
|
389
|
+
process.stderr.write(`devtools workflows run: ${runtime} did not become ready on port ${port} within ${WRANGLER_READY_TIMEOUT_MS / 60_000} minutes.\n`);
|
|
311
390
|
return null;
|
|
312
391
|
}
|
|
313
392
|
async function prepareLocalWrangler(app, initialPort) {
|
|
314
393
|
let port = initialPort;
|
|
394
|
+
if (!(await isWranglerDevRunning(port))) {
|
|
395
|
+
const dir = appDir(app);
|
|
396
|
+
const running = dir === undefined ? undefined : runningVinextDevPort(dir);
|
|
397
|
+
if (running !== undefined && (await isWranglerDevRunning(running))) {
|
|
398
|
+
process.stdout.write(`Using the vinext dev session already running for ${app} on port ${running}.\n`);
|
|
399
|
+
return { port: running };
|
|
400
|
+
}
|
|
401
|
+
}
|
|
315
402
|
while (!(await isWranglerDevRunning(port))) {
|
|
316
403
|
if (!process.stdin.isTTY) {
|
|
317
404
|
process.stderr.write(wranglerDevNotRunningHint(app, port));
|
|
318
405
|
return undefined;
|
|
319
406
|
}
|
|
320
407
|
const action = unwrap(await select({
|
|
321
|
-
message: `No
|
|
408
|
+
message: `No Workflow runtime (vinext dev or wrangler dev) was found on port ${port}.`,
|
|
322
409
|
options: [
|
|
323
410
|
{
|
|
324
411
|
value: "start",
|
|
325
|
-
label: "Start
|
|
412
|
+
label: "Start one temporarily",
|
|
326
413
|
hint: "stop it after this Workflow is triggered",
|
|
327
414
|
},
|
|
328
415
|
{
|
|
329
416
|
value: "port",
|
|
330
417
|
label: "Use another port",
|
|
331
|
-
hint: "
|
|
418
|
+
hint: "a dev session may already be running there",
|
|
332
419
|
},
|
|
333
420
|
{ value: "cancel", label: "Cancel" },
|
|
334
421
|
],
|
|
@@ -579,7 +666,7 @@ export async function runWorkflowsRun(argv) {
|
|
|
579
666
|
finally {
|
|
580
667
|
uninstallSignalCleanup?.();
|
|
581
668
|
if (local?.temporary) {
|
|
582
|
-
process.stdout.write("Stopping the temporary
|
|
669
|
+
process.stdout.write("Stopping the temporary dev session…\n");
|
|
583
670
|
await local.temporary.stop();
|
|
584
671
|
}
|
|
585
672
|
}
|
|
@@ -617,7 +704,14 @@ export async function runWorkflowsServe(argv) {
|
|
|
617
704
|
recordResolved("--port", port);
|
|
618
705
|
}
|
|
619
706
|
if (await isWranglerDevRunning(port)) {
|
|
620
|
-
process.stderr.write(`devtools workflows serve:
|
|
707
|
+
process.stderr.write(`devtools workflows serve: a Workflow runtime is already running on port ${port}.\n`);
|
|
708
|
+
return 1;
|
|
709
|
+
}
|
|
710
|
+
const dir = appDir(app);
|
|
711
|
+
const running = dir === undefined ? undefined : runningVinextDevPort(dir);
|
|
712
|
+
if (running !== undefined) {
|
|
713
|
+
process.stderr.write(`devtools workflows serve: vinext dev is already running for ${app} on port ${running}; ` +
|
|
714
|
+
"vinext allows one per app, and `workflows run` reuses it.\n");
|
|
621
715
|
return 1;
|
|
622
716
|
}
|
|
623
717
|
const session = await startTemporaryWrangler(app, port);
|
|
@@ -625,7 +719,7 @@ export async function runWorkflowsServe(argv) {
|
|
|
625
719
|
return 1;
|
|
626
720
|
// `session.port`, not `port`: the session auto-picks a free port when the
|
|
627
721
|
// requested one is taken, so this line must report where it actually landed.
|
|
628
|
-
process.stdout.write(`
|
|
722
|
+
process.stdout.write(`The dev session will keep running on port ${session.port}. Press Ctrl+C to stop it.\n`);
|
|
629
723
|
await new Promise((resolve) => {
|
|
630
724
|
// `process.on`, not `once`: `once` unregisters itself after the first
|
|
631
725
|
// signal, so a second Ctrl+C arriving during `session.stop()`'s up-to-
|
|
@@ -640,7 +734,7 @@ export async function runWorkflowsServe(argv) {
|
|
|
640
734
|
if (stopping) {
|
|
641
735
|
process.off("SIGINT", onSignal);
|
|
642
736
|
process.off("SIGTERM", onSignal);
|
|
643
|
-
process.stdout.write("Stopping
|
|
737
|
+
process.stdout.write("Stopping the dev session (forced)…\n");
|
|
644
738
|
session.forceStop();
|
|
645
739
|
process.kill(process.pid, signal);
|
|
646
740
|
return;
|
|
@@ -651,7 +745,7 @@ export async function runWorkflowsServe(argv) {
|
|
|
651
745
|
process.on("SIGINT", onSignal);
|
|
652
746
|
process.on("SIGTERM", onSignal);
|
|
653
747
|
});
|
|
654
|
-
process.stdout.write("Stopping
|
|
748
|
+
process.stdout.write("Stopping the dev session…\n");
|
|
655
749
|
await session.stop();
|
|
656
750
|
return 0;
|
|
657
751
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devdogsuga/devtools",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Contributor CLI for a DevDogsUGA checkout: database, env, images, emails, cron, deploy. Ships built JS; run via `pnpm dlx @devdogsuga/devtools` (or the `devtools`/`devtools-ci` bins once installed) from inside a DevDogsUGA clone.",
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@devdogsuga/brand": "*",
|
|
45
45
|
"@devdogsuga/db": "*",
|
|
46
|
-
"@devdogsuga/env": "*"
|
|
46
|
+
"@devdogsuga/env": "*",
|
|
47
|
+
"@devdogsuga/events": "*"
|
|
47
48
|
},
|
|
48
49
|
"peerDependenciesMeta": {
|
|
49
50
|
"@devdogsuga/brand": {
|
|
@@ -54,6 +55,9 @@
|
|
|
54
55
|
},
|
|
55
56
|
"@devdogsuga/env": {
|
|
56
57
|
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"@devdogsuga/events": {
|
|
60
|
+
"optional": true
|
|
57
61
|
}
|
|
58
62
|
},
|
|
59
63
|
"devDependencies": {
|
|
@@ -62,10 +66,11 @@
|
|
|
62
66
|
"@vitest/coverage-v8": "^4.1.11",
|
|
63
67
|
"react": "^19.2.8",
|
|
64
68
|
"vitest": "^4.1.11",
|
|
65
|
-
"@devdogsuga/config": "0.1.1",
|
|
66
|
-
"@devdogsuga/brand": "0.1.1",
|
|
67
69
|
"@devdogsuga/db": "0.1.1",
|
|
68
|
-
"@devdogsuga/env": "0.1.1"
|
|
70
|
+
"@devdogsuga/env": "0.1.1",
|
|
71
|
+
"@devdogsuga/brand": "0.1.2",
|
|
72
|
+
"@devdogsuga/events": "0.1.2",
|
|
73
|
+
"@devdogsuga/config": "0.1.1"
|
|
69
74
|
},
|
|
70
75
|
"scripts": {
|
|
71
76
|
"build": "tsc && node scripts/write-build-info.mjs",
|