@prisma/composer-cli 0.11.0 → 0.12.0-dev.1
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/dist/bin.mjs +183 -175
- package/dist/bin.mjs.map +1 -1
- package/dist/{execute-deploy-destroy-DJ3BlpgU-DpcJjxvk.mjs → execute-deploy-destroy-Bsdh8hf4-BVXNSBmy.mjs} +4 -3
- package/dist/{execute-deploy-destroy-DJ3BlpgU-BCTSVylF.mjs.map → execute-deploy-destroy-Bsdh8hf4-BVXNSBmy.mjs.map} +1 -1
- package/dist/{execute-deploy-destroy-DJ3BlpgU-BCTSVylF.mjs → execute-deploy-destroy-Bsdh8hf4-CZVPrQtx.mjs} +4 -3
- package/dist/{execute-deploy-destroy-DJ3BlpgU-DpcJjxvk.mjs.map → execute-deploy-destroy-Bsdh8hf4-CZVPrQtx.mjs.map} +1 -1
- package/dist/{execute-dev-CQ0Lo2eN-DBThEMBv.mjs → execute-dev-CQ0Lo2eN-DxMcOjxh.mjs} +2 -2
- package/dist/{execute-dev-CQ0Lo2eN-DBThEMBv.mjs.map → execute-dev-CQ0Lo2eN-DxMcOjxh.mjs.map} +1 -1
- package/dist/{execute-dev-CQ0Lo2eN-BBNilsxZ.mjs → execute-dev-CQ0Lo2eN-WebHkuDn.mjs} +2 -2
- package/dist/{execute-dev-CQ0Lo2eN-BBNilsxZ.mjs.map → execute-dev-CQ0Lo2eN-WebHkuDn.mjs.map} +1 -1
- package/dist/{execute-log-CUzTOzSj-31WISHGD.mjs → execute-log-CUzTOzSj-BndClj6B.mjs} +2 -2
- package/dist/{execute-log-CUzTOzSj-31WISHGD.mjs.map → execute-log-CUzTOzSj-BndClj6B.mjs.map} +1 -1
- package/dist/{execute-log-CUzTOzSj-ERhhGgwJ.mjs → execute-log-CUzTOzSj-DPxnEKA2.mjs} +2 -2
- package/dist/{execute-log-CUzTOzSj-ERhhGgwJ.mjs.map → execute-log-CUzTOzSj-DPxnEKA2.mjs.map} +1 -1
- package/dist/{family-BqgXAnt0-BilZvb88.d.mts → family-BqgXAnt0-CU2L1I6j.d.mts} +50 -3
- package/dist/{family-BqgXAnt0-BilZvb88.d.mts.map → family-BqgXAnt0-CU2L1I6j.d.mts.map} +1 -1
- package/dist/family.d.mts +1 -1
- package/dist/family.mjs +182 -174
- package/dist/family.mjs.map +1 -1
- package/dist/{pipeline-Bt8QocRh-BWGl-fzK.mjs → pipeline-Bt8QocRh-BGjwJqNH.mjs} +138 -10
- package/dist/pipeline-Bt8QocRh-BGjwJqNH.mjs.map +1 -0
- package/dist/{pipeline-Bt8QocRh-DWh8gbfz.mjs → pipeline-Bt8QocRh-B_yOh-0h.mjs} +138 -10
- package/dist/pipeline-Bt8QocRh-B_yOh-0h.mjs.map +1 -0
- package/dist/testing.d.mts +1 -1
- package/package.json +6 -6
- package/dist/pipeline-Bt8QocRh-BWGl-fzK.mjs.map +0 -1
- package/dist/pipeline-Bt8QocRh-DWh8gbfz.mjs.map +0 -1
package/dist/bin.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { spawn } from "node:child_process";
|
|
|
7
7
|
import { EnvironmentCredentialManager, createCli, defineCommand, defineCommandFamily, defineConfigSection, defineSessionCommand, exitWithChildStatus, flag, loadConfig, positional } from "@prisma/cli-engine";
|
|
8
8
|
import { CliStructuredError, notOk, ok } from "@prisma/cli-engine/protocol";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
|
-
//#region ../../0-framework/3-tooling/cli/dist/log-
|
|
10
|
+
//#region ../../0-framework/3-tooling/cli/dist/log-E_5UMZl8.mjs
|
|
11
11
|
/** In-package variant threading the injection seam (the CLI's RunDeps, unit
|
|
12
12
|
* tests). Deliberately NOT re-exported through `./control` — the seam mirrors
|
|
13
13
|
* internal types and is not part of the published surface. */
|
|
@@ -15,7 +15,7 @@ async function deployWithDeps(input, deps) {
|
|
|
15
15
|
const cwd = input.cwd ?? process.cwd();
|
|
16
16
|
let executor;
|
|
17
17
|
try {
|
|
18
|
-
executor = await import("./execute-deploy-destroy-
|
|
18
|
+
executor = await import("./execute-deploy-destroy-Bsdh8hf4-BVXNSBmy.mjs");
|
|
19
19
|
} catch (error) {
|
|
20
20
|
return notOk$1(executorLoadFailure("deploy", error, cwd));
|
|
21
21
|
}
|
|
@@ -28,7 +28,7 @@ async function destroyWithDeps(input, deps) {
|
|
|
28
28
|
const cwd = input.cwd ?? process.cwd();
|
|
29
29
|
let executor;
|
|
30
30
|
try {
|
|
31
|
-
executor = await import("./execute-deploy-destroy-
|
|
31
|
+
executor = await import("./execute-deploy-destroy-Bsdh8hf4-BVXNSBmy.mjs");
|
|
32
32
|
} catch (error) {
|
|
33
33
|
return notOk$1(executorLoadFailure("destroy", error, cwd));
|
|
34
34
|
}
|
|
@@ -41,7 +41,7 @@ async function devWithDeps(input, deps) {
|
|
|
41
41
|
const cwd = input.cwd ?? process.cwd();
|
|
42
42
|
let executor;
|
|
43
43
|
try {
|
|
44
|
-
executor = await import("./execute-dev-CQ0Lo2eN-
|
|
44
|
+
executor = await import("./execute-dev-CQ0Lo2eN-WebHkuDn.mjs");
|
|
45
45
|
} catch (error) {
|
|
46
46
|
return notOk$1(executorLoadFailure("dev", error, cwd));
|
|
47
47
|
}
|
|
@@ -54,14 +54,14 @@ async function logWithDeps(input, deps) {
|
|
|
54
54
|
const cwd = input.cwd ?? process.cwd();
|
|
55
55
|
let executor;
|
|
56
56
|
try {
|
|
57
|
-
executor = await import("./execute-log-CUzTOzSj-
|
|
57
|
+
executor = await import("./execute-log-CUzTOzSj-DPxnEKA2.mjs");
|
|
58
58
|
} catch (error) {
|
|
59
59
|
return notOk$1(executorLoadFailure("log", error, cwd));
|
|
60
60
|
}
|
|
61
61
|
return executor.executeLog(input, deps, cwd);
|
|
62
62
|
}
|
|
63
63
|
//#endregion
|
|
64
|
-
//#region ../../0-framework/3-tooling/cli/dist/engine-cli-
|
|
64
|
+
//#region ../../0-framework/3-tooling/cli/dist/engine-cli-BI4fPmYY.mjs
|
|
65
65
|
/**
|
|
66
66
|
* The family boundary's error translation.
|
|
67
67
|
*
|
|
@@ -269,6 +269,23 @@ const composerSection = defineConfigSection({
|
|
|
269
269
|
validate
|
|
270
270
|
});
|
|
271
271
|
/**
|
|
272
|
+
* `destroy`'s target, from its two mutually exclusive flags. Kept out of the
|
|
273
|
+
* grammar because the engine's flag layer has no "exactly one of these"
|
|
274
|
+
* construct — and because both wrong shapes need their own remedy, which a
|
|
275
|
+
* generic arity error could not give.
|
|
276
|
+
*/
|
|
277
|
+
function targetOf(stage, production) {
|
|
278
|
+
if (stage !== void 0 && production) return notOk(new CliStructuredError("DEPLOY.TARGET_CONFLICT", "Pass either --stage <name> or --production to `destroy`, not both."));
|
|
279
|
+
if (stage === void 0 && !production) return notOk(new CliStructuredError("DEPLOY.TARGET_MISSING", "`destroy` requires an explicit target.", { nextActions: [{
|
|
280
|
+
kind: "user-choice",
|
|
281
|
+
label: "Pass --stage <name> to tear down a branch environment, or --production to tear down the production environment."
|
|
282
|
+
}] }));
|
|
283
|
+
return ok(stage !== void 0 ? {
|
|
284
|
+
kind: "stage",
|
|
285
|
+
stage
|
|
286
|
+
} : { kind: "production" });
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
272
289
|
* The workspace the in-process leg acts in, from the engine's credential
|
|
273
290
|
* read. Handlers never decode a token and never read PRISMA_WORKSPACE_ID:
|
|
274
291
|
* whether the credential came from a stored session or the environment, the
|
|
@@ -283,16 +300,18 @@ async function workspaceIdOf(ctx) {
|
|
|
283
300
|
return (await ctx.activeCredential())?.workspaceId;
|
|
284
301
|
}
|
|
285
302
|
/**
|
|
286
|
-
* `
|
|
303
|
+
* `destroy <entry>` — deploy's mirror: same derivation, alchemy destroy.
|
|
287
304
|
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
305
|
+
* No confirmation prompt, matching the CLI this replaces. The front door
|
|
306
|
+
* cannot know what the child will tear down, so a consent step here would be
|
|
307
|
+
* asking the user to approve a list nobody has computed yet; if destroy
|
|
308
|
+
* deserves one it belongs in composer's own operation, not in the grammar.
|
|
291
309
|
*/
|
|
292
|
-
const
|
|
310
|
+
const createDestroyCommand = (operations) => defineCommand({
|
|
293
311
|
help: {
|
|
294
|
-
summary: "
|
|
295
|
-
|
|
312
|
+
summary: "Tear down the application whose root node is <entry>'s default export.",
|
|
313
|
+
description: "Same derivation as deploy. Requires an explicit target: --stage <name> for a branch environment, or --production for the production environment.",
|
|
314
|
+
examples: ["{bin} destroy src/service.ts --stage feat-auth", "{bin} destroy src/service.ts --production"]
|
|
296
315
|
},
|
|
297
316
|
args: {
|
|
298
317
|
positionals: { entry: positional.string({
|
|
@@ -301,21 +320,14 @@ const createDeployCommand = (operations) => defineCommand({
|
|
|
301
320
|
}) },
|
|
302
321
|
flags: {
|
|
303
322
|
name: flag.string({
|
|
304
|
-
brief: "Override the root node's name — the
|
|
323
|
+
brief: "Override the root node's name — the application name to tear down.",
|
|
305
324
|
placeholder: "name"
|
|
306
325
|
}),
|
|
307
326
|
stage: flag.string({
|
|
308
|
-
brief: "
|
|
327
|
+
brief: "Tear down this branch environment.",
|
|
309
328
|
placeholder: "stage"
|
|
310
329
|
}),
|
|
311
|
-
|
|
312
|
-
brief: "Write the deploy's outcome as JSON to this path — resources, preview URLs, and the failure cause. Also settable as PRISMA_COMPOSER_REPORT_FILE.",
|
|
313
|
-
placeholder: "path"
|
|
314
|
-
}),
|
|
315
|
-
buildId: flag.string({
|
|
316
|
-
brief: "Join the deploy record your CI already created rather than letting the target create one. Each target also reads its own environment variable for this; the flag wins.",
|
|
317
|
-
placeholder: "id"
|
|
318
|
-
})
|
|
330
|
+
production: flag.boolean({ brief: "Tear down the project-level production environment." })
|
|
319
331
|
}
|
|
320
332
|
},
|
|
321
333
|
needs: {
|
|
@@ -324,69 +336,129 @@ const createDeployCommand = (operations) => defineCommand({
|
|
|
324
336
|
},
|
|
325
337
|
maySpawn: true,
|
|
326
338
|
handler: async (args, ctx) => {
|
|
339
|
+
const target = targetOf(args.flags.stage, args.flags.production);
|
|
340
|
+
if (!target.ok) return target;
|
|
327
341
|
const alchemy = convergeSpawn(ctx);
|
|
328
|
-
return settleConverge(await operations.
|
|
342
|
+
return settleConverge(await operations.destroy({
|
|
329
343
|
entry: args.positionals.entry,
|
|
330
344
|
name: args.flags.name,
|
|
331
|
-
|
|
345
|
+
target: target.value,
|
|
332
346
|
cwd: ctx.cwd,
|
|
333
|
-
|
|
334
|
-
|
|
347
|
+
onEvent: (event) => {
|
|
348
|
+
if (event.kind !== "no-local-deploy-state") return;
|
|
349
|
+
ctx.report({
|
|
350
|
+
kind: "message",
|
|
351
|
+
severity: "warn",
|
|
352
|
+
text: `No prior deploy state under ${event.cwd} — if you deployed from a different directory, run destroy from there; otherwise this is a no-op.`
|
|
353
|
+
});
|
|
354
|
+
}
|
|
335
355
|
}, operationDeps({
|
|
336
356
|
alchemy,
|
|
337
357
|
configPath: ctx.config.configPath,
|
|
338
358
|
workspaceId: await workspaceIdOf(ctx),
|
|
339
359
|
client: ctx.api
|
|
340
|
-
})), ctx, (
|
|
341
|
-
human: (
|
|
342
|
-
kind: "summary",
|
|
343
|
-
status: "ok",
|
|
344
|
-
text: "Deployed."
|
|
345
|
-
}] : [{
|
|
360
|
+
})), ctx, () => ctx.present({ data: void 0 }, {
|
|
361
|
+
human: () => [{
|
|
346
362
|
kind: "summary",
|
|
347
363
|
status: "ok",
|
|
348
|
-
text:
|
|
349
|
-
}, {
|
|
350
|
-
kind: "table",
|
|
351
|
-
columns: ["Address", "Deployed"],
|
|
352
|
-
rows: summary.nodes.map((node) => [node.address, node.entities.map((entity) => `${entity.kind} ${entity.id}`).join(", ")])
|
|
364
|
+
text: "Destroyed."
|
|
353
365
|
}],
|
|
354
366
|
stdout: () => [],
|
|
355
|
-
json: () =>
|
|
367
|
+
json: () => void 0,
|
|
356
368
|
next: () => []
|
|
357
369
|
}));
|
|
358
370
|
}
|
|
359
371
|
});
|
|
360
372
|
/**
|
|
361
|
-
* `
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
373
|
+
* `log <entry> [address]` — a session command that tails the merged logs of
|
|
374
|
+
* the app running locally on this machine.
|
|
375
|
+
*
|
|
376
|
+
* It reads the LOCAL dev-emulator daemon, not the platform's logs surface, so
|
|
377
|
+
* it is credential-free. It hands the terminal to nothing, which is why it
|
|
378
|
+
* does not declare `maySpawn` and keeps json support: the log lines ARE its
|
|
379
|
+
* json surface.
|
|
380
|
+
*
|
|
381
|
+
* Windows is refused inside the operation itself (LOG.PLATFORM_UNSUPPORTED),
|
|
382
|
+
* which is why nothing here reads the platform.
|
|
365
383
|
*/
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
384
|
+
/** An empty screen reads as broken, so show a little recent history before going live. */
|
|
385
|
+
const DEFAULT_TAIL = 20;
|
|
386
|
+
const createLogCommand = (operations) => defineSessionCommand({
|
|
387
|
+
help: {
|
|
388
|
+
summary: "Tail the merged logs of the locally-running application whose root node is <entry>'s default export.",
|
|
389
|
+
examples: ["{bin} log src/service.ts", "{bin} log src/service.ts catalog.service"]
|
|
390
|
+
},
|
|
391
|
+
args: {
|
|
392
|
+
positionals: {
|
|
393
|
+
entry: positional.string({
|
|
394
|
+
brief: "The module whose default export is the application root.",
|
|
395
|
+
placeholder: "entry"
|
|
396
|
+
}),
|
|
397
|
+
address: positional.optionalString({
|
|
398
|
+
brief: "Only this service's lines, by its dotted address (catalog.service); every service when absent.",
|
|
399
|
+
placeholder: "address"
|
|
400
|
+
})
|
|
401
|
+
},
|
|
402
|
+
flags: {
|
|
403
|
+
name: flag.string({
|
|
404
|
+
brief: "Override the root node's name — the dev instance's application name.",
|
|
405
|
+
placeholder: "name"
|
|
406
|
+
}),
|
|
407
|
+
tail: flag.number({
|
|
408
|
+
brief: `How many trailing history lines to show before live output (default ${String(DEFAULT_TAIL)}).`,
|
|
409
|
+
placeholder: "lines",
|
|
410
|
+
default: DEFAULT_TAIL
|
|
411
|
+
})
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
needs: { config: composerSection },
|
|
415
|
+
handler: async (args, ctx) => {
|
|
416
|
+
const reportLogEvent = (event) => {
|
|
417
|
+
ctx.report({
|
|
418
|
+
kind: "message",
|
|
419
|
+
severity: "warn",
|
|
420
|
+
text: event.kind === "stream-failed" ? `Stream failed: ${event.message}` : `Falling behind — dropped the ${String(event.count)} oldest lines.`
|
|
421
|
+
});
|
|
422
|
+
};
|
|
423
|
+
const result = await operations.log({
|
|
424
|
+
entry: args.positionals.entry,
|
|
425
|
+
name: args.flags.name,
|
|
426
|
+
address: args.positionals.address,
|
|
427
|
+
tail: args.flags.tail ?? DEFAULT_TAIL,
|
|
428
|
+
cwd: ctx.cwd,
|
|
429
|
+
signal: ctx.signal,
|
|
430
|
+
onEvent: reportLogEvent
|
|
431
|
+
}, { configPath: ctx.config.configPath });
|
|
432
|
+
if (!result.ok) return notOk(toEngineError(result.failure));
|
|
433
|
+
const attached = result.value;
|
|
434
|
+
if (attached.services.length === 0) {
|
|
435
|
+
ctx.report({
|
|
436
|
+
kind: "message",
|
|
437
|
+
severity: "warn",
|
|
438
|
+
text: `No running services for "${attached.appName}" — start it first with \`dev ${args.positionals.entry}\`.`
|
|
439
|
+
});
|
|
440
|
+
return ok(void 0);
|
|
441
|
+
}
|
|
442
|
+
for await (const { service, line } of attached.lines) ctx.report({
|
|
443
|
+
kind: "output",
|
|
444
|
+
source: service,
|
|
445
|
+
channel: "data",
|
|
446
|
+
line: `[${service}] ${line}`
|
|
447
|
+
});
|
|
448
|
+
return ok(void 0);
|
|
449
|
+
}
|
|
450
|
+
});
|
|
377
451
|
/**
|
|
378
|
-
* `
|
|
452
|
+
* `deploy <entry>` — a result command that hands the terminal to alchemy.
|
|
379
453
|
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
* deserves one it belongs in composer's own operation, not in the grammar.
|
|
454
|
+
* `--production` is gone. It was accepted and then always errored ("only
|
|
455
|
+
* valid with destroy"), so no invocation using it could ever have succeeded;
|
|
456
|
+
* deploy targets production by default when no `--stage` is given.
|
|
384
457
|
*/
|
|
385
|
-
const
|
|
458
|
+
const createDeployCommand = (operations) => defineCommand({
|
|
386
459
|
help: {
|
|
387
|
-
summary: "
|
|
388
|
-
|
|
389
|
-
examples: ["{bin} destroy src/service.ts --stage feat-auth", "{bin} destroy src/service.ts --production"]
|
|
460
|
+
summary: "Deploy the application whose root node is <entry>'s default export.",
|
|
461
|
+
examples: ["{bin} deploy src/service.ts", "{bin} deploy src/service.ts --stage feat-auth"]
|
|
390
462
|
},
|
|
391
463
|
args: {
|
|
392
464
|
positionals: { entry: positional.string({
|
|
@@ -395,14 +467,21 @@ const createDestroyCommand = (operations) => defineCommand({
|
|
|
395
467
|
}) },
|
|
396
468
|
flags: {
|
|
397
469
|
name: flag.string({
|
|
398
|
-
brief: "Override the root node's name — the application name
|
|
470
|
+
brief: "Override the root node's name — the deploy's application name.",
|
|
399
471
|
placeholder: "name"
|
|
400
472
|
}),
|
|
401
473
|
stage: flag.string({
|
|
402
|
-
brief: "
|
|
474
|
+
brief: "Deploy scope to target; omit for production.",
|
|
403
475
|
placeholder: "stage"
|
|
404
476
|
}),
|
|
405
|
-
|
|
477
|
+
report: flag.string({
|
|
478
|
+
brief: "Write the deploy's outcome as JSON to this path — resources, preview URLs, and the failure cause. Also settable as PRISMA_COMPOSER_REPORT_FILE.",
|
|
479
|
+
placeholder: "path"
|
|
480
|
+
}),
|
|
481
|
+
buildId: flag.string({
|
|
482
|
+
brief: "Join the deploy record your CI already created rather than letting the target create one. Each target also reads its own environment variable for this; the flag wins.",
|
|
483
|
+
placeholder: "id"
|
|
484
|
+
})
|
|
406
485
|
}
|
|
407
486
|
},
|
|
408
487
|
needs: {
|
|
@@ -411,35 +490,35 @@ const createDestroyCommand = (operations) => defineCommand({
|
|
|
411
490
|
},
|
|
412
491
|
maySpawn: true,
|
|
413
492
|
handler: async (args, ctx) => {
|
|
414
|
-
const target = targetOf(args.flags.stage, args.flags.production);
|
|
415
|
-
if (!target.ok) return target;
|
|
416
493
|
const alchemy = convergeSpawn(ctx);
|
|
417
|
-
return settleConverge(await operations.
|
|
494
|
+
return settleConverge(await operations.deploy({
|
|
418
495
|
entry: args.positionals.entry,
|
|
419
496
|
name: args.flags.name,
|
|
420
|
-
|
|
497
|
+
stage: args.flags.stage,
|
|
421
498
|
cwd: ctx.cwd,
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
ctx.report({
|
|
425
|
-
kind: "message",
|
|
426
|
-
severity: "warn",
|
|
427
|
-
text: `No prior deploy state under ${event.cwd} — if you deployed from a different directory, run destroy from there; otherwise this is a no-op.`
|
|
428
|
-
});
|
|
429
|
-
}
|
|
499
|
+
reportPath: args.flags.report,
|
|
500
|
+
reportId: args.flags.buildId
|
|
430
501
|
}, operationDeps({
|
|
431
502
|
alchemy,
|
|
432
503
|
configPath: ctx.config.configPath,
|
|
433
504
|
workspaceId: await workspaceIdOf(ctx),
|
|
434
505
|
client: ctx.api
|
|
435
|
-
})), ctx, () => ctx.present({ data:
|
|
436
|
-
human: () => [{
|
|
506
|
+
})), ctx, ({ summary }) => ctx.present({ data: { summary: summary ?? null } }, {
|
|
507
|
+
human: (ui) => summary === void 0 ? [{
|
|
437
508
|
kind: "summary",
|
|
438
509
|
status: "ok",
|
|
439
|
-
text: "
|
|
510
|
+
text: "Deployed."
|
|
511
|
+
}] : [{
|
|
512
|
+
kind: "summary",
|
|
513
|
+
status: "ok",
|
|
514
|
+
text: `Deployed ${ui.emphasize(summary.app)}.`
|
|
515
|
+
}, {
|
|
516
|
+
kind: "table",
|
|
517
|
+
columns: ["Address", "Deployed"],
|
|
518
|
+
rows: summary.nodes.map((node) => [node.address, node.entities.map((entity) => `${entity.kind} ${entity.id}`).join(", ")])
|
|
440
519
|
}],
|
|
441
520
|
stdout: () => [],
|
|
442
|
-
json: () =>
|
|
521
|
+
json: () => ({ summary: summary ?? null }),
|
|
443
522
|
next: () => []
|
|
444
523
|
}));
|
|
445
524
|
}
|
|
@@ -581,7 +660,7 @@ Generated stack file: ${event.stackFilePath}\nRun \`${event.reproduceCommand}\`
|
|
|
581
660
|
const createDevCommand = (operations) => defineSessionCommand({
|
|
582
661
|
help: {
|
|
583
662
|
summary: "Bring up the application whose root node is <entry>'s default export, entirely on this machine.",
|
|
584
|
-
description: "Runs credential-free and watches the app for changes, reconverging on every edit.
|
|
663
|
+
description: "Runs credential-free and watches the app for changes, reconverging on every edit.",
|
|
585
664
|
examples: ["{bin} dev src/service.ts", "{bin} dev src/service.ts --fresh"]
|
|
586
665
|
},
|
|
587
666
|
args: {
|
|
@@ -618,85 +697,6 @@ const createDevCommand = (operations) => defineSessionCommand({
|
|
|
618
697
|
}
|
|
619
698
|
});
|
|
620
699
|
/**
|
|
621
|
-
* `log <entry> [address]` — a session command that tails the merged logs of
|
|
622
|
-
* the app running locally on this machine.
|
|
623
|
-
*
|
|
624
|
-
* It reads the LOCAL dev-emulator daemon, not the platform's logs surface, so
|
|
625
|
-
* it is credential-free. It hands the terminal to nothing, which is why it
|
|
626
|
-
* does not declare `maySpawn` and keeps json support: the log lines ARE its
|
|
627
|
-
* json surface.
|
|
628
|
-
*
|
|
629
|
-
* Windows is refused inside the operation itself (LOG.PLATFORM_UNSUPPORTED),
|
|
630
|
-
* which is why nothing here reads the platform.
|
|
631
|
-
*/
|
|
632
|
-
/** An empty screen reads as broken, so show a little recent history before going live. */
|
|
633
|
-
const DEFAULT_TAIL = 20;
|
|
634
|
-
const createLogCommand = (operations) => defineSessionCommand({
|
|
635
|
-
help: {
|
|
636
|
-
summary: "Tail the merged logs of the locally-running application whose root node is <entry>'s default export.",
|
|
637
|
-
examples: ["{bin} log src/service.ts", "{bin} log src/service.ts catalog.service"]
|
|
638
|
-
},
|
|
639
|
-
args: {
|
|
640
|
-
positionals: {
|
|
641
|
-
entry: positional.string({
|
|
642
|
-
brief: "The module whose default export is the application root.",
|
|
643
|
-
placeholder: "entry"
|
|
644
|
-
}),
|
|
645
|
-
address: positional.optionalString({
|
|
646
|
-
brief: "Only this service's lines, by its dotted address (catalog.service); every service when absent.",
|
|
647
|
-
placeholder: "address"
|
|
648
|
-
})
|
|
649
|
-
},
|
|
650
|
-
flags: {
|
|
651
|
-
name: flag.string({
|
|
652
|
-
brief: "Override the root node's name — the dev instance's application name.",
|
|
653
|
-
placeholder: "name"
|
|
654
|
-
}),
|
|
655
|
-
tail: flag.number({
|
|
656
|
-
brief: `How many trailing history lines to show before live output (default ${String(DEFAULT_TAIL)}).`,
|
|
657
|
-
placeholder: "lines",
|
|
658
|
-
default: DEFAULT_TAIL
|
|
659
|
-
})
|
|
660
|
-
}
|
|
661
|
-
},
|
|
662
|
-
needs: { config: composerSection },
|
|
663
|
-
handler: async (args, ctx) => {
|
|
664
|
-
const reportLogEvent = (event) => {
|
|
665
|
-
ctx.report({
|
|
666
|
-
kind: "message",
|
|
667
|
-
severity: "warn",
|
|
668
|
-
text: event.kind === "stream-failed" ? `Stream failed: ${event.message}` : `Falling behind — dropped the ${String(event.count)} oldest lines.`
|
|
669
|
-
});
|
|
670
|
-
};
|
|
671
|
-
const result = await operations.log({
|
|
672
|
-
entry: args.positionals.entry,
|
|
673
|
-
name: args.flags.name,
|
|
674
|
-
address: args.positionals.address,
|
|
675
|
-
tail: args.flags.tail ?? DEFAULT_TAIL,
|
|
676
|
-
cwd: ctx.cwd,
|
|
677
|
-
signal: ctx.signal,
|
|
678
|
-
onEvent: reportLogEvent
|
|
679
|
-
}, { configPath: ctx.config.configPath });
|
|
680
|
-
if (!result.ok) return notOk(toEngineError(result.failure));
|
|
681
|
-
const attached = result.value;
|
|
682
|
-
if (attached.services.length === 0) {
|
|
683
|
-
ctx.report({
|
|
684
|
-
kind: "message",
|
|
685
|
-
severity: "warn",
|
|
686
|
-
text: `No running services for "${attached.appName}" — start it first with \`dev ${args.positionals.entry}\`.`
|
|
687
|
-
});
|
|
688
|
-
return ok(void 0);
|
|
689
|
-
}
|
|
690
|
-
for await (const { service, line } of attached.lines) ctx.report({
|
|
691
|
-
kind: "output",
|
|
692
|
-
source: service,
|
|
693
|
-
channel: "data",
|
|
694
|
-
line: `[${service}] ${line}`
|
|
695
|
-
});
|
|
696
|
-
return ok(void 0);
|
|
697
|
-
}
|
|
698
|
-
});
|
|
699
|
-
/**
|
|
700
700
|
* Composer's `CommandFamily` — the unit the engine mounts, whether the process
|
|
701
701
|
* is composer's own CLI or the `prisma` bin.
|
|
702
702
|
*
|
|
@@ -711,9 +711,14 @@ const createLogCommand = (operations) => defineSessionCommand({
|
|
|
711
711
|
* scripts/check-family-static-graph.mjs enforces this against BUILT output,
|
|
712
712
|
* where type-only imports have already been erased.
|
|
713
713
|
*
|
|
714
|
-
* The
|
|
714
|
+
* The commands close over the operations they are given, so a host can
|
|
715
715
|
* mount this family against the test double and exercise real grammar, real
|
|
716
716
|
* arg validation and real handlers with no alchemy behind them.
|
|
717
|
+
*
|
|
718
|
+
* The family ships `deploy` and `dev` only: `destroy` and `log` were retired
|
|
719
|
+
* from the family surface (2026-08-21 PM review), so hosts mounting the family
|
|
720
|
+
* — the `prisma` bin — never see them. They remain first-class commands of
|
|
721
|
+
* composer's own bin, mounted on top of the family in engine-cli.ts.
|
|
717
722
|
*/
|
|
718
723
|
const realOperations = {
|
|
719
724
|
deploy: deployWithDeps,
|
|
@@ -727,9 +732,7 @@ function createComposerFamily(options = {}) {
|
|
|
727
732
|
configSection: composerSection,
|
|
728
733
|
commands: {
|
|
729
734
|
deploy: createDeployCommand(operations),
|
|
730
|
-
|
|
731
|
-
dev: createDevCommand(operations),
|
|
732
|
-
log: createLogCommand(operations)
|
|
735
|
+
dev: createDevCommand(operations)
|
|
733
736
|
},
|
|
734
737
|
docsBaseUrl: DOCS_BASE
|
|
735
738
|
});
|
|
@@ -898,22 +901,27 @@ function createRuntime(host, loadConfig) {
|
|
|
898
901
|
const BINARY_NAME = "prisma-composer";
|
|
899
902
|
/**
|
|
900
903
|
* Composer's commands mount at the top level of its own CLI (`prisma-composer
|
|
901
|
-
* deploy`)
|
|
902
|
-
*
|
|
903
|
-
*
|
|
904
|
-
*
|
|
904
|
+
* deploy`). The bin mounts more than the family carries: `destroy` and `log`
|
|
905
|
+
* were retired from the family (the surface the `prisma` bin mounts, per the
|
|
906
|
+
* 2026-08-21 PM review) but stay first-class commands of `prisma-composer`
|
|
907
|
+
* itself, so their definitions are mounted here on top of the family.
|
|
905
908
|
*/
|
|
906
|
-
function mountedTree(family) {
|
|
907
|
-
return {
|
|
909
|
+
function mountedTree(family, operations) {
|
|
910
|
+
return {
|
|
911
|
+
...family.commands,
|
|
912
|
+
destroy: createDestroyCommand(operations),
|
|
913
|
+
log: createLogCommand(operations)
|
|
914
|
+
};
|
|
908
915
|
}
|
|
909
916
|
function createComposerCli(spec) {
|
|
910
|
-
const
|
|
917
|
+
const operations = spec.operations ?? realOperations;
|
|
918
|
+
const family = createComposerFamily({ operations });
|
|
911
919
|
return createCli({
|
|
912
920
|
name: BINARY_NAME,
|
|
913
921
|
version: spec.version,
|
|
914
922
|
commandFamilies: [family],
|
|
915
923
|
groups: {},
|
|
916
|
-
commands: mountedTree(family)
|
|
924
|
+
commands: mountedTree(family, operations)
|
|
917
925
|
});
|
|
918
926
|
}
|
|
919
927
|
/**
|
|
@@ -932,7 +940,7 @@ function runComposerCli(argv, host, spec, hooks) {
|
|
|
932
940
|
return createComposerCli(spec).run(argv, runtime, hooks);
|
|
933
941
|
}
|
|
934
942
|
//#endregion
|
|
935
|
-
//#region ../../0-framework/3-tooling/cli/dist/cli-
|
|
943
|
+
//#region ../../0-framework/3-tooling/cli/dist/cli-B4o-gpsM.mjs
|
|
936
944
|
/**
|
|
937
945
|
* The `prisma-composer` entrypoint: adapt this process into the engine's
|
|
938
946
|
* `HostProcess`, run one invocation of composer's own CLI, and hand back an
|