@prisma/cli 3.0.0-dev.107.1 → 3.0.0-dev.108.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/cli2.js CHANGED
@@ -9,6 +9,7 @@ import "./shell/prompt.js";
9
9
  import { createAppCommand } from "./commands/app/index.js";
10
10
  import { createAuthCommand } from "./commands/auth/index.js";
11
11
  import { createBranchCommand } from "./commands/branch/index.js";
12
+ import { createBuildCommand } from "./commands/build/index.js";
12
13
  import { createDatabaseCommand } from "./commands/database/index.js";
13
14
  import { createGitCommand } from "./commands/git/index.js";
14
15
  import { createProjectCommand } from "./commands/project/index.js";
@@ -52,6 +53,7 @@ function createProgram(runtime) {
52
53
  program.addCommand(createProjectCommand(runtime));
53
54
  program.addCommand(createGitCommand(runtime));
54
55
  program.addCommand(createBranchCommand(runtime));
56
+ program.addCommand(createBuildCommand(runtime));
55
57
  program.addCommand(createDatabaseCommand(runtime));
56
58
  program.addCommand(createAppCommand(runtime));
57
59
  return program;
@@ -0,0 +1,29 @@
1
+ import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
+ import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
+ import { configureRuntimeCommand } from "../../shell/runtime.js";
4
+ import { runStreamingCommand } from "../../shell/command-runner.js";
5
+ import { runBuildLogs } from "../../controllers/build.js";
6
+ import { Command, Option } from "commander";
7
+ //#region src/commands/build/index.ts
8
+ function createBuildCommand(runtime) {
9
+ const build = attachCommandDescriptor(configureRuntimeCommand(new Command("build"), runtime), "build");
10
+ addCompactGlobalFlags(build);
11
+ build.addCommand(createLogsCommand(runtime));
12
+ return build;
13
+ }
14
+ function createLogsCommand(runtime) {
15
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("logs"), runtime), "build.logs");
16
+ command.argument("<buildId>", "Build id from a git-push or Console deploy").addOption(new Option("--follow", "Keep the connection open and stream new logs as the build runs")).addOption(new Option("--cursor <cursor>", "Resume from a prior terminal cursor"));
17
+ addGlobalFlags(command);
18
+ command.action(async (buildId, options) => {
19
+ const follow = options.follow;
20
+ const cursor = options.cursor;
21
+ await runStreamingCommand(runtime, "build.logs", options, (context) => runBuildLogs(context, buildId, {
22
+ follow,
23
+ cursor
24
+ }), { emitJsonSuccessEvent: false });
25
+ });
26
+ return command;
27
+ }
28
+ //#endregion
29
+ export { createBuildCommand };
@@ -0,0 +1,88 @@
1
+ import { CliError, authRequiredError } from "../shell/errors.js";
2
+ import { writeJsonEvent } from "../shell/output.js";
3
+ import { requireComputeAuth } from "../lib/auth/guard.js";
4
+ //#region src/controllers/build.ts
5
+ async function runBuildLogs(context, buildId, options = {}) {
6
+ const client = await requireComputeAuth(context.runtime.env, context.runtime.signal);
7
+ if (!client) throw authRequiredError(["prisma-cli auth login"]);
8
+ if (!context.flags.json && !context.flags.quiet) context.output.stderr.write(`build logs → Streaming logs for build ${buildId}\n\n`);
9
+ const { data, response } = await client.GET("/v1/builds/{buildId}/logs", {
10
+ params: {
11
+ path: { buildId },
12
+ query: {
13
+ ...options.follow ? { follow: "true" } : {},
14
+ ...options.cursor ? { cursor: options.cursor } : {}
15
+ }
16
+ },
17
+ parseAs: "stream",
18
+ signal: context.runtime.signal
19
+ });
20
+ const body = data;
21
+ if (!response.ok || !body) throw buildLogsRequestError(buildId, response.status);
22
+ let sawError = false;
23
+ await forEachNdjsonRecord(body, (record) => {
24
+ if (record.type === "terminal" && record.kind === "error") sawError = true;
25
+ writeBuildLogRecord(context, record);
26
+ });
27
+ if (sawError) process.exitCode = 1;
28
+ }
29
+ function writeBuildLogRecord(context, record) {
30
+ if (context.flags.json) {
31
+ writeJsonEvent(context.output, {
32
+ type: record.type,
33
+ command: "build.logs",
34
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
35
+ data: record
36
+ });
37
+ return;
38
+ }
39
+ if (record.type === "log") {
40
+ const stream = record.source === "stderr" || record.level === "error" ? context.output.stderr : context.output.stdout;
41
+ stream.write(record.text);
42
+ if (!record.text.endsWith("\n")) stream.write("\n");
43
+ return;
44
+ }
45
+ if (record.code !== "end") context.output.stderr.write(`${record.message}\n`);
46
+ }
47
+ /** Reads a newline-delimited JSON body line by line, parsing each into a record. */
48
+ async function forEachNdjsonRecord(body, onRecord) {
49
+ const reader = body.getReader();
50
+ const decoder = new TextDecoder();
51
+ let buffer = "";
52
+ for (;;) {
53
+ const { done, value } = await reader.read();
54
+ if (value) buffer += decoder.decode(value, { stream: true });
55
+ let newlineIndex = buffer.indexOf("\n");
56
+ while (newlineIndex !== -1) {
57
+ const line = buffer.slice(0, newlineIndex).trim();
58
+ buffer = buffer.slice(newlineIndex + 1);
59
+ if (line) onRecord(JSON.parse(line));
60
+ newlineIndex = buffer.indexOf("\n");
61
+ }
62
+ if (done) {
63
+ const tail = buffer.trim();
64
+ if (tail) onRecord(JSON.parse(tail));
65
+ return;
66
+ }
67
+ }
68
+ }
69
+ function buildLogsRequestError(buildId, status) {
70
+ if (status === 404) return new CliError({
71
+ code: "BUILD_NOT_FOUND",
72
+ domain: "app",
73
+ summary: `Build ${buildId} was not found`,
74
+ why: "The build does not exist, or your workspace does not have access to it.",
75
+ fix: "Check the build id, or run prisma-cli auth login to switch to the workspace that owns it.",
76
+ exitCode: 1
77
+ });
78
+ return new CliError({
79
+ code: "BUILD_LOGS_FAILED",
80
+ domain: "app",
81
+ summary: `Failed to read logs for build ${buildId}`,
82
+ why: `The Management API returned HTTP ${status}.`,
83
+ fix: "Retry the command, or rerun with --trace for more detail.",
84
+ exitCode: 1
85
+ });
86
+ }
87
+ //#endregion
88
+ export { runBuildLogs };
@@ -195,6 +195,22 @@ const DESCRIPTORS = [
195
195
  description: "View your Platform branches",
196
196
  examples: ["prisma-cli branch list"]
197
197
  },
