@looma/prisma-cli 0.1.1 → 0.1.3
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 +17 -0
- package/dist/controllers/app.js +7 -0
- package/dist/lib/app/bun-project.js +39 -0
- package/dist/lib/app/local-dev.js +6 -35
- package/dist/lib/app/prototype-build.js +186 -12
- package/dist/shell/errors.js +2 -0
- package/dist/shell/output.js +7 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,23 @@ pnpm prisma-cli auth login
|
|
|
15
15
|
pnpm prisma-cli app deploy
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
Minimal Bun smoke flow:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
mkdir my-bun-app
|
|
22
|
+
cd my-bun-app
|
|
23
|
+
bun init --yes
|
|
24
|
+
pnpm add -D @looma/prisma-cli
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then replace `index.ts` with a small `Bun.serve(...)` server and run:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pnpm prisma-cli app build
|
|
31
|
+
pnpm prisma-cli auth login
|
|
32
|
+
pnpm prisma-cli app deploy --app my-bun-app
|
|
33
|
+
```
|
|
34
|
+
|
|
18
35
|
Notes:
|
|
19
36
|
|
|
20
37
|
- the official Prisma ORM package still owns the `prisma` executable
|
package/dist/controllers/app.js
CHANGED
|
@@ -591,6 +591,7 @@ function deployFailedError(summary, error, nextSteps) {
|
|
|
591
591
|
summary,
|
|
592
592
|
why: error instanceof Error ? error.message : String(error),
|
|
593
593
|
fix: "Retry the command, or rerun with --trace for more detailed diagnostics.",
|
|
594
|
+
debug: formatDebugDetails(error),
|
|
594
595
|
exitCode: 1,
|
|
595
596
|
nextSteps
|
|
596
597
|
});
|
|
@@ -613,6 +614,7 @@ function buildFailedError(summary, error) {
|
|
|
613
614
|
summary,
|
|
614
615
|
why: error instanceof Error ? error.message : String(error),
|
|
615
616
|
fix: "Inspect the framework output, fix the build issue, and rerun prisma app build.",
|
|
617
|
+
debug: formatDebugDetails(error),
|
|
616
618
|
exitCode: 1,
|
|
617
619
|
nextSteps: ["prisma app build", "prisma app deploy"]
|
|
618
620
|
});
|
|
@@ -638,6 +640,7 @@ function removeFailedError(summary, error, nextSteps) {
|
|
|
638
640
|
summary,
|
|
639
641
|
why: error instanceof Error ? error.message : String(error),
|
|
640
642
|
fix: "Retry the command, or rerun with --trace for more detailed diagnostics.",
|
|
643
|
+
debug: formatDebugDetails(error),
|
|
641
644
|
exitCode: 1,
|
|
642
645
|
nextSteps
|
|
643
646
|
});
|
|
@@ -645,6 +648,10 @@ function removeFailedError(summary, error, nextSteps) {
|
|
|
645
648
|
function localStateCleanupWarning(target, error) {
|
|
646
649
|
return `The app was removed remotely, but the local ${target} state could not be cleared: ${error instanceof Error ? error.message : String(error)}`;
|
|
647
650
|
}
|
|
651
|
+
function formatDebugDetails(error) {
|
|
652
|
+
if (error instanceof Error) return error.stack ?? error.message;
|
|
653
|
+
return typeof error === "string" ? error : null;
|
|
654
|
+
}
|
|
648
655
|
function isMissingProjectError(error) {
|
|
649
656
|
return error instanceof Error && error.message === "Resource Not Found";
|
|
650
657
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { access, readFile } from "node:fs/promises";
|
|
3
|
+
//#region src/lib/app/bun-project.ts
|
|
4
|
+
async function readBunPackageJson(appPath) {
|
|
5
|
+
const packageJsonPath = path.join(appPath, "package.json");
|
|
6
|
+
let content;
|
|
7
|
+
try {
|
|
8
|
+
content = await readFile(packageJsonPath, "utf8");
|
|
9
|
+
} catch (error) {
|
|
10
|
+
if (error.code === "ENOENT") return null;
|
|
11
|
+
throw new Error(`Failed to read ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(content);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
throw new Error(`Failed to parse ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function readBunPackageEntrypoint(packageJson) {
|
|
20
|
+
if (typeof packageJson?.main === "string") return packageJson.main;
|
|
21
|
+
if (typeof packageJson?.module === "string") return packageJson.module;
|
|
22
|
+
}
|
|
23
|
+
async function resolveBunEntrypoint(appPath, explicitEntrypoint) {
|
|
24
|
+
const packageJson = await readBunPackageJson(appPath);
|
|
25
|
+
const candidate = explicitEntrypoint ?? readBunPackageEntrypoint(packageJson);
|
|
26
|
+
if (!candidate) throw new Error("Entrypoint is required. Pass --entry or define package.json main or module.");
|
|
27
|
+
if (path.isAbsolute(candidate)) throw new Error("Entrypoint must be a relative path.");
|
|
28
|
+
const normalized = path.normalize(candidate);
|
|
29
|
+
if (normalized.startsWith("..") || path.isAbsolute(normalized) || normalized.includes(`${path.sep}..${path.sep}`)) throw new Error("Entrypoint must not escape the app directory.");
|
|
30
|
+
const entrypointPath = path.join(appPath, normalized);
|
|
31
|
+
try {
|
|
32
|
+
await access(entrypointPath);
|
|
33
|
+
} catch {
|
|
34
|
+
throw new Error(`Entrypoint file does not exist: ${entrypointPath}`);
|
|
35
|
+
}
|
|
36
|
+
return normalized.split(path.sep).join("/");
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { readBunPackageEntrypoint, readBunPackageJson, resolveBunEntrypoint };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { readBunPackageEntrypoint, readBunPackageJson, resolveBunEntrypoint } from "./bun-project.js";
|
|
1
2
|
import path from "node:path";
|
|
2
|
-
import { access
|
|
3
|
+
import { access } from "node:fs/promises";
|
|
3
4
|
import { spawn } from "node:child_process";
|
|
4
5
|
//#region src/lib/app/local-dev.ts
|
|
5
6
|
const NEXT_CONFIG_FILENAMES = [
|
|
@@ -18,21 +19,6 @@ async function detectLocalBuildType(appPath) {
|
|
|
18
19
|
if (await isBunProject(appPath)) return "bun";
|
|
19
20
|
return null;
|
|
20
21
|
}
|
|
21
|
-
async function resolveBunEntrypoint(appPath, explicitEntrypoint) {
|
|
22
|
-
const packageJson = await readPackageJson(appPath);
|
|
23
|
-
const candidate = explicitEntrypoint ?? (typeof packageJson?.main === "string" ? packageJson.main : void 0);
|
|
24
|
-
if (!candidate) throw new Error("Entrypoint is required. Pass --entry or define package.json main.");
|
|
25
|
-
if (path.isAbsolute(candidate)) throw new Error("Entrypoint must be a relative path.");
|
|
26
|
-
const normalized = path.normalize(candidate);
|
|
27
|
-
if (normalized.startsWith("..") || path.isAbsolute(normalized) || normalized.includes(`${path.sep}..${path.sep}`)) throw new Error("Entrypoint must not escape the app directory.");
|
|
28
|
-
const entrypointPath = path.join(appPath, normalized);
|
|
29
|
-
try {
|
|
30
|
-
await access(entrypointPath);
|
|
31
|
-
} catch {
|
|
32
|
-
throw new Error(`Entrypoint file does not exist: ${entrypointPath}`);
|
|
33
|
-
}
|
|
34
|
-
return normalized.split(path.sep).join("/");
|
|
35
|
-
}
|
|
36
22
|
async function runLocalApp(options) {
|
|
37
23
|
const spawnImpl = options.spawnImpl ?? spawn;
|
|
38
24
|
if (options.buildType === "nextjs") {
|
|
@@ -108,7 +94,7 @@ async function isNextProject(appPath) {
|
|
|
108
94
|
await access(path.join(appPath, fileName));
|
|
109
95
|
return true;
|
|
110
96
|
} catch {}
|
|
111
|
-
return hasDependency(await
|
|
97
|
+
return hasDependency(await readBunPackageJson(appPath), "next");
|
|
112
98
|
}
|
|
113
99
|
async function isBunProject(appPath) {
|
|
114
100
|
try {
|
|
@@ -119,32 +105,17 @@ async function isBunProject(appPath) {
|
|
|
119
105
|
await access(path.join(appPath, "bun.lockb"));
|
|
120
106
|
return true;
|
|
121
107
|
} catch {}
|
|
122
|
-
const packageJson = await
|
|
108
|
+
const packageJson = await readBunPackageJson(appPath);
|
|
123
109
|
if (!packageJson) return false;
|
|
124
|
-
const
|
|
110
|
+
const hasEntrypoint = typeof readBunPackageEntrypoint(packageJson) === "string";
|
|
125
111
|
const hasBunDependency = hasDependency(packageJson, "@types/bun") || hasDependency(packageJson, "bun");
|
|
126
112
|
const usesBunScripts = (typeof packageJson.scripts === "object" && packageJson.scripts !== null ? Object.values(packageJson.scripts) : []).some((value) => typeof value === "string" && /\bbun\b/.test(value));
|
|
127
|
-
return
|
|
113
|
+
return hasEntrypoint && (hasBunDependency || usesBunScripts);
|
|
128
114
|
}
|
|
129
115
|
function hasDependency(packageJson, dependencyName) {
|
|
130
116
|
if (!packageJson) return false;
|
|
131
117
|
return [packageJson.dependencies, packageJson.devDependencies].some((group) => typeof group === "object" && group !== null && dependencyName in group);
|
|
132
118
|
}
|
|
133
|
-
async function readPackageJson(appPath) {
|
|
134
|
-
const packageJsonPath = path.join(appPath, "package.json");
|
|
135
|
-
let content;
|
|
136
|
-
try {
|
|
137
|
-
content = await readFile(packageJsonPath, "utf8");
|
|
138
|
-
} catch (error) {
|
|
139
|
-
if (error.code === "ENOENT") return null;
|
|
140
|
-
throw new Error(`Failed to read ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
return JSON.parse(content);
|
|
144
|
-
} catch (error) {
|
|
145
|
-
throw new Error(`Failed to parse ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
119
|
async function runWithFallback(candidates, options, spawnImpl, missingCommandMessage) {
|
|
149
120
|
for (const candidate of candidates) try {
|
|
150
121
|
const result = await spawnCommand(candidate, options, spawnImpl);
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import { resolveBunEntrypoint } from "./bun-project.js";
|
|
1
2
|
import path from "node:path";
|
|
2
|
-
import { cp, readdir, readlink, rm, stat } from "node:fs/promises";
|
|
3
|
-
import
|
|
3
|
+
import { chmod, copyFile, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, rm, stat } from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { execFile } from "node:child_process";
|
|
6
|
+
import { BunBuild } from "@prisma/compute-sdk";
|
|
4
7
|
//#region src/lib/app/prototype-build.ts
|
|
8
|
+
const NEXT_CONFIG_FILENAMES = [
|
|
9
|
+
"next.config.js",
|
|
10
|
+
"next.config.mjs",
|
|
11
|
+
"next.config.ts",
|
|
12
|
+
"next.config.mts"
|
|
13
|
+
];
|
|
5
14
|
var PrototypeBuildStrategy = class {
|
|
6
15
|
#appPath;
|
|
7
16
|
#entrypoint;
|
|
@@ -49,28 +58,132 @@ async function executePrototypeBuild(options) {
|
|
|
49
58
|
async function resolvePrototypeBuildStrategy(options) {
|
|
50
59
|
if (options.buildType === "nextjs") return {
|
|
51
60
|
buildType: "nextjs",
|
|
52
|
-
strategy: new
|
|
61
|
+
strategy: new PrototypeNextjsBuild({ appPath: options.appPath })
|
|
53
62
|
};
|
|
54
|
-
if (options.buildType === "bun")
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
if (options.buildType === "bun") {
|
|
64
|
+
const entrypoint = await resolveBunEntrypoint(options.appPath, options.entrypoint);
|
|
65
|
+
return {
|
|
66
|
+
buildType: "bun",
|
|
67
|
+
strategy: new BunBuild({
|
|
68
|
+
appPath: options.appPath,
|
|
69
|
+
entrypoint
|
|
70
|
+
})
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const nextjsStrategy = new PrototypeNextjsBuild({ appPath: options.appPath });
|
|
62
74
|
if (await nextjsStrategy.canBuild()) return {
|
|
63
75
|
buildType: "nextjs",
|
|
64
76
|
strategy: nextjsStrategy
|
|
65
77
|
};
|
|
78
|
+
const entrypoint = await resolveBunEntrypoint(options.appPath, options.entrypoint);
|
|
66
79
|
return {
|
|
67
80
|
buildType: "bun",
|
|
68
81
|
strategy: new BunBuild({
|
|
69
82
|
appPath: options.appPath,
|
|
70
|
-
entrypoint
|
|
83
|
+
entrypoint
|
|
71
84
|
})
|
|
72
85
|
};
|
|
73
86
|
}
|
|
87
|
+
var PrototypeNextjsBuild = class {
|
|
88
|
+
#appPath;
|
|
89
|
+
constructor(options) {
|
|
90
|
+
this.#appPath = options.appPath;
|
|
91
|
+
}
|
|
92
|
+
async canBuild() {
|
|
93
|
+
return await this.#hasNextConfig() || await this.#hasNextDependency();
|
|
94
|
+
}
|
|
95
|
+
async execute() {
|
|
96
|
+
await this.#runBuild();
|
|
97
|
+
const standaloneDir = path.join(this.#appPath, ".next", "standalone");
|
|
98
|
+
if (!(await stat(standaloneDir).catch(() => null))?.isDirectory()) throw new Error("Next.js build did not produce standalone output. Add output: \"standalone\" to your next.config file.");
|
|
99
|
+
const outDir = await mkdtemp(path.join(os.tmpdir(), "compute-build-"));
|
|
100
|
+
try {
|
|
101
|
+
const artifactDir = path.join(outDir, "app");
|
|
102
|
+
await stageNextjsStandaloneArtifact({
|
|
103
|
+
standaloneDir,
|
|
104
|
+
artifactDir,
|
|
105
|
+
appPath: this.#appPath
|
|
106
|
+
});
|
|
107
|
+
const publicDir = path.join(this.#appPath, "public");
|
|
108
|
+
if (await directoryExists(publicDir)) await cp(publicDir, path.join(artifactDir, "public"), { recursive: true });
|
|
109
|
+
const staticDir = path.join(this.#appPath, ".next", "static");
|
|
110
|
+
if (await directoryExists(staticDir)) await cp(staticDir, path.join(artifactDir, ".next", "static"), { recursive: true });
|
|
111
|
+
return {
|
|
112
|
+
directory: artifactDir,
|
|
113
|
+
entrypoint: "server.js",
|
|
114
|
+
defaultPortMapping: { http: 3e3 },
|
|
115
|
+
cleanup: () => rm(outDir, {
|
|
116
|
+
recursive: true,
|
|
117
|
+
force: true
|
|
118
|
+
})
|
|
119
|
+
};
|
|
120
|
+
} catch (error) {
|
|
121
|
+
await rm(outDir, {
|
|
122
|
+
recursive: true,
|
|
123
|
+
force: true
|
|
124
|
+
});
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async #hasNextConfig() {
|
|
129
|
+
let entries;
|
|
130
|
+
try {
|
|
131
|
+
entries = await readdir(this.#appPath);
|
|
132
|
+
} catch {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return entries.some((entry) => NEXT_CONFIG_FILENAMES.includes(entry));
|
|
136
|
+
}
|
|
137
|
+
async #hasNextDependency() {
|
|
138
|
+
const packageJsonPath = path.join(this.#appPath, "package.json");
|
|
139
|
+
let content;
|
|
140
|
+
try {
|
|
141
|
+
content = await readFile(packageJsonPath, "utf8");
|
|
142
|
+
} catch {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
let parsed;
|
|
146
|
+
try {
|
|
147
|
+
parsed = JSON.parse(content);
|
|
148
|
+
} catch {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
const deps = isRecord(parsed.dependencies) ? parsed.dependencies : {};
|
|
152
|
+
const devDeps = isRecord(parsed.devDependencies) ? parsed.devDependencies : {};
|
|
153
|
+
return "next" in deps || "next" in devDeps;
|
|
154
|
+
}
|
|
155
|
+
async #runBuild() {
|
|
156
|
+
const candidates = [
|
|
157
|
+
{
|
|
158
|
+
command: path.join(this.#appPath, "node_modules", ".bin", "next"),
|
|
159
|
+
args: ["build"]
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
command: "npx",
|
|
163
|
+
args: ["next", "build"]
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
command: "bunx",
|
|
167
|
+
args: ["next", "build"]
|
|
168
|
+
}
|
|
169
|
+
];
|
|
170
|
+
for (const { command, args } of candidates) try {
|
|
171
|
+
await exec(command, args, this.#appPath);
|
|
172
|
+
return;
|
|
173
|
+
} catch (error) {
|
|
174
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") continue;
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
throw new Error("Could not find the Next.js CLI. Install it with `npm install next` or ensure npx/bunx is available.");
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
async function stageNextjsStandaloneArtifact(options) {
|
|
181
|
+
const standaloneRoot = path.resolve(options.standaloneDir);
|
|
182
|
+
await copyPathMaterializingSymlinks(standaloneRoot, path.resolve(options.artifactDir), {
|
|
183
|
+
standaloneRoot,
|
|
184
|
+
appRoot: path.resolve(options.appPath)
|
|
185
|
+
});
|
|
186
|
+
}
|
|
74
187
|
async function normalizeArtifactSymlinks(artifactDir, appPath) {
|
|
75
188
|
const normalizedArtifactDir = path.resolve(artifactDir);
|
|
76
189
|
const normalizedAppPath = path.resolve(appPath);
|
|
@@ -105,5 +218,66 @@ function isPathWithin(rootPath, candidatePath) {
|
|
|
105
218
|
const relativePath = path.relative(rootPath, candidatePath);
|
|
106
219
|
return relativePath === "" || !relativePath.startsWith(`..${path.sep}`) && relativePath !== ".." && !path.isAbsolute(relativePath);
|
|
107
220
|
}
|
|
221
|
+
async function copyPathMaterializingSymlinks(sourcePath, destinationPath, options) {
|
|
222
|
+
const sourceStat = await lstat(sourcePath);
|
|
223
|
+
if (sourceStat.isSymbolicLink()) {
|
|
224
|
+
await copyPathMaterializingSymlinks(await resolveSymlinkTarget(sourcePath, options), destinationPath, options);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (sourceStat.isDirectory()) {
|
|
228
|
+
await mkdir(destinationPath, { recursive: true });
|
|
229
|
+
const entries = await readdir(sourcePath, { withFileTypes: true });
|
|
230
|
+
for (const entry of entries) await copyPathMaterializingSymlinks(path.join(sourcePath, entry.name), path.join(destinationPath, entry.name), options);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (sourceStat.isFile()) {
|
|
234
|
+
await mkdir(path.dirname(destinationPath), { recursive: true });
|
|
235
|
+
await copyFile(sourcePath, destinationPath);
|
|
236
|
+
await chmod(destinationPath, sourceStat.mode);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async function resolveSymlinkTarget(symlinkPath, options) {
|
|
240
|
+
const linkTarget = await readlink(symlinkPath);
|
|
241
|
+
const resolvedTarget = path.resolve(path.dirname(symlinkPath), linkTarget);
|
|
242
|
+
if (await pathExists(resolvedTarget)) {
|
|
243
|
+
if (!isPathWithin(options.appRoot, resolvedTarget)) throw new Error(`Build artifact symlink escapes the app directory: ${resolvedTarget}`);
|
|
244
|
+
return resolvedTarget;
|
|
245
|
+
}
|
|
246
|
+
if (isPathWithin(options.standaloneRoot, resolvedTarget)) {
|
|
247
|
+
const fallbackTarget = path.join(options.appRoot, path.relative(options.standaloneRoot, resolvedTarget));
|
|
248
|
+
if (await pathExists(fallbackTarget)) return fallbackTarget;
|
|
249
|
+
}
|
|
250
|
+
throw new Error(`Next.js standalone symlink target is missing: ${symlinkPath} -> ${linkTarget} (resolved to ${resolvedTarget})`);
|
|
251
|
+
}
|
|
252
|
+
async function directoryExists(dirPath) {
|
|
253
|
+
return (await stat(dirPath).catch(() => null))?.isDirectory() ?? false;
|
|
254
|
+
}
|
|
255
|
+
function exec(command, args, cwd) {
|
|
256
|
+
return new Promise((resolve, reject) => {
|
|
257
|
+
execFile(command, args, { cwd }, (error, _stdout, stderr) => {
|
|
258
|
+
if (error) {
|
|
259
|
+
if ("code" in error && error.code === "ENOENT") {
|
|
260
|
+
reject(Object.assign(/* @__PURE__ */ new Error(`${command} not found`), { code: "ENOENT" }));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const message = stderr.trim() || error.message;
|
|
264
|
+
reject(/* @__PURE__ */ new Error(`Next.js build failed:\n${message}`));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
resolve();
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
function isRecord(value) {
|
|
272
|
+
return typeof value === "object" && value !== null;
|
|
273
|
+
}
|
|
274
|
+
async function pathExists(targetPath) {
|
|
275
|
+
try {
|
|
276
|
+
await stat(targetPath);
|
|
277
|
+
return true;
|
|
278
|
+
} catch {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
108
282
|
//#endregion
|
|
109
283
|
export { PrototypeBuildStrategy, executePrototypeBuild };
|
package/dist/shell/errors.js
CHANGED
|
@@ -6,6 +6,7 @@ var CliError = class extends Error {
|
|
|
6
6
|
summary;
|
|
7
7
|
why;
|
|
8
8
|
fix;
|
|
9
|
+
debug;
|
|
9
10
|
where;
|
|
10
11
|
meta;
|
|
11
12
|
docsUrl;
|
|
@@ -20,6 +21,7 @@ var CliError = class extends Error {
|
|
|
20
21
|
this.summary = options.summary;
|
|
21
22
|
this.why = options.why;
|
|
22
23
|
this.fix = options.fix;
|
|
24
|
+
this.debug = options.debug ?? null;
|
|
23
25
|
this.where = options.where ?? null;
|
|
24
26
|
this.meta = options.meta ?? {};
|
|
25
27
|
this.docsUrl = options.docsUrl ?? null;
|
package/dist/shell/output.js
CHANGED
|
@@ -37,7 +37,13 @@ function writeHumanError(output, ui, error, options) {
|
|
|
37
37
|
lines.push(`Why: ${error.why}`);
|
|
38
38
|
}
|
|
39
39
|
if (error.fix) lines.push(`Fix: ${error.fix}`);
|
|
40
|
-
if (
|
|
40
|
+
if (options.trace) {
|
|
41
|
+
if (error.debug) {
|
|
42
|
+
lines.push("");
|
|
43
|
+
lines.push("Trace:");
|
|
44
|
+
lines.push(...error.debug.trimEnd().split("\n"));
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
41
47
|
lines.push("");
|
|
42
48
|
lines.push("More: Re-run with --trace for deeper diagnostics");
|
|
43
49
|
}
|