@prisma/cli 8.0.0-rc.5 → 8.0.0-rc.5-dev.65
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 +28 -29
- package/dist/cli.js +79 -20
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -15,15 +15,9 @@
|
|
|
15
15
|
`@prisma/cli` is the public beta of the new CLI for the
|
|
16
16
|
Prisma Developer Platform.
|
|
17
17
|
|
|
18
|
-
It is
|
|
19
|
-
deployments,
|
|
20
|
-
|
|
21
|
-
The command model is under active development to include tooling for your
|
|
22
|
-
schema, database, migration, and broader platform workflows.
|
|
23
|
-
|
|
24
|
-
Looking for Prisma ORM commands such as `prisma generate`, `prisma migrate`, or
|
|
25
|
-
`prisma studio`? Use the [`prisma`](https://www.npmjs.com/package/prisma)
|
|
26
|
-
package.
|
|
18
|
+
It is one binary for the ORM, Composer, and the Prisma Developer
|
|
19
|
+
Platform: projects, branches, services, deployments, environment
|
|
20
|
+
variables, and the Prisma ORM schema and migration workflow.
|
|
27
21
|
|
|
28
22
|
---
|
|
29
23
|
|
|
@@ -32,7 +26,7 @@ package.
|
|
|
32
26
|
Install the beta package locally:
|
|
33
27
|
|
|
34
28
|
```bash
|
|
35
|
-
npm install --save-dev @prisma/cli
|
|
29
|
+
npm install --save-dev @prisma/cli@next
|
|
36
30
|
```
|
|
37
31
|
|
|
38
32
|
Run the binary exposed by this package:
|
|
@@ -40,22 +34,26 @@ Run the binary exposed by this package:
|
|
|
40
34
|
```bash
|
|
41
35
|
npx prisma-cli --help
|
|
42
36
|
npx prisma-cli auth login
|
|
43
|
-
npx prisma-cli app
|
|
37
|
+
npx prisma-cli project create my-app
|
|
38
|
+
npx prisma-cli git connect git@github.com:owner/repo.git
|
|
44
39
|
```
|
|
45
40
|
|
|
41
|
+
Deployments start from pushing the connected repository, the Console, or
|
|
42
|
+
`prisma-cli composer deploy` — there is no standalone deploy command.
|
|
43
|
+
|
|
46
44
|
With `pnpm`:
|
|
47
45
|
|
|
48
46
|
```bash
|
|
49
|
-
pnpm add -D @prisma/cli
|
|
47
|
+
pnpm add -D @prisma/cli@next
|
|
50
48
|
pnpm prisma-cli auth login
|
|
51
|
-
pnpm prisma-cli
|
|
49
|
+
pnpm prisma-cli git connect
|
|
52
50
|
```
|
|
53
51
|
|
|
54
52
|
Useful next commands:
|
|
55
53
|
|
|
56
54
|
```bash
|
|
57
|
-
npx prisma-cli
|
|
58
|
-
npx prisma-cli
|
|
55
|
+
npx prisma-cli service list
|
|
56
|
+
npx prisma-cli service logs
|
|
59
57
|
npx prisma-cli project env add DATABASE_URL=postgresql://example --role preview
|
|
60
58
|
npx prisma-cli project env add --file .env --role preview
|
|
61
59
|
npx prisma-cli project env list
|
|
@@ -71,24 +69,27 @@ The beta package exposes `prisma-cli` so it can coexist with the existing
|
|
|
71
69
|
|
|
72
70
|
| Group | What it does |
|
|
73
71
|
| --- | --- |
|
|
74
|
-
| `version` | Show the installed CLI build and host environment. |
|
|
75
72
|
| `auth` | Log in, log out, and inspect the active Prisma account. |
|
|
76
|
-
| `project` | List
|
|
77
|
-
| `git` | Connect or disconnect a project from a GitHub repository. |
|
|
73
|
+
| `project` | List, create, link, and manage projects and their environment variables. |
|
|
74
|
+
| `git` | Connect or disconnect a project from a GitHub repository; pushes deploy. |
|
|
78
75
|
| `branch` | List Prisma branches for the resolved project. |
|
|
79
|
-
| `
|
|
80
|
-
| `bucket` | Create, list, and delete
|
|
81
|
-
| `
|
|
76
|
+
| `postgres` | Create, inspect, restore, and remove Prisma Postgres databases and their connections. |
|
|
77
|
+
| `bucket` | Create, list, and delete object-store buckets and their access keys. |
|
|
78
|
+
| `service` | Inspect services: deployments, logs, domains, promote, roll back, remove. |
|
|
79
|
+
| `build` | Stream platform build logs. |
|
|
80
|
+
| `composer` | Deploy, destroy, and develop Composer apps. |
|
|
81
|
+
| `contract`, `db`, `migrate`, `migration`, `format`, `orm init`, `lsp` | The Prisma ORM workflow. |
|
|
82
|
+
| `init` | Write a committed compute config for the project. |
|
|
82
83
|
|
|
83
84
|
Common examples:
|
|
84
85
|
|
|
85
86
|
```bash
|
|
86
|
-
npx prisma-cli version
|
|
87
|
+
npx prisma-cli --version
|
|
87
88
|
npx prisma-cli auth whoami
|
|
88
89
|
npx prisma-cli project show
|
|
89
90
|
npx prisma-cli branch list
|
|
90
|
-
npx prisma-cli
|
|
91
|
-
npx prisma-cli
|
|
91
|
+
npx prisma-cli service list
|
|
92
|
+
npx prisma-cli service deployment promote DEPLOYMENT_ID
|
|
92
93
|
```
|
|
93
94
|
|
|
94
95
|
### Built for humans, CI, and agents
|
|
@@ -105,9 +106,9 @@ npx prisma-cli app promote <deployment-id>
|
|
|
105
106
|
## Beta notes
|
|
106
107
|
|
|
107
108
|
- Requires Node.js 22.18 or newer.
|
|
108
|
-
- This is a
|
|
109
|
-
-
|
|
110
|
-
- The package binary is `prisma-cli
|
|
109
|
+
- This is a release-candidate package and may change quickly.
|
|
110
|
+
- The 8.0.0 release candidates publish as `@prisma/cli` on the `next` dist-tag.
|
|
111
|
+
- The package binary is `prisma-cli`; the sibling `prisma` package ships the same CLI under the `prisma` binary.
|
|
111
112
|
- Local project context is cached in `.prisma/local.json`, which is gitignored and not a declarative repo config file.
|
|
112
113
|
|
|
113
114
|
---
|
|
@@ -115,9 +116,7 @@ npx prisma-cli app promote <deployment-id>
|
|
|
115
116
|
## Documentation
|
|
116
117
|
|
|
117
118
|
- [CLI docs index](https://github.com/prisma/prisma-cli/blob/main/docs/README.md)
|
|
118
|
-
- [Resource model](https://github.com/prisma/prisma-cli/blob/main/docs/product/resource-model.md)
|
|
119
119
|
- [Command principles](https://github.com/prisma/prisma-cli/blob/main/docs/product/command-principles.md)
|
|
120
|
-
- [Command spec](https://github.com/prisma/prisma-cli/blob/main/docs/product/command-spec.md)
|
|
121
120
|
- [Output conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/output-conventions.md)
|
|
122
121
|
- [Error conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/error-conventions.md)
|
|
123
122
|
|
package/dist/cli.js
CHANGED
|
@@ -34,9 +34,12 @@ import { pipeline } from "node:stream/promises";
|
|
|
34
34
|
* this constant rather than restating the name.
|
|
35
35
|
*/
|
|
36
36
|
const CLI_NAME = "prisma-cli";
|
|
37
|
-
/** The CLI docs page (also the update-check fallback instruction URL).
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
/** The CLI docs page (also the update-check fallback instruction URL).
|
|
38
|
+
* The old /docs/orm/tools/prisma-cli path 308-redirects to the ORM CLI
|
|
39
|
+
* reference — the wrong docs for the unified CLI — so this points at
|
|
40
|
+
* the docs root until the unified CLI has its own page. */
|
|
41
|
+
const CLI_DOCS_URL = "https://www.prisma.io/docs";
|
|
42
|
+
const PRISMA_CLI_PACKAGE_SPEC = `@prisma/cli@next`;
|
|
40
43
|
const DEFAULT_PRISMA_CLI_PACKAGE_RUNNER = ["npx", "-y"];
|
|
41
44
|
const PRISMA_CLI_BINARY = "prisma-cli";
|
|
42
45
|
function formatPrismaCliCommand(args, options = {}) {
|
|
@@ -2805,12 +2808,11 @@ function projectRemoveBlockedError(projectId, error) {
|
|
|
2805
2808
|
domain: "project",
|
|
2806
2809
|
summary: "Project cannot be removed yet",
|
|
2807
2810
|
why: error?.error?.message ?? `Project "${projectId}" still has active deployments.`,
|
|
2808
|
-
fix: "Remove the project's
|
|
2811
|
+
fix: "Remove the project's services first, then retry the removal.",
|
|
2809
2812
|
exitCode: 1,
|
|
2810
2813
|
nextSteps: [formatPrismaCliCommand([
|
|
2811
|
-
"
|
|
2814
|
+
"service",
|
|
2812
2815
|
"remove",
|
|
2813
|
-
"--app",
|
|
2814
2816
|
"<name>"
|
|
2815
2817
|
])]
|
|
2816
2818
|
});
|
|
@@ -2951,7 +2953,7 @@ function projectAmbiguousError(projectRef, matches) {
|
|
|
2951
2953
|
function projectAmbiguousCliError(projectRef, matches) {
|
|
2952
2954
|
const firstMatch = matches[0];
|
|
2953
2955
|
const nextSteps = ["prisma-cli project list"];
|
|
2954
|
-
if (firstMatch) nextSteps.push(`prisma-cli
|
|
2956
|
+
if (firstMatch) nextSteps.push(`prisma-cli project link ${firstMatch.id}`);
|
|
2955
2957
|
return new CliError({
|
|
2956
2958
|
code: "PROJECT_AMBIGUOUS",
|
|
2957
2959
|
domain: "project",
|
|
@@ -3618,7 +3620,7 @@ function localStateWriteFailedError(error, options) {
|
|
|
3618
3620
|
debug: formatDebugDetails(error.cause),
|
|
3619
3621
|
meta: options.meta,
|
|
3620
3622
|
exitCode: 1,
|
|
3621
|
-
nextSteps: ["prisma-cli project link <id-or-name>"
|
|
3623
|
+
nextSteps: ["prisma-cli project link <id-or-name>"]
|
|
3622
3624
|
});
|
|
3623
3625
|
}
|
|
3624
3626
|
function toProjectSummary(project) {
|
|
@@ -6515,10 +6517,12 @@ function toAbsoluteUrl(url) {
|
|
|
6515
6517
|
}
|
|
6516
6518
|
//#endregion
|
|
6517
6519
|
//#region src/commands/project/presentation.ts
|
|
6518
|
-
|
|
6520
|
+
/** Deploys come from pushing a connected repository, so the step after
|
|
6521
|
+
* creating or linking a Project is connecting one. */
|
|
6522
|
+
const CONNECT_REPO_NEXT_ACTION = {
|
|
6519
6523
|
kind: "run-command",
|
|
6520
|
-
label: `${CLI_NAME}
|
|
6521
|
-
command: `${CLI_NAME}
|
|
6524
|
+
label: `${CLI_NAME} git connect`,
|
|
6525
|
+
command: `${CLI_NAME} git connect`
|
|
6522
6526
|
};
|
|
6523
6527
|
/** The legacy local-pin warnings of `project remove` / `project
|
|
6524
6528
|
* transfer`: the operation succeeded, so they are warn diagnostics
|
|
@@ -6563,7 +6567,7 @@ function setupPresentations(result) {
|
|
|
6563
6567
|
}
|
|
6564
6568
|
],
|
|
6565
6569
|
json: () => serializeProjectSetup(result),
|
|
6566
|
-
next: () => [
|
|
6570
|
+
next: () => [CONNECT_REPO_NEXT_ACTION]
|
|
6567
6571
|
};
|
|
6568
6572
|
}
|
|
6569
6573
|
//#endregion
|
|
@@ -6810,7 +6814,7 @@ function initPresentations(result, formatCommand) {
|
|
|
6810
6814
|
stdout: () => [result.configPath],
|
|
6811
6815
|
next: () => [
|
|
6812
6816
|
...typesMissing(result) && result.types.installCommand ? [runCommand(result.types.installCommand)] : [],
|
|
6813
|
-
runCommand(formatCommand(["
|
|
6817
|
+
runCommand(formatCommand(["git", "connect"])),
|
|
6814
6818
|
...isLinked(result) ? [] : [runCommand(formatCommand(["project", "link"]))]
|
|
6815
6819
|
]
|
|
6816
6820
|
};
|
|
@@ -9313,7 +9317,7 @@ async function readEnvFileAssignments(cwd, filePath, command) {
|
|
|
9313
9317
|
try {
|
|
9314
9318
|
contents = await readFile(resolvedPath, "utf8");
|
|
9315
9319
|
} catch (error) {
|
|
9316
|
-
throw usageError(`Failed to read env file "${filePath}"`, error instanceof Error ? error.message : "The file could not be read.", "Pass a readable dotenv file path.", [
|
|
9320
|
+
throw usageError(`Failed to read env file "${filePath}"`, error instanceof Error ? error.message : "The file could not be read.", "Pass a readable dotenv file path.", [`prisma-cli project env ${command} --file .env --role preview`], "app");
|
|
9317
9321
|
}
|
|
9318
9322
|
return parseEnvFileContents(contents, filePath, command);
|
|
9319
9323
|
}
|
|
@@ -9365,7 +9369,7 @@ function extractParsedKeys(contents) {
|
|
|
9365
9369
|
}
|
|
9366
9370
|
function validateEnvFileKey(key, line, filePath, command) {
|
|
9367
9371
|
try {
|
|
9368
|
-
validateKey(key, command
|
|
9372
|
+
validateKey(key, command);
|
|
9369
9373
|
} catch (error) {
|
|
9370
9374
|
const reason = error instanceof Error && error.message.length > 0 ? error.message : "Invalid environment variable key.";
|
|
9371
9375
|
throw usageError(`Invalid environment variable "${key}" in "${filePath}"`, `Line ${line}: ${reason}`, "Use a valid env-var key and retry the import.", [], "app");
|
|
@@ -9701,7 +9705,7 @@ async function resolveOrCreateBranch(client, projectId, branchName, signal) {
|
|
|
9701
9705
|
why: "Creating the first branch would make it the project default, but branch overrides are preview-only.",
|
|
9702
9706
|
fix: "Create or deploy the default branch first, then add the branch override.",
|
|
9703
9707
|
exitCode: 1,
|
|
9704
|
-
nextSteps: ["prisma-cli
|
|
9708
|
+
nextSteps: ["prisma-cli git connect <repository-url>"]
|
|
9705
9709
|
});
|
|
9706
9710
|
const { data, error, response } = await client.POST("/v1/projects/{projectId}/branches", {
|
|
9707
9711
|
params: { path: { projectId } },
|
|
@@ -12053,8 +12057,8 @@ function domainWaitPresentations(result) {
|
|
|
12053
12057
|
async function loadComputeConfig$1(cwd, signal) {
|
|
12054
12058
|
return loadComputeConfig(cwd, { signal });
|
|
12055
12059
|
}
|
|
12056
|
-
function computeConfigErrorToCliError(error, commandName
|
|
12057
|
-
const command = `prisma-cli
|
|
12060
|
+
function computeConfigErrorToCliError(error, commandName) {
|
|
12061
|
+
const command = `prisma-cli service ${commandName}`;
|
|
12058
12062
|
return matchError(error, {
|
|
12059
12063
|
ComputeConfigAmbiguousError: (ambiguous) => new CliError({
|
|
12060
12064
|
code: "COMPUTE_CONFIG_INVALID",
|
|
@@ -14226,6 +14230,52 @@ function runTelemetry(inputs) {
|
|
|
14226
14230
|
//#region src/auth/legacy-state.ts
|
|
14227
14231
|
const LEGACY_PLACEHOLDER_NAME = "Unknown workspace";
|
|
14228
14232
|
/**
|
|
14233
|
+
* The sessions re-serialized in the legacy store's record shape. The
|
|
14234
|
+
* 3.x CLI reads `tokens` from auth.json (`data.tokens || []`, silently
|
|
14235
|
+
* empty for any other shape), so a write that dropped the key made
|
|
14236
|
+
* every session invisible to `@prisma/cli@latest` on the same machine
|
|
14237
|
+
* the moment this CLI first mutated the file (#204). Sessions without
|
|
14238
|
+
* a refresh token still mirror; the legacy reader skips them, exactly
|
|
14239
|
+
* as it skips its own unrefreshable records.
|
|
14240
|
+
*/
|
|
14241
|
+
function legacyTokensMirror(sessions) {
|
|
14242
|
+
return sessions.map((session) => ({
|
|
14243
|
+
workspaceId: session.workspaceId,
|
|
14244
|
+
token: session.token,
|
|
14245
|
+
...session.refreshToken === void 0 ? {} : { refreshToken: session.refreshToken }
|
|
14246
|
+
}));
|
|
14247
|
+
}
|
|
14248
|
+
/**
|
|
14249
|
+
* Keeps auth.context.json's `activeWorkspaceId` — the pointer the 3.x
|
|
14250
|
+
* CLI selects its session with — in step with `currentWorkspaceId`.
|
|
14251
|
+
* The rest of the context file (the remembered-workspace name map) is
|
|
14252
|
+
* preserved verbatim; only the pointer moves.
|
|
14253
|
+
*/
|
|
14254
|
+
async function syncLegacyContext(authFilePath, currentWorkspaceId) {
|
|
14255
|
+
const contextFilePath = getAuthContextFilePath(authFilePath);
|
|
14256
|
+
const context = await readLegacyContext(contextFilePath);
|
|
14257
|
+
if (context.exists && context.activeWorkspaceId === currentWorkspaceId) return;
|
|
14258
|
+
if (!context.exists && currentWorkspaceId === null) return;
|
|
14259
|
+
const raw = await fs.readFile(contextFilePath, "utf8").catch(() => null);
|
|
14260
|
+
let workspaces = {};
|
|
14261
|
+
if (raw !== null) try {
|
|
14262
|
+
const parsed = JSON.parse(raw);
|
|
14263
|
+
if (typeof parsed.workspaces === "object" && parsed.workspaces !== null && !Array.isArray(parsed.workspaces)) workspaces = parsed.workspaces;
|
|
14264
|
+
} catch {}
|
|
14265
|
+
const tempPath = `${contextFilePath}.${randomUUID()}.tmp`;
|
|
14266
|
+
const payload = `${JSON.stringify({
|
|
14267
|
+
activeWorkspaceId: currentWorkspaceId,
|
|
14268
|
+
workspaces
|
|
14269
|
+
}, null, 2)}\n`;
|
|
14270
|
+
try {
|
|
14271
|
+
await fs.writeFile(tempPath, payload, "utf8");
|
|
14272
|
+
await fs.rename(tempPath, contextFilePath);
|
|
14273
|
+
} catch (error) {
|
|
14274
|
+
await fs.unlink(tempPath).catch(() => {});
|
|
14275
|
+
throw error;
|
|
14276
|
+
}
|
|
14277
|
+
}
|
|
14278
|
+
/**
|
|
14229
14279
|
* The legacy store read as sessions. Pure: adoption never writes, and
|
|
14230
14280
|
* the legacy files stay untouched until a mutation materializes the
|
|
14231
14281
|
* adopted set in the new format.
|
|
@@ -14412,14 +14462,22 @@ function normalizeSession(session) {
|
|
|
14412
14462
|
};
|
|
14413
14463
|
}
|
|
14414
14464
|
/** Temp file in the same directory, fsync, rename, mode 0600 — a reader
|
|
14415
|
-
* only ever sees a complete state.
|
|
14465
|
+
* only ever sees a complete state. The written file also carries the
|
|
14466
|
+
* legacy `tokens` mirror and the auth.context.json pointer stays in
|
|
14467
|
+
* step, so the 3.x CLI sharing this store keeps seeing the sessions
|
|
14468
|
+
* (#204). Our own reader branches on `sessions` before it ever looks
|
|
14469
|
+
* at `tokens`, so the mirror is invisible to this CLI. */
|
|
14416
14470
|
async function writeCredentialState(filePath, state) {
|
|
14417
14471
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
14418
14472
|
const tempPath = `${filePath}.${randomUUID()}.tmp`;
|
|
14473
|
+
const payload = {
|
|
14474
|
+
...state,
|
|
14475
|
+
tokens: legacyTokensMirror(state.sessions)
|
|
14476
|
+
};
|
|
14419
14477
|
try {
|
|
14420
14478
|
const handle = await fs.open(tempPath, "wx", FILE_MODE);
|
|
14421
14479
|
try {
|
|
14422
|
-
await handle.writeFile(`${JSON.stringify(
|
|
14480
|
+
await handle.writeFile(`${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
14423
14481
|
await handle.sync();
|
|
14424
14482
|
} finally {
|
|
14425
14483
|
await handle.close();
|
|
@@ -14430,6 +14488,7 @@ async function writeCredentialState(filePath, state) {
|
|
|
14430
14488
|
throw error;
|
|
14431
14489
|
}
|
|
14432
14490
|
await fs.chmod(filePath, FILE_MODE).catch(() => {});
|
|
14491
|
+
await syncLegacyContext(filePath, state.currentWorkspaceId);
|
|
14433
14492
|
}
|
|
14434
14493
|
var StateLockTimeoutError = class extends CliStructuredError {
|
|
14435
14494
|
constructor(lockPath, waitTimeoutMs) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/cli",
|
|
3
|
-
"version": "8.0.0-rc.5",
|
|
3
|
+
"version": "8.0.0-rc.5-dev.65",
|
|
4
4
|
"description": "Command-line interface for the Prisma Developer Platform.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"license": "Apache-2.0",
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@prisma/cli-engine": "0.2.0",
|
|
43
|
-
"@prisma/composer-cli": "0.
|
|
43
|
+
"@prisma/composer-cli": "0.9.0-dev.1",
|
|
44
44
|
"@prisma/compute-sdk": "0.39.0",
|
|
45
45
|
"@prisma/credentials-store": "^7.8.0",
|
|
46
46
|
"@prisma/management-api-sdk": "1.55.0",
|
|
47
|
-
"@prisma/orm-toolchain": "8.0.0-rc.3",
|
|
47
|
+
"@prisma/orm-toolchain": "8.0.0-rc.3-dev.3",
|
|
48
48
|
"@vercel/detect-agent": "^1.2.3",
|
|
49
49
|
"better-result": "^2.9.2",
|
|
50
50
|
"dotenv": "^17.4.2",
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"open": "^11.0.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@prisma/composer": "0.
|
|
56
|
-
"@repo/cli-conformance": "8.0.0-rc.5",
|
|
57
|
-
"@repo/cli-telemetry": "8.0.0-rc.5",
|
|
58
|
-
"@repo/tsconfig": "8.0.0-rc.5",
|
|
55
|
+
"@prisma/composer": "0.9.0-dev.1",
|
|
56
|
+
"@repo/cli-conformance": "8.0.0-rc.5-dev.65",
|
|
57
|
+
"@repo/cli-telemetry": "8.0.0-rc.5-dev.65",
|
|
58
|
+
"@repo/tsconfig": "8.0.0-rc.5-dev.65",
|
|
59
59
|
"@types/node": "^22.19.19",
|
|
60
60
|
"tsdown": "^0.21.10",
|
|
61
61
|
"tsx": "^4.22.4",
|