@prisma/cli 3.0.0-alpha.10 → 3.0.0-alpha.11
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.
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { getAuthFilePath } from "../lib/auth/client.js";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
2
4
|
import { CredentialsStore } from "@prisma/credentials-store";
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
3
6
|
//#region src/adapters/token-storage.ts
|
|
4
7
|
function findLatestValidTokens(allCredentials) {
|
|
5
8
|
for (let i = allCredentials.length - 1; i >= 0; i -= 1) {
|
|
@@ -14,10 +17,19 @@ function findLatestValidTokens(allCredentials) {
|
|
|
14
17
|
}
|
|
15
18
|
return null;
|
|
16
19
|
}
|
|
20
|
+
function tokensEqual(a, b) {
|
|
21
|
+
return a?.workspaceId === b?.workspaceId && a?.accessToken === b?.accessToken && a?.refreshToken === b?.refreshToken;
|
|
22
|
+
}
|
|
23
|
+
function sleep(ms) {
|
|
24
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
25
|
+
}
|
|
17
26
|
var FileTokenStorage = class {
|
|
18
27
|
credentialsStore;
|
|
28
|
+
lockFilePath;
|
|
19
29
|
constructor(env = process.env) {
|
|
20
|
-
|
|
30
|
+
const authFilePath = getAuthFilePath(env);
|
|
31
|
+
this.credentialsStore = new CredentialsStore(authFilePath);
|
|
32
|
+
this.lockFilePath = `${authFilePath}.lock`;
|
|
21
33
|
}
|
|
22
34
|
async getTokens() {
|
|
23
35
|
try {
|
|
@@ -38,6 +50,50 @@ var FileTokenStorage = class {
|
|
|
38
50
|
if (!tokens) return;
|
|
39
51
|
await this.credentialsStore.deleteCredentials(tokens.workspaceId);
|
|
40
52
|
}
|
|
53
|
+
async clearTokensIfCurrent(tokens) {
|
|
54
|
+
if (!tokensEqual(await this.getTokens(), tokens)) return;
|
|
55
|
+
await this.clearTokens();
|
|
56
|
+
}
|
|
57
|
+
async withRefreshLock(fn) {
|
|
58
|
+
const lockId = await this.acquireRefreshLock();
|
|
59
|
+
try {
|
|
60
|
+
return await fn();
|
|
61
|
+
} finally {
|
|
62
|
+
await this.releaseRefreshLock(lockId);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async acquireRefreshLock() {
|
|
66
|
+
const lockId = randomUUID();
|
|
67
|
+
await fs.mkdir(path.dirname(this.lockFilePath), { recursive: true });
|
|
68
|
+
while (true) try {
|
|
69
|
+
const handle = await fs.open(this.lockFilePath, "wx");
|
|
70
|
+
try {
|
|
71
|
+
await handle.writeFile(lockId, "utf8");
|
|
72
|
+
} finally {
|
|
73
|
+
await handle.close();
|
|
74
|
+
}
|
|
75
|
+
return lockId;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error.code !== "EEXIST") throw error;
|
|
78
|
+
const staleLockId = await this.getStaleRefreshLockId();
|
|
79
|
+
if (staleLockId) {
|
|
80
|
+
await this.releaseRefreshLock(staleLockId);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
await sleep(100);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async getStaleRefreshLockId() {
|
|
87
|
+
const lockId = await fs.readFile(this.lockFilePath, "utf8").catch(() => null);
|
|
88
|
+
if (lockId === null) return null;
|
|
89
|
+
const stats = await fs.stat(this.lockFilePath).catch(() => null);
|
|
90
|
+
if (!stats) return null;
|
|
91
|
+
return Date.now() - stats.mtimeMs > 3e4 ? lockId : null;
|
|
92
|
+
}
|
|
93
|
+
async releaseRefreshLock(lockId) {
|
|
94
|
+
if (await fs.readFile(this.lockFilePath, "utf8").catch(() => null) !== lockId) return;
|
|
95
|
+
await fs.unlink(this.lockFilePath).catch(() => {});
|
|
96
|
+
}
|
|
41
97
|
};
|
|
42
98
|
//#endregion
|
|
43
99
|
export { FileTokenStorage };
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { CliError } from "./errors.js";
|
|
1
|
+
import { CliError, authRequiredError } from "./errors.js";
|
|
2
2
|
import { cliErrorToJson, writeHumanError, writeHumanLines, writeJsonError, writeJsonEvent, writeJsonSuccess } from "./output.js";
|
|
3
3
|
import { getCommandDescriptor } from "./command-meta.js";
|
|
4
4
|
import { resolveGlobalFlags } from "./global-flags.js";
|
|
5
5
|
import { createCommandContext } from "./runtime.js";
|
|
6
|
+
import { AuthError } from "@prisma/management-api-sdk";
|
|
6
7
|
//#region src/shell/command-runner.ts
|
|
8
|
+
function toCliError(error) {
|
|
9
|
+
if (error instanceof CliError) return error;
|
|
10
|
+
if (error instanceof AuthError) return authRequiredError(["prisma-cli auth login"], { debug: error.message });
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
7
13
|
async function runCommand(runtime, commandName, options, handler, presenter) {
|
|
8
14
|
const flags = resolveGlobalFlags(runtime.argv, options);
|
|
9
15
|
const context = await createCommandContext(runtime, flags);
|
|
@@ -20,10 +26,11 @@ async function runCommand(runtime, commandName, options, handler, presenter) {
|
|
|
20
26
|
if (flags.quiet) return;
|
|
21
27
|
writeHumanLines(context.output, presenter.renderHuman(context, descriptor, success.result));
|
|
22
28
|
} catch (error) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
const cliError = toCliError(error);
|
|
30
|
+
if (cliError) {
|
|
31
|
+
if (flags.json) writeJsonError(context.output, commandName, cliError);
|
|
32
|
+
else writeHumanError(context.output, context.ui, cliError, { trace: flags.trace });
|
|
33
|
+
process.exitCode = cliError.exitCode;
|
|
27
34
|
return;
|
|
28
35
|
}
|
|
29
36
|
throw error;
|
|
@@ -43,17 +50,18 @@ async function runStreamingCommand(runtime, commandName, options, handler) {
|
|
|
43
50
|
nextSteps: []
|
|
44
51
|
});
|
|
45
52
|
} catch (error) {
|
|
46
|
-
|
|
53
|
+
const cliError = toCliError(error);
|
|
54
|
+
if (cliError) {
|
|
47
55
|
if (flags.json) writeJsonEvent(context.output, {
|
|
48
56
|
type: "error",
|
|
49
57
|
command: commandName,
|
|
50
58
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
51
|
-
error: cliErrorToJson(
|
|
59
|
+
error: cliErrorToJson(cliError),
|
|
52
60
|
warnings: [],
|
|
53
|
-
nextSteps:
|
|
61
|
+
nextSteps: cliError.nextSteps
|
|
54
62
|
});
|
|
55
|
-
else writeHumanError(context.output, context.ui,
|
|
56
|
-
process.exitCode =
|
|
63
|
+
else writeHumanError(context.output, context.ui, cliError, { trace: flags.trace });
|
|
64
|
+
process.exitCode = cliError.exitCode;
|
|
57
65
|
return;
|
|
58
66
|
}
|
|
59
67
|
throw error;
|
package/dist/shell/errors.js
CHANGED
|
@@ -42,13 +42,14 @@ function usageError(summary, why, fix, nextSteps = [], domain = "cli") {
|
|
|
42
42
|
nextSteps
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
-
function authRequiredError(nextSteps = ["prisma-cli auth login"]) {
|
|
45
|
+
function authRequiredError(nextSteps = ["prisma-cli auth login"], options = {}) {
|
|
46
46
|
return new CliError({
|
|
47
47
|
code: "AUTH_REQUIRED",
|
|
48
48
|
domain: "auth",
|
|
49
49
|
summary: "Authentication required",
|
|
50
50
|
why: "This command needs an authenticated session.",
|
|
51
51
|
fix: "Run prisma-cli auth login, or rerun the command in a TTY to sign in interactively.",
|
|
52
|
+
debug: options.debug,
|
|
52
53
|
exitCode: 1,
|
|
53
54
|
nextSteps
|
|
54
55
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/cli",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.11",
|
|
4
4
|
"description": "Preview of the unified Prisma CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@prisma/compute-sdk": "^0.18.0",
|
|
40
40
|
"c12": "4.0.0-beta.4",
|
|
41
41
|
"@prisma/credentials-store": "^7.7.0",
|
|
42
|
-
"@prisma/management-api-sdk": "^1.
|
|
42
|
+
"@prisma/management-api-sdk": "^1.32.1",
|
|
43
43
|
"colorette": "^2.0.20",
|
|
44
44
|
"commander": "^12.1.0",
|
|
45
45
|
"magicast": "^0.3.5",
|