198
+ {
199
+ id: "build",
200
+ path: ["prisma", "build"],
201
+ description: "Inspect builds",
202
+ examples: ["prisma-cli build logs <build_id>"]
203
+ },
204
+ {
205
+ id: "build.logs",
206
+ path: [
207
+ "prisma",
208
+ "build",
209
+ "logs"
210
+ ],
211
+ description: "Stream the logs for a build",
212
+ examples: ["prisma-cli build logs <build_id>", "prisma-cli build logs <build_id> --follow"]
213
+ },
198
214
  {
199
215
  id: "database",
200
216
  path: ["prisma", "database"],
@@ -75,12 +75,12 @@ async function renderBestEffortCommandDiagnostics(context, options) {
75
75
  return [];
76
76
  }
77
77
  }
78
- async function runStreamingCommand(runtime, commandName, options, handler) {
78
+ async function runStreamingCommand(runtime, commandName, options, handler, streamOptions) {
79
79
  const flags = resolveGlobalFlags(runtime.argv, options);
80
80
  const context = await createCommandContext(runtime, flags);
81
81
  try {
82
82
  await handler(context);
83
- if (flags.json) writeJsonEvent(context.output, {
83
+ if (flags.json && (streamOptions?.emitJsonSuccessEvent ?? true)) writeJsonEvent(context.output, {
84
84
  type: "success",
85
85
  command: commandName,
86
86
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/cli",
3
- "version": "3.0.0-dev.107.1",
3
+ "version": "3.0.0-dev.108.1",
4
4
  "description": "Command-line interface for the Prisma Developer Platform.",
5
5
  "type": "module",
6
6
  "bin": {