@prisma/cli 3.0.0-dev.97.1 → 8.0.0-rc.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/README.md +3 -14
- package/dist/adapters/local-state.js +14 -3
- package/dist/{lib/auth → auth}/client.js +11 -3
- package/dist/auth/errors.js +50 -0
- package/dist/{lib/auth → auth}/guard.js +7 -6
- package/dist/{lib/auth → auth}/login.js +147 -6
- package/dist/{lib/auth/auth-ops.js → auth/operations.js} +63 -13
- package/dist/auth/recipient.js +42 -0
- package/dist/{adapters → auth}/token-storage.js +28 -7
- package/dist/auth/workspaces.js +171 -0
- package/dist/cli-command.js +14 -0
- package/dist/cli-name.js +12 -0
- package/dist/cli.js +1 -1
- package/dist/cli2.js +25 -8
- package/dist/command-arguments.js +12 -0
- package/dist/commands/agent/index.js +60 -0
- package/dist/commands/app/index.js +11 -6
- package/dist/commands/auth/index.js +2 -3
- package/dist/commands/bucket/index.js +123 -0
- package/dist/commands/build/index.js +29 -0
- package/dist/commands/database/index.js +92 -2
- package/dist/commands/feedback/index.js +20 -0
- package/dist/commands/git/index.js +1 -1
- package/dist/commands/init/index.js +33 -0
- package/dist/commands/project/index.js +54 -5
- package/dist/controllers/agent-setup.js +52 -0
- package/dist/controllers/agent.js +228 -0
- package/dist/controllers/app-env-api.js +3 -2
- package/dist/controllers/app-env-file.js +1 -1
- package/dist/controllers/app-env.js +5 -5
- package/dist/controllers/app.js +423 -358
- package/dist/controllers/auth.js +62 -254
- package/dist/controllers/branch.js +5 -16
- package/dist/controllers/bucket.js +184 -0
- package/dist/controllers/build.js +88 -0
- package/dist/controllers/database.js +230 -85
- package/dist/controllers/feedback.js +90 -0
- package/dist/controllers/init.js +814 -0
- package/dist/controllers/project.js +345 -184
- package/dist/controllers/select-prompt-port.js +1 -0
- package/dist/{shell/errors.js → errors.js} +8 -40
- package/dist/lib/agent/cli-command.js +20 -0
- package/dist/lib/agent/constants.js +12 -0
- package/dist/lib/agent/package-manager.js +99 -0
- package/dist/lib/agent/setup-status.js +83 -0
- package/dist/lib/app/app-provider.js +168 -95
- package/dist/lib/app/branch-database-deploy.js +70 -42
- package/dist/lib/app/branch-database.js +39 -20
- package/dist/lib/app/build-settings.js +8 -3
- package/dist/lib/app/build.js +16 -14
- package/dist/lib/app/bun-project.js +1 -1
- package/dist/lib/app/compute-config.js +29 -31
- package/dist/lib/app/deploy-plan.js +1 -0
- package/dist/lib/app/deploy-progress.js +7 -7
- package/dist/lib/app/env-config.js +1 -1
- package/dist/lib/app/env-file.js +2 -2
- package/dist/lib/app/env-vars.js +1 -1
- package/dist/lib/app/local-dev.js +1 -1
- package/dist/lib/app/production-deploy-gate.js +3 -2
- package/dist/lib/bucket/provider.js +139 -0
- package/dist/lib/database/provider.js +235 -17
- package/dist/lib/diagnostics.js +2 -1
- package/dist/lib/feedback.js +15 -0
- package/dist/lib/git/local-branch.js +1 -1
- package/dist/lib/project/interactive-setup.js +6 -5
- package/dist/lib/project/local-pin.js +1 -1
- package/dist/lib/project/provider.js +93 -0
- package/dist/lib/project/resolution.js +11 -8
- package/dist/lib/project/setup.js +9 -6
- package/dist/lib/version.js +3 -2
- package/dist/lib/workspace-id.js +18 -0
- package/dist/payload-B88Qvzxk-CrtTXSOe.js +34 -0
- package/dist/presenters/agent.js +74 -0
- package/dist/presenters/app.js +33 -7
- package/dist/presenters/auth.js +3 -2
- package/dist/presenters/bucket.js +174 -0
- package/dist/presenters/database.js +193 -5
- package/dist/presenters/feedback.js +26 -0
- package/dist/presenters/init.js +30 -0
- package/dist/presenters/project.js +98 -4
- package/dist/shell/cli-command.js +2 -0
- package/dist/shell/command-meta.js +303 -4
- package/dist/shell/command-runner.js +13 -6
- package/dist/shell/help.js +6 -5
- package/dist/shell/output.js +65 -3
- package/dist/shell/prompt.js +12 -5
- package/dist/shell/runtime.js +4 -21
- package/dist/state-dir.js +12 -0
- package/dist/{shell/update-check.js → update-check.js} +6 -5
- package/dist/v8/cli.js +14699 -0
- package/dist/v8/sender.js +192 -0
- package/package.json +21 -13
- package/dist/adapters/mock-api.js +0 -136
- package/dist/lib/app/app-interaction.js +0 -5
- package/dist/shell/command-arguments.js +0 -6
- package/dist/use-cases/auth.js +0 -145
- package/dist/use-cases/branch.js +0 -47
- package/dist/use-cases/create-cli-gateways.js +0 -68
- package/dist/use-cases/project.js +0 -30
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { access, readFile, readdir, stat } from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
2
|
+
import { access, readFile, readdir, stat } from "node:fs/promises";
|
|
3
3
|
//#region src/lib/app/branch-database.ts
|
|
4
4
|
const SKIPPED_DIRECTORIES = new Set([
|
|
5
5
|
".git",
|
|
6
|
+
".agents",
|
|
6
7
|
".next",
|
|
7
8
|
".nuxt",
|
|
8
9
|
".output",
|
|
@@ -54,14 +55,18 @@ async function inspectBranchDatabaseSignal(cwd, signal) {
|
|
|
54
55
|
} : selectedPrismaOrmSchema.schema;
|
|
55
56
|
return {
|
|
56
57
|
schema,
|
|
57
|
-
unsupportedSchema: schema ? null : unsupportedPrismaNextConfig
|
|
58
|
-
kind: "prisma-next",
|
|
59
|
-
path: unsupportedPrismaNextConfig.path,
|
|
60
|
-
target: unsupportedPrismaNextConfig.target
|
|
61
|
-
} : selectedPrismaOrmSchema.unsupportedSchema,
|
|
58
|
+
unsupportedSchema: schema ? null : toUnsupportedSchema(unsupportedPrismaNextConfig) ?? selectedPrismaOrmSchema.unsupportedSchema,
|
|
62
59
|
databaseUrlReferences: state.databaseUrlReferences
|
|
63
60
|
};
|
|
64
61
|
}
|
|
62
|
+
function toUnsupportedSchema(config) {
|
|
63
|
+
if (!config) return null;
|
|
64
|
+
return {
|
|
65
|
+
kind: "prisma-next",
|
|
66
|
+
path: config.path,
|
|
67
|
+
target: config.target
|
|
68
|
+
};
|
|
69
|
+
}
|
|
65
70
|
function hasBranchDatabaseSignal(signal) {
|
|
66
71
|
if (signal.unsupportedSchema) return false;
|
|
67
72
|
return Boolean(signal.schema || signal.databaseUrlReferences.length > 0);
|
|
@@ -69,29 +74,42 @@ function hasBranchDatabaseSignal(signal) {
|
|
|
69
74
|
async function scanDirectory(cwd, directory, depth, state, signal) {
|
|
70
75
|
signal.throwIfAborted();
|
|
71
76
|
if (depth > MAX_SCAN_DEPTH || state.filesVisited >= MAX_SCAN_FILES) return;
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
entries = await readdir(directory, { withFileTypes: true });
|
|
75
|
-
} catch (error) {
|
|
76
|
-
if (error.code === "ENOENT") return;
|
|
77
|
-
throw error;
|
|
78
|
-
}
|
|
79
|
-
entries.sort((left, right) => left.name.localeCompare(right.name));
|
|
77
|
+
const entries = await readSortedDirectoryEntries(directory);
|
|
80
78
|
for (const entry of entries) {
|
|
81
79
|
signal.throwIfAborted();
|
|
82
80
|
if (state.filesVisited >= MAX_SCAN_FILES) return;
|
|
83
81
|
const entryPath = path.join(directory, entry.name);
|
|
84
|
-
if (entry
|
|
85
|
-
|
|
82
|
+
if (isScannableDirectory(entry)) {
|
|
83
|
+
await scanDirectory(cwd, entryPath, depth + 1, state, signal);
|
|
86
84
|
continue;
|
|
87
85
|
}
|
|
88
86
|
if (!entry.isFile()) continue;
|
|
89
87
|
state.filesVisited += 1;
|
|
90
|
-
|
|
91
|
-
if (isPrismaNextConfigFile(entry.name)) state.prismaNextConfigCandidates.push(entryPath);
|
|
88
|
+
recordSchemaCandidates(entry.name, entryPath, state);
|
|
92
89
|
if (state.databaseUrlReferences.length < MAX_DATABASE_URL_REFERENCE_FILES && shouldScanForDatabaseUrl(entry.name) && await fileContainsDatabaseUrl(entryPath, signal)) state.databaseUrlReferences.push(path.relative(cwd, entryPath) || entry.name);
|
|
93
90
|
}
|
|
94
91
|
}
|
|
92
|
+
async function readSortedDirectoryEntries(directory) {
|
|
93
|
+
let entries;
|
|
94
|
+
try {
|
|
95
|
+
entries = await readdir(directory, { withFileTypes: true });
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (error.code === "ENOENT") return [];
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
return entries.sort((left, right) => compareCodeUnits(left.name, right.name));
|
|
101
|
+
}
|
|
102
|
+
function compareCodeUnits(left, right) {
|
|
103
|
+
if (left < right) return -1;
|
|
104
|
+
return left > right ? 1 : 0;
|
|
105
|
+
}
|
|
106
|
+
function isScannableDirectory(entry) {
|
|
107
|
+
return entry.isDirectory() && !SKIPPED_DIRECTORIES.has(entry.name);
|
|
108
|
+
}
|
|
109
|
+
function recordSchemaCandidates(fileName, filePath, state) {
|
|
110
|
+
if (fileName === "schema.prisma") state.schemaCandidates.push(filePath);
|
|
111
|
+
if (isPrismaNextConfigFile(fileName)) state.prismaNextConfigCandidates.push(filePath);
|
|
112
|
+
}
|
|
95
113
|
async function selectPrismaOrmSchema(cwd, candidates, signal) {
|
|
96
114
|
const sorted = sortByPreferredRelativePath(cwd, candidates, "schema.prisma");
|
|
97
115
|
for (const schemaPath of sorted) {
|
|
@@ -137,7 +155,7 @@ function sortByPreferredRelativePath(cwd, candidates, preferredRootFile) {
|
|
|
137
155
|
})).sort((left, right) => {
|
|
138
156
|
if (left.relative === preferredRootFile) return -1;
|
|
139
157
|
if (right.relative === preferredRootFile) return 1;
|
|
140
|
-
return left.relative.length - right.relative.length || left.relative
|
|
158
|
+
return left.relative.length - right.relative.length || compareCodeUnits(left.relative, right.relative);
|
|
141
159
|
}).map((candidate) => candidate.absolute);
|
|
142
160
|
}
|
|
143
161
|
async function hasMigrationsDirectory(schemaDirectory, signal) {
|
|
@@ -174,8 +192,9 @@ async function classifyPrismaNextConfig(configPath, signal) {
|
|
|
174
192
|
target: "unknown"
|
|
175
193
|
};
|
|
176
194
|
}
|
|
195
|
+
const SCHEMA_PROVIDER = /\bprovider\s*=\s*"([^"]+)"/;
|
|
177
196
|
async function classifyPrismaOrmSchemaTarget(schemaPath, signal) {
|
|
178
|
-
switch ((await readTextFileIfSmall(schemaPath, signal))?.match(
|
|
197
|
+
switch ((await readTextFileIfSmall(schemaPath, signal))?.match(SCHEMA_PROVIDER)?.[1] ?? null) {
|
|
179
198
|
case "postgresql": return "postgresql";
|
|
180
199
|
case "mongodb": return "mongodb";
|
|
181
200
|
case "mysql": return "mysql";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { resolveBuildSettings, resolveConfiguredBuildSettings } from "@prisma/compute-sdk";
|
|
4
4
|
//#region src/lib/app/build-settings.ts
|
|
5
5
|
/** Legacy build-settings file: no longer read or written, only detected for migration. */
|
|
@@ -26,7 +26,7 @@ async function detectLegacyBuildSettings(options) {
|
|
|
26
26
|
let legacy;
|
|
27
27
|
try {
|
|
28
28
|
const parsed = JSON.parse(content);
|
|
29
|
-
const buildCommand = parsed.buildCommand
|
|
29
|
+
const buildCommand = normalizeLegacyBuildCommand(parsed.buildCommand);
|
|
30
30
|
const outputDirectory = typeof parsed.outputDirectory === "string" ? normalizeRelativePath(parsed.outputDirectory) : void 0;
|
|
31
31
|
if (buildCommand === void 0 || !outputDirectory) return {
|
|
32
32
|
kind: "invalid",
|
|
@@ -80,10 +80,15 @@ async function resolveConfiguredAppBuildSettings(options) {
|
|
|
80
80
|
settings
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
+
const WINDOWS_DRIVE_PREFIX = /^[A-Za-z]:/;
|
|
84
|
+
function normalizeLegacyBuildCommand(value) {
|
|
85
|
+
if (typeof value === "string") return value.trim() || null;
|
|
86
|
+
if (value === null) return null;
|
|
87
|
+
}
|
|
83
88
|
function normalizeRelativePath(value) {
|
|
84
89
|
const raw = value.trim().replace(/\\/g, "/");
|
|
85
90
|
if (raw.length === 0 || raw.split("/").includes("..")) return;
|
|
86
|
-
if (
|
|
91
|
+
if (WINDOWS_DRIVE_PREFIX.test(raw)) return;
|
|
87
92
|
const normalized = path.posix.normalize(raw);
|
|
88
93
|
const segments = normalized.split("/");
|
|
89
94
|
if (path.win32.isAbsolute(value) || path.posix.isAbsolute(normalized) || segments.includes("..")) return;
|
package/dist/lib/app/build.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import "./build-settings.js";
|
|
2
|
-
import "node:fs/promises";
|
|
3
1
|
import "node:path";
|
|
2
|
+
import "node:fs/promises";
|
|
3
|
+
import { FRAMEWORKS } from "@prisma/compute-sdk/config";
|
|
4
4
|
import { normalizeArtifactSymlinks, resolveBuildStrategy } from "@prisma/compute-sdk";
|
|
5
5
|
//#region src/lib/app/build.ts
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
const RESOLVED_APP_BUILD_TYPES = [...frameworkBuildTypesByLastOccurrence()];
|
|
7
|
+
const APP_BUILD_TYPES = ["auto", ...RESOLVED_APP_BUILD_TYPES];
|
|
8
|
+
const APP_BUILD_TYPE_LABELS = APP_BUILD_TYPES.join(", ");
|
|
9
|
+
function frameworkBuildTypesByLastOccurrence() {
|
|
10
|
+
const buildTypes = /* @__PURE__ */ new Set();
|
|
11
|
+
for (const framework of FRAMEWORKS) {
|
|
12
|
+
if (buildTypes.has(framework.buildType)) buildTypes.delete(framework.buildType);
|
|
13
|
+
buildTypes.add(framework.buildType);
|
|
14
|
+
}
|
|
15
|
+
return buildTypes;
|
|
16
|
+
}
|
|
16
17
|
var AppBuildStrategy = class {
|
|
17
18
|
#appPath;
|
|
18
19
|
#entrypoint;
|
|
@@ -68,13 +69,14 @@ async function executeAppBuild(options) {
|
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
async function resolveAppBuildStrategy(options) {
|
|
72
|
+
const buildType = options.buildType === "auto" && options.entrypoint ? "bun" : options.buildType;
|
|
71
73
|
return resolveBuildStrategy({
|
|
72
74
|
appPath: options.appPath,
|
|
73
|
-
buildType
|
|
75
|
+
buildType,
|
|
74
76
|
entrypoint: options.entrypoint,
|
|
75
77
|
buildSettings: options.buildSettings,
|
|
76
78
|
signal: options.signal
|
|
77
79
|
});
|
|
78
80
|
}
|
|
79
81
|
//#endregion
|
|
80
|
-
export { APP_BUILD_TYPES, AppBuildStrategy, RESOLVED_APP_BUILD_TYPES, executeAppBuild };
|
|
82
|
+
export { APP_BUILD_TYPES, APP_BUILD_TYPE_LABELS, AppBuildStrategy, RESOLVED_APP_BUILD_TYPES, executeAppBuild };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { access, readFile } from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
2
|
+
import { access, readFile } from "node:fs/promises";
|
|
3
3
|
//#region src/lib/app/bun-project.ts
|
|
4
4
|
async function readBunPackageJson(appPath, signal) {
|
|
5
5
|
const packageJsonPath = path.join(appPath, "package.json");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CliError } from "../../
|
|
2
|
-
import { COMPUTE_CONFIG_FILENAME, COMPUTE_CONFIG_FILENAME as COMPUTE_CONFIG_FILENAME$1, ComputeConfigTargetRequiredError, computeTargetAppDir, frameworkByKey, inferComputeTargetFromCwd, loadComputeConfig, selectComputeDeployTarget } from "@prisma/compute-sdk/config";
|
|
1
|
+
import { CliError } from "../../errors.js";
|
|
3
2
|
import path from "node:path";
|
|
3
|
+
import { COMPUTE_CONFIG_FILENAME, frameworkByKey, loadComputeConfig } from "@prisma/compute-sdk/config";
|
|
4
4
|
import { matchError } from "better-result";
|
|
5
5
|
//#region src/lib/app/compute-config.ts
|
|
6
6
|
/**
|
|
@@ -18,47 +18,45 @@ function computeFrameworkToBuildType(framework) {
|
|
|
18
18
|
function mergeComputeDeployInputs(options) {
|
|
19
19
|
const { cli, target, configFilename } = options;
|
|
20
20
|
const configAnnotation = `set by ${configFilename}`;
|
|
21
|
-
const framework = cli.framework
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
value: target.framework,
|
|
26
|
-
annotation: configAnnotation
|
|
27
|
-
} : void 0;
|
|
28
|
-
const entrypoint = cli.entrypoint ? {
|
|
29
|
-
value: cli.entrypoint,
|
|
30
|
-
annotation: "set by --entry"
|
|
31
|
-
} : target?.entry ? {
|
|
32
|
-
value: target.entry,
|
|
33
|
-
annotation: configAnnotation
|
|
34
|
-
} : void 0;
|
|
35
|
-
const httpPort = cli.httpPort ? {
|
|
36
|
-
value: cli.httpPort,
|
|
37
|
-
annotation: "set by --http-port"
|
|
38
|
-
} : target?.httpPort ? {
|
|
39
|
-
value: String(target.httpPort),
|
|
40
|
-
annotation: configAnnotation
|
|
41
|
-
} : void 0;
|
|
21
|
+
const framework = mergeStringInput(cli.framework, "set by --framework", target?.framework ?? void 0, configAnnotation);
|
|
22
|
+
const entrypoint = mergeStringInput(cli.entrypoint, "set by --entry", target?.entry ?? void 0, configAnnotation);
|
|
23
|
+
const httpPort = mergeStringInput(cli.httpPort, "set by --http-port", target?.httpPort ? String(target.httpPort) : void 0, configAnnotation);
|
|
24
|
+
const region = mergeStringInput(cli.region, "set by --region", target?.region ?? void 0, configAnnotation);
|
|
42
25
|
const cliEnvInputs = cli.envInputs && cli.envInputs.length > 0 ? cli.envInputs : void 0;
|
|
43
26
|
const configEnvInputs = target && target.envInputs.length > 0 ? target.envInputs : void 0;
|
|
44
27
|
const envInputs = cliEnvInputs ?? configEnvInputs;
|
|
45
|
-
const configAppName = target
|
|
46
|
-
value: target.name,
|
|
47
|
-
annotation: configAnnotation
|
|
48
|
-
} : target?.key ? {
|
|
49
|
-
value: target.key,
|
|
50
|
-
annotation: configAnnotation
|
|
51
|
-
} : void 0;
|
|
28
|
+
const configAppName = readConfigAppName(target, configAnnotation);
|
|
52
29
|
return {
|
|
53
30
|
framework,
|
|
54
31
|
entrypoint,
|
|
55
32
|
httpPort,
|
|
33
|
+
region,
|
|
56
34
|
envInputs,
|
|
57
35
|
envInputsFromConfig: !cliEnvInputs && configEnvInputs !== void 0,
|
|
58
36
|
configAppName,
|
|
59
37
|
appRoot: target?.root ?? void 0
|
|
60
38
|
};
|
|
61
39
|
}
|
|
40
|
+
function mergeStringInput(cliValue, cliAnnotation, configValue, configAnnotation) {
|
|
41
|
+
if (cliValue !== void 0) return {
|
|
42
|
+
value: cliValue,
|
|
43
|
+
annotation: cliAnnotation
|
|
44
|
+
};
|
|
45
|
+
if (configValue) return {
|
|
46
|
+
value: configValue,
|
|
47
|
+
annotation: configAnnotation
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function readConfigAppName(target, configAnnotation) {
|
|
51
|
+
if (target?.name) return {
|
|
52
|
+
value: target.name,
|
|
53
|
+
annotation: configAnnotation
|
|
54
|
+
};
|
|
55
|
+
if (target?.key) return {
|
|
56
|
+
value: target.key,
|
|
57
|
+
annotation: configAnnotation
|
|
58
|
+
};
|
|
59
|
+
}
|
|
62
60
|
/**
|
|
63
61
|
* Merges CLI inputs for the local `app build` and `app run` commands with a
|
|
64
62
|
* selected config target. Explicit flags win; `--build-type auto` is the
|
|
@@ -144,4 +142,4 @@ function computeConfigErrorToCliError(error, commandName = "deploy") {
|
|
|
144
142
|
});
|
|
145
143
|
}
|
|
146
144
|
//#endregion
|
|
147
|
-
export {
|
|
145
|
+
export { computeConfigErrorToCliError, computeFrameworkToBuildType, loadComputeConfig$1 as loadComputeConfig, mergeComputeDeployInputs, mergeComputeLocalInputs };
|
|
@@ -30,6 +30,7 @@ function perAppInputsForDeployAll(inputs) {
|
|
|
30
30
|
["--framework", inputs.framework],
|
|
31
31
|
["--entry", inputs.entrypoint],
|
|
32
32
|
["--http-port", inputs.httpPort],
|
|
33
|
+
["--region", inputs.region],
|
|
33
34
|
["--env", inputs.envAssignments?.length ? inputs.envAssignments : void 0],
|
|
34
35
|
[inputs.appIdEnvVar.name, inputs.appIdEnvVar.value]
|
|
35
36
|
].filter(([, value]) => value !== void 0).map(([flag]) => flag);
|
|
@@ -6,7 +6,7 @@ function createDeployProgressState() {
|
|
|
6
6
|
buildCompleted: false,
|
|
7
7
|
archiveReady: false,
|
|
8
8
|
uploadCompleted: false,
|
|
9
|
-
|
|
9
|
+
deploymentId: null,
|
|
10
10
|
startRequested: false,
|
|
11
11
|
containerLive: false,
|
|
12
12
|
deploymentUrl: null,
|
|
@@ -39,8 +39,8 @@ function createDeployProgress(output, ui, enabled, state = createDeployProgressS
|
|
|
39
39
|
onUploadStart() {
|
|
40
40
|
write("Uploading...");
|
|
41
41
|
},
|
|
42
|
-
|
|
43
|
-
state.
|
|
42
|
+
onDeploymentCreated(deploymentId) {
|
|
43
|
+
state.deploymentId = deploymentId;
|
|
44
44
|
},
|
|
45
45
|
onUploadComplete() {
|
|
46
46
|
state.uploadCompleted = true;
|
|
@@ -69,16 +69,16 @@ function createPromoteProgress(output, enabled) {
|
|
|
69
69
|
output.write(`${line}\n`);
|
|
70
70
|
};
|
|
71
71
|
return {
|
|
72
|
-
|
|
73
|
-
write(`Starting deployment ${
|
|
72
|
+
onDeploymentStarting(deploymentId) {
|
|
73
|
+
write(`Starting deployment ${deploymentId}...`);
|
|
74
74
|
},
|
|
75
|
-
|
|
75
|
+
onDeploymentStartRequested() {
|
|
76
76
|
write("Requesting deployment start...");
|
|
77
77
|
},
|
|
78
78
|
onStatusChange(status) {
|
|
79
79
|
write(`Status: ${status}`);
|
|
80
80
|
},
|
|
81
|
-
|
|
81
|
+
onDeploymentRunning() {
|
|
82
82
|
write("Deployment is running.");
|
|
83
83
|
},
|
|
84
84
|
onPromoteStart() {
|
package/dist/lib/app/env-file.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { usageError } from "../../
|
|
1
|
+
import { usageError } from "../../errors.js";
|
|
2
2
|
import { validateKey } from "./env-config.js";
|
|
3
|
-
import { readFile } from "node:fs/promises";
|
|
4
3
|
import path from "node:path";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
5
|
import { parse } from "dotenv";
|
|
6
6
|
//#region src/lib/app/env-file.ts
|
|
7
7
|
const ASSIGNMENT_KEY_PATTERN = /^\s*(?:export\s+)?([^#=\s]+)\s*=/;
|
package/dist/lib/app/env-vars.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CliError } from "../../
|
|
2
|
-
import { confirmPrompt } from "../../shell/prompt.js";
|
|
1
|
+
import { CliError } from "../../errors.js";
|
|
3
2
|
import { canPrompt } from "../../shell/runtime.js";
|
|
3
|
+
import { confirmPrompt } from "../../shell/prompt.js";
|
|
4
4
|
//#region src/lib/app/production-deploy-gate.ts
|
|
5
5
|
async function enforceProductionDeployGate(context, provider, options) {
|
|
6
6
|
if (options.branchKind !== "production") return { firstProductionDeploy: false };
|
|
@@ -25,6 +25,7 @@ async function enforceProductionDeployGate(context, provider, options) {
|
|
|
25
25
|
if (!await confirmPrompt({
|
|
26
26
|
input: context.runtime.stdin,
|
|
27
27
|
output: context.output.stderr,
|
|
28
|
+
signal: context.runtime.signal,
|
|
28
29
|
message: "Deploy to production?",
|
|
29
30
|
initialValue: false
|
|
30
31
|
})) throw productionDeployCancelledError();
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { CliError } from "../../errors.js";
|
|
2
|
+
//#region src/lib/bucket/provider.ts
|
|
3
|
+
function createManagementBucketProvider(client) {
|
|
4
|
+
return {
|
|
5
|
+
async listBuckets(options) {
|
|
6
|
+
const buckets = [];
|
|
7
|
+
let cursor;
|
|
8
|
+
while (true) {
|
|
9
|
+
const result = await client.GET("/v1/buckets", {
|
|
10
|
+
params: { query: {
|
|
11
|
+
projectId: options.projectId,
|
|
12
|
+
branchGitName: options.branchName,
|
|
13
|
+
cursor
|
|
14
|
+
} },
|
|
15
|
+
signal: options.signal
|
|
16
|
+
});
|
|
17
|
+
if (result.error || !result.data) throw bucketApiError("Failed to list buckets", result.response, result.error);
|
|
18
|
+
const data = result.data;
|
|
19
|
+
buckets.push(...data.data);
|
|
20
|
+
if (!data.pagination.hasMore || !data.pagination.nextCursor) break;
|
|
21
|
+
cursor = data.pagination.nextCursor;
|
|
22
|
+
}
|
|
23
|
+
return buckets.map(normalizeBucket);
|
|
24
|
+
},
|
|
25
|
+
async createBucket(options) {
|
|
26
|
+
const result = await client.POST("/v1/buckets", {
|
|
27
|
+
body: {
|
|
28
|
+
projectId: options.projectId,
|
|
29
|
+
...options.name ? { name: options.name } : {},
|
|
30
|
+
...options.branchGitName ? { branchGitName: options.branchGitName } : {}
|
|
31
|
+
},
|
|
32
|
+
signal: options.signal
|
|
33
|
+
});
|
|
34
|
+
if (result.error || !result.data) throw bucketApiError("Failed to create bucket", result.response, result.error);
|
|
35
|
+
const data = result.data;
|
|
36
|
+
return normalizeBucket(data.data);
|
|
37
|
+
},
|
|
38
|
+
async deleteBucket(bucketId, options) {
|
|
39
|
+
const result = await client.DELETE("/v1/buckets/{bucketId}", {
|
|
40
|
+
params: { path: { bucketId } },
|
|
41
|
+
signal: options?.signal
|
|
42
|
+
});
|
|
43
|
+
if (result.error) throw bucketApiError("Failed to delete bucket", result.response, result.error);
|
|
44
|
+
},
|
|
45
|
+
async listKeys(bucketId, options) {
|
|
46
|
+
const keys = [];
|
|
47
|
+
let cursor;
|
|
48
|
+
while (true) {
|
|
49
|
+
const result = await client.GET("/v1/buckets/{bucketId}/keys", {
|
|
50
|
+
params: {
|
|
51
|
+
path: { bucketId },
|
|
52
|
+
query: { cursor }
|
|
53
|
+
},
|
|
54
|
+
signal: options?.signal
|
|
55
|
+
});
|
|
56
|
+
if (result.error || !result.data) throw bucketApiError("Failed to list bucket keys", result.response, result.error);
|
|
57
|
+
const data = result.data;
|
|
58
|
+
keys.push(...data.data);
|
|
59
|
+
if (!data.pagination.hasMore || !data.pagination.nextCursor) break;
|
|
60
|
+
cursor = data.pagination.nextCursor;
|
|
61
|
+
}
|
|
62
|
+
return keys.map(normalizeKey);
|
|
63
|
+
},
|
|
64
|
+
async createKey(options) {
|
|
65
|
+
const result = await client.POST("/v1/buckets/{bucketId}/keys", {
|
|
66
|
+
params: { path: { bucketId: options.bucketId } },
|
|
67
|
+
body: {
|
|
68
|
+
role: options.role,
|
|
69
|
+
...options.name ? { name: options.name } : {}
|
|
70
|
+
},
|
|
71
|
+
signal: options.signal
|
|
72
|
+
});
|
|
73
|
+
if (result.error || !result.data) throw bucketApiError("Failed to create bucket key", result.response, result.error);
|
|
74
|
+
const raw = result.data.data;
|
|
75
|
+
const secretAccessKey = raw.secretAccessKey;
|
|
76
|
+
const accessKeyId = raw.accessKeyId;
|
|
77
|
+
const endpoint = raw.endpoint;
|
|
78
|
+
const bucketName = raw.bucketName;
|
|
79
|
+
if (!secretAccessKey || !accessKeyId || !endpoint || !bucketName) throw new CliError({
|
|
80
|
+
code: "BUCKET_KEY_SECRET_MISSING",
|
|
81
|
+
domain: "bucket",
|
|
82
|
+
summary: "Created bucket key did not return credentials",
|
|
83
|
+
why: "Bucket key credentials are one-time-view secrets, but the Management API did not include them in this create response.",
|
|
84
|
+
fix: "Create another bucket key and store the returned credentials immediately.",
|
|
85
|
+
exitCode: 1,
|
|
86
|
+
nextSteps: [`prisma-cli bucket key create ${options.bucketId}`]
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
key: normalizeKey(raw),
|
|
90
|
+
secretAccessKey,
|
|
91
|
+
accessKeyId,
|
|
92
|
+
endpoint,
|
|
93
|
+
bucketName
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
async deleteKey(bucketId, keyId, options) {
|
|
97
|
+
const result = await client.DELETE("/v1/buckets/{bucketId}/keys/{keyId}", {
|
|
98
|
+
params: { path: {
|
|
99
|
+
bucketId,
|
|
100
|
+
keyId
|
|
101
|
+
} },
|
|
102
|
+
signal: options?.signal
|
|
103
|
+
});
|
|
104
|
+
if (result.error) throw bucketApiError("Failed to delete bucket key", result.response, result.error);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function normalizeBucket(raw) {
|
|
109
|
+
return {
|
|
110
|
+
id: raw.id,
|
|
111
|
+
name: raw.name,
|
|
112
|
+
status: raw.status,
|
|
113
|
+
branchId: raw.branchId,
|
|
114
|
+
createdAt: raw.createdAt
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function normalizeKey(raw) {
|
|
118
|
+
return {
|
|
119
|
+
id: raw.id,
|
|
120
|
+
name: raw.name,
|
|
121
|
+
role: raw.role,
|
|
122
|
+
valueHint: raw.valueHint,
|
|
123
|
+
createdAt: raw.createdAt
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function bucketApiError(summary, response, error) {
|
|
127
|
+
const status = response?.status ?? 0;
|
|
128
|
+
return new CliError({
|
|
129
|
+
code: error?.error?.code ?? "BUCKET_API_ERROR",
|
|
130
|
+
domain: "bucket",
|
|
131
|
+
summary,
|
|
132
|
+
why: error?.error?.message ?? `The Management API returned status ${status || "unknown"}.`,
|
|
133
|
+
fix: error?.error?.hint ?? "Re-run with --trace for the underlying API response details.",
|
|
134
|
+
exitCode: 1,
|
|
135
|
+
nextSteps: []
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
export { createManagementBucketProvider };
|