create-prisma 0.13.1 → 0.13.2-pr.111.376.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 -3
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/{json-output-CPdx9Prn.mjs → json-output-wzlPfgC6.mjs} +244 -48
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -21,8 +21,8 @@ does not include this runtime itself. MongoDB and Deno-only apps do not need it.
|
|
|
21
21
|
|
|
22
22
|
For npm, use 11.6.0 or newer, which includes the [upstream resolver fix](https://github.com/npm/cli/pull/8448).
|
|
23
23
|
Older npm releases can crash resolving the dependency tree (`Cannot read properties of null (reading 'edgesOut')`). Run
|
|
24
|
-
`npm install --global npm@11` to update. create-prisma checks the selected
|
|
25
|
-
|
|
24
|
+
`npm install --global npm@11` to update. create-prisma checks the selected package manager
|
|
25
|
+
before writing project files and never upgrades your package manager automatically. Yarn 1 is not supported.
|
|
26
26
|
|
|
27
27
|
The deployment prompt is:
|
|
28
28
|
|
|
@@ -110,4 +110,4 @@ bun run build
|
|
|
110
110
|
|
|
111
111
|
## Telemetry
|
|
112
112
|
|
|
113
|
-
Published builds may send anonymous usage telemetry. It never includes project names, file paths, or database URLs. Disable it with `DO_NOT_TRACK`, `CREATE_PRISMA_DISABLE_TELEMETRY`, or `CREATE_PRISMA_TELEMETRY_DISABLED`.
|
|
113
|
+
Published builds may send anonymous usage telemetry. It never includes project names, file paths, or database URLs. Failure events carry only stable identifiers such as exit codes and tool error codes, never messages or command output. Disable it with `DO_NOT_TRACK`, `CREATE_PRISMA_DISABLE_TELEMETRY`, or `CREATE_PRISMA_TELEMETRY_DISABLED`.
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as ApplicationLayer } from "./json-output-
|
|
2
|
+
import { a as ApplicationLayer } from "./json-output-wzlPfgC6.mjs";
|
|
3
3
|
import { runCreatePrismaCli } from "./index.mjs";
|
|
4
4
|
import { Effect } from "effect";
|
|
5
5
|
import { NodeRuntime } from "@effect/platform-node-shared";
|
package/dist/index.d.mts
CHANGED
|
@@ -68,7 +68,7 @@ type CreateCommandInput = typeof CreateCommandInputSchema.Type;
|
|
|
68
68
|
//#region src/create-outcome.d.ts
|
|
69
69
|
declare const CreateFailureStageSchema: Schema.Literals<readonly ["validate_input", "collect_context", "scaffold_template", "initialize_prisma", "configure_project", "install_dependencies", "initialize_agent_skills", "emit_contract", "plan_migration", "initialize_git", "authenticate", "select_workspace", "check_project_name", "build", "composer_deploy", "unknown"]>;
|
|
70
70
|
type CreateFailureStage = typeof CreateFailureStageSchema.Type;
|
|
71
|
-
declare const CreateCancellationStageSchema: Schema.Literals<readonly ["project_name", "template", "database_provider", "authoring_style", "package_manager", "agent_skills", "deployment_intent", "select_workspace"]>;
|
|
71
|
+
declare const CreateCancellationStageSchema: Schema.Literals<readonly ["project_name", "template", "database_provider", "authoring_style", "package_manager", "agent_skills", "deployment_intent", "authenticate", "select_workspace"]>;
|
|
72
72
|
type CreateCancellationStage = typeof CreateCancellationStageSchema.Type;
|
|
73
73
|
//#endregion
|
|
74
74
|
//#region src/result.d.ts
|
|
@@ -124,7 +124,7 @@ declare const CreateCommandFailureResultSchema: Schema.Struct<{
|
|
|
124
124
|
readonly schemaVersion: Schema.Literal<1>;
|
|
125
125
|
readonly ok: Schema.Literal<false>;
|
|
126
126
|
readonly error: Schema.Struct<{
|
|
127
|
-
readonly stage: Schema.Union<readonly [Schema.Literals<readonly ["validate_input", "collect_context", "scaffold_template", "initialize_prisma", "configure_project", "install_dependencies", "initialize_agent_skills", "emit_contract", "plan_migration", "initialize_git", "authenticate", "select_workspace", "check_project_name", "build", "composer_deploy", "unknown"]>, Schema.Literals<readonly ["project_name", "template", "database_provider", "authoring_style", "package_manager", "agent_skills", "deployment_intent", "select_workspace"]>, Schema.Literal<"parse_arguments">]>;
|
|
127
|
+
readonly stage: Schema.Union<readonly [Schema.Literals<readonly ["validate_input", "collect_context", "scaffold_template", "initialize_prisma", "configure_project", "install_dependencies", "initialize_agent_skills", "emit_contract", "plan_migration", "initialize_git", "authenticate", "select_workspace", "check_project_name", "build", "composer_deploy", "unknown"]>, Schema.Literals<readonly ["project_name", "template", "database_provider", "authoring_style", "package_manager", "agent_skills", "deployment_intent", "authenticate", "select_workspace"]>, Schema.Literal<"parse_arguments">]>;
|
|
128
128
|
readonly message: Schema.String;
|
|
129
129
|
}>;
|
|
130
130
|
readonly project: Schema.optionalKey<Schema.Struct<{
|
|
@@ -171,7 +171,7 @@ declare const CreateCommandResultSchema: Schema.Union<readonly [Schema.Struct<{
|
|
|
171
171
|
readonly schemaVersion: Schema.Literal<1>;
|
|
172
172
|
readonly ok: Schema.Literal<false>;
|
|
173
173
|
readonly error: Schema.Struct<{
|
|
174
|
-
readonly stage: Schema.Union<readonly [Schema.Literals<readonly ["validate_input", "collect_context", "scaffold_template", "initialize_prisma", "configure_project", "install_dependencies", "initialize_agent_skills", "emit_contract", "plan_migration", "initialize_git", "authenticate", "select_workspace", "check_project_name", "build", "composer_deploy", "unknown"]>, Schema.Literals<readonly ["project_name", "template", "database_provider", "authoring_style", "package_manager", "agent_skills", "deployment_intent", "select_workspace"]>, Schema.Literal<"parse_arguments">]>;
|
|
174
|
+
readonly stage: Schema.Union<readonly [Schema.Literals<readonly ["validate_input", "collect_context", "scaffold_template", "initialize_prisma", "configure_project", "install_dependencies", "initialize_agent_skills", "emit_contract", "plan_migration", "initialize_git", "authenticate", "select_workspace", "check_project_name", "build", "composer_deploy", "unknown"]>, Schema.Literals<readonly ["project_name", "template", "database_provider", "authoring_style", "package_manager", "agent_skills", "deployment_intent", "authenticate", "select_workspace"]>, Schema.Literal<"parse_arguments">]>;
|
|
175
175
|
readonly message: Schema.String;
|
|
176
176
|
}>;
|
|
177
177
|
readonly project: Schema.optionalKey<Schema.Struct<{
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { _ as authoringStyles, b as normalizeDatabaseProvider, c as CreateCommandResultSchema, d as AuthoringStyleSchema, f as CreateCommandInputSchema, g as agentSkillTargets, h as PackageManagerSchema, i as getErrorMessage, l as createCommandFailureResult, m as DatabaseProviderSchema, n as writeJsonResult, o as applicationRuntime, p as CreateTemplateSchema, r as runCreateCommandEffect, s as CREATE_PRISMA_RESULT_SCHEMA_VERSION, t as isJsonOutputRequested, u as AgentSkillTargetSchema, v as createTemplates, x as packageManagers, y as databaseProviderInputs } from "./json-output-
|
|
2
|
+
import { _ as authoringStyles, b as normalizeDatabaseProvider, c as CreateCommandResultSchema, d as AuthoringStyleSchema, f as CreateCommandInputSchema, g as agentSkillTargets, h as PackageManagerSchema, i as getErrorMessage, l as createCommandFailureResult, m as DatabaseProviderSchema, n as writeJsonResult, o as applicationRuntime, p as CreateTemplateSchema, r as runCreateCommandEffect, s as CREATE_PRISMA_RESULT_SCHEMA_VERSION, t as isJsonOutputRequested, u as AgentSkillTargetSchema, v as createTemplates, x as packageManagers, y as databaseProviderInputs } from "./json-output-wzlPfgC6.mjs";
|
|
3
3
|
import { Console, Effect, Option } from "effect";
|
|
4
4
|
import { Argument, CliError, Command, Flag } from "effect/unstable/cli";
|
|
5
5
|
|
|
6
6
|
//#region src/index.ts
|
|
7
|
-
const CLI_VERSION = "0.13.1";
|
|
7
|
+
const CLI_VERSION = "0.13.2-pr.111.376.1";
|
|
8
8
|
const optionalArgument = (name, description) => Argument.string(name).pipe(Argument.withDescription(description), Argument.optional, Argument.map(Option.getOrUndefined));
|
|
9
9
|
const optionalBoolean = (name, description) => Flag.boolean(name).pipe(Flag.withDescription(description), Flag.optional, Flag.map(Option.getOrUndefined));
|
|
10
10
|
const optionalString = (name, description) => Flag.string(name).pipe(Flag.withDescription(description), Flag.optional, Flag.map(Option.getOrUndefined));
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Cause, Clock, Context, Effect, Exit, FileSystem, Layer, ManagedRuntime, Option, Ref, Result, Schema, SchemaTransformation } from "effect";
|
|
3
3
|
import { cancel, confirm, intro, isCancel, log, note, outro, select, spinner, taskLog, text } from "@clack/prompts";
|
|
4
|
+
import { statSync } from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
4
6
|
import { NodeChildProcessSpawner, NodeFileSystem, NodePath, NodeStdio, NodeTerminal } from "@effect/platform-node-shared";
|
|
5
7
|
import { execa } from "execa";
|
|
6
8
|
import { createInterface } from "node:readline";
|
|
9
|
+
import { stripVTControlCharacters, styleText } from "node:util";
|
|
7
10
|
import { randomUUID } from "node:crypto";
|
|
8
11
|
import os from "node:os";
|
|
9
|
-
import path from "node:path";
|
|
10
12
|
import { PostHog } from "posthog-node";
|
|
11
13
|
import Handlebars from "handlebars";
|
|
12
14
|
import { fileURLToPath } from "node:url";
|
|
13
15
|
import { Writable } from "node:stream";
|
|
14
|
-
import { styleText } from "node:util";
|
|
15
16
|
|
|
16
17
|
//#region src/utils/child-process-failure.ts
|
|
17
18
|
const ChildProcessFailureSchema = Schema.Literals([
|
|
@@ -41,6 +42,27 @@ function getChildProcessFailure(error) {
|
|
|
41
42
|
if (typeof exitCode === "number") return "non_zero_exit";
|
|
42
43
|
return "spawn_failed";
|
|
43
44
|
}
|
|
45
|
+
function isFile(filePath) {
|
|
46
|
+
try {
|
|
47
|
+
return statSync(filePath, { throwIfNoEntry: false })?.isFile() === true;
|
|
48
|
+
} catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function isCommandOnWindowsPath({ command, cwd, env }) {
|
|
53
|
+
const environment = {
|
|
54
|
+
...process.env,
|
|
55
|
+
...env
|
|
56
|
+
};
|
|
57
|
+
const pathKey = Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH");
|
|
58
|
+
const directories = /[\\/]/.test(command) ? [""] : [cwd, ...(pathKey ? environment[pathKey] ?? "" : "").split(";")];
|
|
59
|
+
const extensions = ["", ...(environment.PATHEXT || ".EXE;.CMD;.BAT;.COM").split(";")];
|
|
60
|
+
return directories.some((directory) => extensions.some((extension) => isFile(path.resolve(cwd, directory.replace(/^"(.*)"$/, "$1"), command + extension))));
|
|
61
|
+
}
|
|
62
|
+
function getSpawnedCommandFailure(error, spawned) {
|
|
63
|
+
const failure = getChildProcessFailure(error);
|
|
64
|
+
return failure === "non_zero_exit" && (spawned.platform ?? process.platform) === "win32" && !isCommandOnWindowsPath(spawned) ? "command_not_found" : failure;
|
|
65
|
+
}
|
|
44
66
|
|
|
45
67
|
//#endregion
|
|
46
68
|
//#region src/create-outcome.ts
|
|
@@ -66,6 +88,8 @@ const CreateFailureReasonSchema = Schema.Literals([
|
|
|
66
88
|
"invalid_input",
|
|
67
89
|
"unsupported_node_version",
|
|
68
90
|
"unsupported_package_manager_version",
|
|
91
|
+
"package_manager_not_found",
|
|
92
|
+
"package_manager_check_failed",
|
|
69
93
|
"invalid_project_name",
|
|
70
94
|
"target_path_not_directory",
|
|
71
95
|
"target_directory_not_empty",
|
|
@@ -99,6 +123,7 @@ const CreateCancellationStageSchema = Schema.Literals([
|
|
|
99
123
|
"package_manager",
|
|
100
124
|
"agent_skills",
|
|
101
125
|
"deployment_intent",
|
|
126
|
+
"authenticate",
|
|
102
127
|
"select_workspace"
|
|
103
128
|
]);
|
|
104
129
|
var CreateCancellationError = class extends Schema.TaggedError()("CreateCancellationError", {
|
|
@@ -119,16 +144,22 @@ var CreateFailure = class extends Schema.TaggedError()("CreateFailure", {
|
|
|
119
144
|
cause: Schema.optionalKey(Schema.Defect()),
|
|
120
145
|
errorReported: Schema.optionalKey(Schema.Boolean)
|
|
121
146
|
}) {};
|
|
147
|
+
const STRUCTURED_ERROR_CODE_PATTERN = /^[A-Z][A-Z0-9_]*(\.[A-Z0-9_]+)+$/;
|
|
148
|
+
function isStructuredErrorCode(value) {
|
|
149
|
+
return typeof value === "string" && STRUCTURED_ERROR_CODE_PATTERN.test(value);
|
|
150
|
+
}
|
|
122
151
|
var PrismaCliCommandError = class extends Schema.TaggedError()("PrismaCliCommandError", {
|
|
123
152
|
message: Schema.String,
|
|
124
153
|
command: Schema.optionalKey(Schema.String),
|
|
125
154
|
code: Schema.optionalKey(Schema.String),
|
|
155
|
+
causeCode: Schema.optionalKey(Schema.String),
|
|
126
156
|
stderr: Schema.optionalKey(Schema.String),
|
|
127
157
|
exitCode: Schema.optionalKey(Schema.Number),
|
|
128
158
|
childProcessFailure: Schema.optional(ChildProcessFailureSchema)
|
|
129
159
|
}) {
|
|
130
160
|
prismaCliCommand = this.command;
|
|
131
161
|
prismaCliErrorCode = this.code;
|
|
162
|
+
prismaCliCauseCode = this.causeCode;
|
|
132
163
|
};
|
|
133
164
|
|
|
134
165
|
//#endregion
|
|
@@ -353,7 +384,7 @@ var CommandRunner = class CommandRunner extends Context.Service()("create-prisma
|
|
|
353
384
|
exitCode: result.exitCode ?? 1,
|
|
354
385
|
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
355
386
|
stderr: typeof result.stderr === "string" ? result.stderr : "",
|
|
356
|
-
childProcessFailure:
|
|
387
|
+
childProcessFailure: getSpawnedCommandFailure(result, spec)
|
|
357
388
|
};
|
|
358
389
|
},
|
|
359
390
|
catch: (cause) => new CommandExecutionError({
|
|
@@ -386,22 +417,47 @@ const NodeCliLayer = Layer.provideMerge(NodeChildProcessSpawner.layer, Layer.mer
|
|
|
386
417
|
const ApplicationLayer = Layer.merge(NodeCliLayer, CommandRunner.layer);
|
|
387
418
|
const applicationRuntime = ManagedRuntime.make(ApplicationLayer);
|
|
388
419
|
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region src/utils/package-manager-error-code.ts
|
|
422
|
+
const grammars = {
|
|
423
|
+
npm: {
|
|
424
|
+
line: /^npm (?:error|ERR!) code (\S+)$/,
|
|
425
|
+
allow: /^E[A-Z0-9_]{2,40}$/
|
|
426
|
+
},
|
|
427
|
+
pnpm: {
|
|
428
|
+
line: /^(?:\[([A-Z0-9_]+)\] |\u2009([A-Z0-9_]+)\u2009 )/,
|
|
429
|
+
allow: /^(?:ERR_PNPM_[A-Z0-9_]{1,60}|E[A-Z0-9_]{2,40})$/
|
|
430
|
+
},
|
|
431
|
+
yarn: {
|
|
432
|
+
line: /^(?:➤ )?(YN\d{4}): /,
|
|
433
|
+
allow: /^YN(?!0000)\d{4}$/
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
function getGrammar(command) {
|
|
437
|
+
const name = command.replace(/^.*[\\/]/, "").replace(/\.(?:cmd|exe)$/i, "").toLowerCase();
|
|
438
|
+
return Object.hasOwn(grammars, name) ? grammars[name] : void 0;
|
|
439
|
+
}
|
|
440
|
+
function getPackageManagerErrorCode(command, output) {
|
|
441
|
+
const grammar = getGrammar(command);
|
|
442
|
+
if (!grammar) return void 0;
|
|
443
|
+
const lines = stripVTControlCharacters(`${output.stdout}\n${output.stderr}`).split(/\r?\n/);
|
|
444
|
+
for (const line of lines.reverse()) {
|
|
445
|
+
const match = grammar.line.exec(line);
|
|
446
|
+
const candidate = match?.[1] ?? match?.[2];
|
|
447
|
+
if (candidate !== void 0 && grammar.allow.test(candidate)) return candidate;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
389
451
|
//#endregion
|
|
390
452
|
//#region src/telemetry/client.ts
|
|
391
|
-
const TELEMETRY_API_KEY = "
|
|
453
|
+
const TELEMETRY_API_KEY = "";
|
|
392
454
|
const TELEMETRY_HOST = "https://us.i.posthog.com";
|
|
393
455
|
const TELEMETRY_CONFIG_FILE = "telemetry.json";
|
|
394
456
|
const TELEMETRY_TIMEOUT_MS = 2e3;
|
|
395
457
|
const AnonymousId = Schema.String.check(Schema.isUUID(4));
|
|
396
458
|
const decodeAnonymousId = Schema.decodeUnknownExit(AnonymousId);
|
|
397
|
-
const isTruthyEnvValue = (value) => [
|
|
398
|
-
"1",
|
|
399
|
-
"true",
|
|
400
|
-
"yes",
|
|
401
|
-
"on"
|
|
402
|
-
].includes(String(value ?? "").trim().toLowerCase());
|
|
403
459
|
function shouldDisableTelemetry() {
|
|
404
|
-
return
|
|
460
|
+
return true;
|
|
405
461
|
}
|
|
406
462
|
function getTelemetryConfigDir() {
|
|
407
463
|
if (process.platform === "darwin") return path.join(os.homedir(), "Library", "Application Support", "create-prisma");
|
|
@@ -424,7 +480,7 @@ const getAnonymousIdEffect = Effect.fn("Telemetry.getAnonymousId")(function* ()
|
|
|
424
480
|
return anonymousId;
|
|
425
481
|
});
|
|
426
482
|
const getCommonProperties = () => ({
|
|
427
|
-
"cli-version": "0.13.1",
|
|
483
|
+
"cli-version": "0.13.2-pr.111.376.1",
|
|
428
484
|
"node-version": process.version,
|
|
429
485
|
platform: process.platform,
|
|
430
486
|
arch: process.arch
|
|
@@ -464,6 +520,7 @@ const expectedRejectionReasons = new Set([
|
|
|
464
520
|
"invalid_input",
|
|
465
521
|
"unsupported_node_version",
|
|
466
522
|
"unsupported_package_manager_version",
|
|
523
|
+
"package_manager_not_found",
|
|
467
524
|
"invalid_project_name",
|
|
468
525
|
"target_path_not_directory",
|
|
469
526
|
"target_directory_not_empty",
|
|
@@ -513,11 +570,18 @@ function getErrorCode(error) {
|
|
|
513
570
|
function getChildProcessFailureProperty(error) {
|
|
514
571
|
return error instanceof CommandExecutionError || error instanceof PrismaCliCommandError ? error.childProcessFailure ?? null : null;
|
|
515
572
|
}
|
|
573
|
+
function getPackageManagerErrorCodeProperty(error) {
|
|
574
|
+
return error instanceof CommandExecutionError ? getPackageManagerErrorCode(error.command, error) ?? null : null;
|
|
575
|
+
}
|
|
516
576
|
function getPrismaCliFailureProperty(error, property) {
|
|
517
577
|
if (typeof error !== "object" || error === null) return null;
|
|
518
578
|
const value = Reflect.get(error, property);
|
|
519
579
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
520
580
|
}
|
|
581
|
+
function getPrismaCliCauseCodeProperty(error) {
|
|
582
|
+
const causeCode = getPrismaCliFailureProperty(error, "prismaCliCauseCode");
|
|
583
|
+
return isStructuredErrorCode(causeCode) ? causeCode : null;
|
|
584
|
+
}
|
|
521
585
|
const trackCreateCompletedEffect = Effect.fn("Telemetry.createCompleted")(function* (params) {
|
|
522
586
|
yield* trackCliTelemetryEffect(CREATE_PRISMA_NEXT_COMPLETED_EVENT, {
|
|
523
587
|
...getBaseCreateProperties(params.input, params.context),
|
|
@@ -535,7 +599,9 @@ const trackCreateFailedEffect = Effect.fn("Telemetry.createFailed")(function* (p
|
|
|
535
599
|
"error-code": getErrorCode(params.error),
|
|
536
600
|
"child-process-failure": getChildProcessFailureProperty(params.error),
|
|
537
601
|
"prisma-cli-command": getPrismaCliFailureProperty(params.error, "prismaCliCommand"),
|
|
538
|
-
"prisma-cli-error-code": getPrismaCliFailureProperty(params.error, "prismaCliErrorCode")
|
|
602
|
+
"prisma-cli-error-code": getPrismaCliFailureProperty(params.error, "prismaCliErrorCode"),
|
|
603
|
+
"prisma-cli-cause-code": getPrismaCliCauseCodeProperty(params.error),
|
|
604
|
+
"package-manager-error-code": params.stage === "install_dependencies" ? getPackageManagerErrorCodeProperty(params.error) : null
|
|
539
605
|
}).pipe(Effect.scoped, Effect.timeout(TELEMETRY_TIMEOUT_MS), Effect.catch(() => Effect.void));
|
|
540
606
|
});
|
|
541
607
|
const trackCreateCancelledEffect = Effect.fn("Telemetry.createCancelled")(function* (params) {
|
|
@@ -626,6 +692,20 @@ function getCreateTemplateDependencies(template, packageManager) {
|
|
|
626
692
|
return targets;
|
|
627
693
|
}
|
|
628
694
|
|
|
695
|
+
//#endregion
|
|
696
|
+
//#region src/utils/errors.ts
|
|
697
|
+
function redactSecrets(message) {
|
|
698
|
+
return message.replace(/\b((?:(?:prisma\+)?postgres(?:ql)?|mongodb(?:\+srv)?):\/\/)[^\s'"]+/gi, "$1<redacted>").replace(/\b([A-Z0-9_]*(?:MONGODB_(?:URL|URI)|DATABASE_URL|TOKEN|SECRET|PASSWORD|API_KEY|PRIVATE_KEY)[A-Z0-9_]*\s*=\s*)(?:"[^"]*"|'[^']*'|[^\s]+)/gi, "$1<redacted>").replace(/(\bAuthorization\s*:\s*Bearer\s+)[^\s'"]+/gi, "$1<redacted>");
|
|
699
|
+
}
|
|
700
|
+
function getErrorMessage(error) {
|
|
701
|
+
if (error instanceof PrismaCliCommandError) return redactSecrets(error.message);
|
|
702
|
+
if (error instanceof Error && "stderr" in error) {
|
|
703
|
+
const stderr = String(error.stderr ?? "").trim();
|
|
704
|
+
if (stderr) return redactSecrets(stderr);
|
|
705
|
+
}
|
|
706
|
+
return redactSecrets(error instanceof Error ? error.message : String(error));
|
|
707
|
+
}
|
|
708
|
+
|
|
629
709
|
//#endregion
|
|
630
710
|
//#region src/utils/package-manager.ts
|
|
631
711
|
const DENO_ALLOW_FRESH_DEPENDENCIES = "--minimum-dependency-age=0";
|
|
@@ -635,22 +715,108 @@ const packageManagerManifestValues = {
|
|
|
635
715
|
yarn: "yarn@4.13.0",
|
|
636
716
|
bun: "bun@1.4.1"
|
|
637
717
|
};
|
|
638
|
-
const
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
718
|
+
const packageManagerChecks = {
|
|
719
|
+
npm: {
|
|
720
|
+
name: "npm",
|
|
721
|
+
versionArgs: ["--version"],
|
|
722
|
+
install: "Install Node.js from https://nodejs.org to get npm",
|
|
723
|
+
minimum: {
|
|
724
|
+
version: [
|
|
725
|
+
11,
|
|
726
|
+
6,
|
|
727
|
+
0
|
|
728
|
+
],
|
|
729
|
+
guidance: "Older npm releases can crash while resolving Prisma dependencies. Run npm install --global npm@11, then retry create-prisma."
|
|
730
|
+
}
|
|
731
|
+
},
|
|
732
|
+
pnpm: {
|
|
733
|
+
name: "pnpm",
|
|
734
|
+
versionArgs: ["--version"],
|
|
735
|
+
install: "Install it from https://pnpm.io/installation"
|
|
736
|
+
},
|
|
737
|
+
yarn: {
|
|
738
|
+
name: "Yarn",
|
|
739
|
+
versionArgs: ["--version"],
|
|
740
|
+
install: "Install it with Corepack (https://yarnpkg.com/corepack)",
|
|
741
|
+
minimum: {
|
|
742
|
+
version: [
|
|
743
|
+
2,
|
|
744
|
+
0,
|
|
745
|
+
0
|
|
746
|
+
],
|
|
747
|
+
guidance: `Generated projects use ${packageManagerManifestValues.yarn}, which Yarn 1 refuses to install. Enable Corepack (https://yarnpkg.com/corepack) or install Yarn 4, then retry create-prisma, or choose another package manager with --package-manager.`
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
bun: {
|
|
751
|
+
name: "Bun",
|
|
752
|
+
versionArgs: ["--version"],
|
|
753
|
+
install: "Install it from https://bun.sh"
|
|
754
|
+
},
|
|
755
|
+
deno: {
|
|
756
|
+
name: "Deno",
|
|
757
|
+
versionArgs: ["-V"],
|
|
758
|
+
install: "Install it from https://docs.deno.com/runtime/getting_started/installation"
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
const PACKAGE_MANAGER_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
762
|
+
function parsePackageManagerVersion(packageManager, version) {
|
|
763
|
+
const prefix = `${packageManager} `;
|
|
764
|
+
const match = PACKAGE_MANAGER_VERSION_PATTERN.exec(version.startsWith(prefix) ? version.slice(prefix.length) : version);
|
|
765
|
+
if (!match) return void 0;
|
|
766
|
+
const parts = [
|
|
767
|
+
Number(match[1]),
|
|
768
|
+
Number(match[2]),
|
|
769
|
+
Number(match[3])
|
|
770
|
+
];
|
|
771
|
+
return parts.every(Number.isSafeInteger) ? parts : void 0;
|
|
772
|
+
}
|
|
773
|
+
function isOlderVersion(version, minimum) {
|
|
774
|
+
for (const [index, part] of version.entries()) if (part !== minimum[index]) return part < minimum[index];
|
|
775
|
+
return false;
|
|
776
|
+
}
|
|
777
|
+
const probePackageManagerEffect = Effect.fn("PackageManager.probe")(function* (packageManager, cwd) {
|
|
778
|
+
const runner = yield* CommandRunner;
|
|
779
|
+
const { name, versionArgs, install, minimum } = packageManagerChecks[packageManager];
|
|
780
|
+
const output = (yield* runner.runChecked({
|
|
781
|
+
command: packageManager,
|
|
782
|
+
args: versionArgs,
|
|
783
|
+
cwd
|
|
784
|
+
}).pipe(Effect.mapError((cause) => cause.childProcessFailure === "command_not_found" ? new CreateFailure({
|
|
785
|
+
stage: "validate_input",
|
|
786
|
+
reason: "package_manager_not_found",
|
|
787
|
+
message: `${name} is not installed or is not on your PATH. ${install}, then retry create-prisma, or choose another package manager with --package-manager.`,
|
|
788
|
+
cause
|
|
789
|
+
}) : new CreateFailure({
|
|
790
|
+
stage: "validate_input",
|
|
791
|
+
reason: "package_manager_check_failed",
|
|
792
|
+
message: `Could not run ${[packageManager, ...versionArgs].join(" ")}: ${getErrorMessage(cause)}`,
|
|
793
|
+
cause
|
|
794
|
+
})))).stdout.trim();
|
|
795
|
+
const version = parsePackageManagerVersion(packageManager, output);
|
|
796
|
+
if (!version) return yield* new CreateFailure({
|
|
797
|
+
stage: "validate_input",
|
|
798
|
+
reason: "package_manager_check_failed",
|
|
799
|
+
message: `Could not determine the installed ${name} version: ${output}`
|
|
800
|
+
});
|
|
801
|
+
if (minimum && isOlderVersion(version, minimum.version)) return yield* new CreateFailure({
|
|
649
802
|
stage: "validate_input",
|
|
650
803
|
reason: "unsupported_package_manager_version",
|
|
651
|
-
message:
|
|
804
|
+
message: `${name} ${version.join(".")} is unsupported. Required: ${name} ${minimum.version.join(".")} or newer. ${minimum.guidance}`
|
|
652
805
|
});
|
|
653
806
|
});
|
|
807
|
+
const verifyPackageManagerEffect = Effect.fn("PackageManager.verify")(function* (packageManager) {
|
|
808
|
+
const fs = yield* FileSystem.FileSystem;
|
|
809
|
+
yield* probePackageManagerEffect(packageManager, yield* fs.makeTempDirectoryScoped({ prefix: "create-prisma-" }).pipe(Effect.tap((directory) => fs.writeFileString(path.join(directory, "package.json"), JSON.stringify({
|
|
810
|
+
name: "create-prisma-probe",
|
|
811
|
+
private: true,
|
|
812
|
+
packageManager: getPackageManagerManifestValue(packageManager)
|
|
813
|
+
}))), Effect.mapError((cause) => new CreateFailure({
|
|
814
|
+
stage: "validate_input",
|
|
815
|
+
reason: "package_manager_check_failed",
|
|
816
|
+
message: `Could not prepare a directory to check ${packageManagerChecks[packageManager].name}: ${getErrorMessage(cause)}`,
|
|
817
|
+
cause
|
|
818
|
+
}))));
|
|
819
|
+
}, Effect.scoped);
|
|
654
820
|
function parseUserAgent(userAgent) {
|
|
655
821
|
if (userAgent?.startsWith("pnpm")) return "pnpm";
|
|
656
822
|
if (userAgent?.startsWith("yarn")) return "yarn";
|
|
@@ -1127,20 +1293,6 @@ const installProjectDependenciesEffect = Effect.fn("Dependencies.install")(funct
|
|
|
1127
1293
|
});
|
|
1128
1294
|
});
|
|
1129
1295
|
|
|
1130
|
-
//#endregion
|
|
1131
|
-
//#region src/utils/errors.ts
|
|
1132
|
-
function redactSecrets(message) {
|
|
1133
|
-
return message.replace(/\b((?:(?:prisma\+)?postgres(?:ql)?|mongodb(?:\+srv)?):\/\/)[^\s'"]+/gi, "$1<redacted>").replace(/\b([A-Z0-9_]*(?:MONGODB_(?:URL|URI)|DATABASE_URL|TOKEN|SECRET|PASSWORD|API_KEY|PRIVATE_KEY)[A-Z0-9_]*\s*=\s*)(?:"[^"]*"|'[^']*'|[^\s]+)/gi, "$1<redacted>").replace(/(\bAuthorization\s*:\s*Bearer\s+)[^\s'"]+/gi, "$1<redacted>");
|
|
1134
|
-
}
|
|
1135
|
-
function getErrorMessage(error) {
|
|
1136
|
-
if (error instanceof PrismaCliCommandError) return redactSecrets(error.message);
|
|
1137
|
-
if (error instanceof Error && "stderr" in error) {
|
|
1138
|
-
const stderr = String(error.stderr ?? "").trim();
|
|
1139
|
-
if (stderr) return redactSecrets(stderr);
|
|
1140
|
-
}
|
|
1141
|
-
return redactSecrets(error instanceof Error ? error.message : String(error));
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
1296
|
//#endregion
|
|
1145
1297
|
//#region src/workflow/failure.ts
|
|
1146
1298
|
const atCreateStage = (effect, stage, reason) => effect.pipe(Effect.mapError((error) => error instanceof CreateFailure || error instanceof CreateCancellationError ? error : new CreateFailure({
|
|
@@ -1256,7 +1408,7 @@ const ensureAuthentication = Effect.fn("Deployment.ensureAuthentication")(functi
|
|
|
1256
1408
|
cwd: options.projectDir,
|
|
1257
1409
|
env: process.env,
|
|
1258
1410
|
stdio: "inherit"
|
|
1259
|
-
});
|
|
1411
|
+
}).pipe(Effect.mapError((error) => error.childProcessFailure === "interrupted" || error.childProcessFailure === "cancelled" ? new CreateCancellationError({ stage: "authenticate" }) : error));
|
|
1260
1412
|
const authenticatedState = yield* whoami();
|
|
1261
1413
|
if (!authenticatedState.authenticated) return yield* new CreateFailure({
|
|
1262
1414
|
stage: "authenticate",
|
|
@@ -1321,10 +1473,7 @@ const selectDeploymentWorkspace = Effect.fn("Deployment.selectWorkspace")(functi
|
|
|
1321
1473
|
})),
|
|
1322
1474
|
output: options.output
|
|
1323
1475
|
}));
|
|
1324
|
-
if (isCancel(selectedWorkspaceId)) {
|
|
1325
|
-
yield* Effect.sync(() => cancel("Operation cancelled.", { output: options.output }));
|
|
1326
|
-
return yield* new CreateCancellationError({ stage: "select_workspace" });
|
|
1327
|
-
}
|
|
1476
|
+
if (isCancel(selectedWorkspaceId)) return yield* new CreateCancellationError({ stage: "select_workspace" });
|
|
1328
1477
|
yield* Effect.sync(() => options.afterPrompt?.());
|
|
1329
1478
|
if (selectedWorkspaceId === activeWorkspace.id) return activeWorkspace;
|
|
1330
1479
|
return yield* useWorkspace({
|
|
@@ -1354,6 +1503,49 @@ function parseComposerDeployResult(result) {
|
|
|
1354
1503
|
};
|
|
1355
1504
|
}
|
|
1356
1505
|
|
|
1506
|
+
//#endregion
|
|
1507
|
+
//#region src/tasks/composer/deploy-report.ts
|
|
1508
|
+
const ComposerRunReportSchema = Schema.fromJsonString(Schema.Struct({
|
|
1509
|
+
version: Schema.Literal(1),
|
|
1510
|
+
failure: Schema.NullOr(Schema.Struct({ code: Schema.String }))
|
|
1511
|
+
}));
|
|
1512
|
+
const decodeComposerRunReport = Schema.decodeUnknownOption(ComposerRunReportSchema);
|
|
1513
|
+
function parseComposerDeployFailureCode(report) {
|
|
1514
|
+
const code = Option.getOrUndefined(decodeComposerRunReport(report))?.failure?.code;
|
|
1515
|
+
return isStructuredErrorCode(code) ? code : void 0;
|
|
1516
|
+
}
|
|
1517
|
+
function withCauseCode(error, causeCode) {
|
|
1518
|
+
return new PrismaCliCommandError({
|
|
1519
|
+
message: error.message,
|
|
1520
|
+
...error.command === void 0 ? {} : { command: error.command },
|
|
1521
|
+
...error.code === void 0 ? {} : { code: error.code },
|
|
1522
|
+
causeCode,
|
|
1523
|
+
...error.stderr === void 0 ? {} : { stderr: error.stderr },
|
|
1524
|
+
...error.exitCode === void 0 ? {} : { exitCode: error.exitCode },
|
|
1525
|
+
childProcessFailure: error.childProcessFailure
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
const readComposerDeployFailureCode = Effect.fn("Deployment.readFailureCode")(function* (reportPath) {
|
|
1529
|
+
const report = yield* (yield* FileSystem.FileSystem).readFileString(reportPath).pipe(Effect.option);
|
|
1530
|
+
return Option.isSome(report) ? parseComposerDeployFailureCode(report.value) : void 0;
|
|
1531
|
+
});
|
|
1532
|
+
const runComposerDeployEffect = Effect.fn("Deployment.runComposerDeploy")(function* (options) {
|
|
1533
|
+
const reportPath = yield* (yield* FileSystem.FileSystem).makeTempDirectoryScoped({ prefix: "create-prisma-deploy-" }).pipe(Effect.map((directory) => path.join(directory, "report.json")), Effect.option, Effect.map(Option.getOrUndefined));
|
|
1534
|
+
return yield* runPrismaJsonCommandEffect({
|
|
1535
|
+
packageManager: options.packageManager,
|
|
1536
|
+
projectDir: options.projectDir,
|
|
1537
|
+
args: [
|
|
1538
|
+
"deploy",
|
|
1539
|
+
"module.ts",
|
|
1540
|
+
...reportPath ? ["--report", reportPath] : []
|
|
1541
|
+
],
|
|
1542
|
+
...options.onStderrLine ? { onStderrLine: options.onStderrLine } : {}
|
|
1543
|
+
}).pipe(Effect.catchTag("PrismaCliCommandError", (error) => Effect.gen(function* () {
|
|
1544
|
+
const causeCode = reportPath ? yield* readComposerDeployFailureCode(reportPath) : void 0;
|
|
1545
|
+
return yield* Effect.fail(causeCode ? withCauseCode(error, causeCode) : error);
|
|
1546
|
+
})));
|
|
1547
|
+
}, Effect.scoped);
|
|
1548
|
+
|
|
1357
1549
|
//#endregion
|
|
1358
1550
|
//#region src/tasks/composer/projects.ts
|
|
1359
1551
|
const ProjectShowResultSchema = Schema.Struct({
|
|
@@ -1493,10 +1685,9 @@ const deployNewProjectWithComposerEffect = Effect.fn("Deployment.deploy")(functi
|
|
|
1493
1685
|
deploymentLog.message(`$ ${deployCommand}`);
|
|
1494
1686
|
}
|
|
1495
1687
|
});
|
|
1496
|
-
const deployment = parseComposerDeployResult(yield* atCreateStage(decodePrismaCommandResult(ComposerDeployCommandResultSchema, yield* atCreateStage(
|
|
1688
|
+
const deployment = parseComposerDeployResult(yield* atCreateStage(decodePrismaCommandResult(ComposerDeployCommandResultSchema, yield* atCreateStage(runComposerDeployEffect({
|
|
1497
1689
|
packageManager: options.packageManager,
|
|
1498
1690
|
projectDir: options.projectDir,
|
|
1499
|
-
args: ["deploy", "module.ts"],
|
|
1500
1691
|
onStderrLine: (line) => {
|
|
1501
1692
|
const redacted = redactSecrets(line);
|
|
1502
1693
|
if (options.verbose) output.write(`${redacted}\n`);
|
|
@@ -1528,12 +1719,17 @@ const deployNewProjectWithComposerEffect = Effect.fn("Deployment.deploy")(functi
|
|
|
1528
1719
|
};
|
|
1529
1720
|
}).pipe(Effect.tapCause((cause) => Effect.sync(() => {
|
|
1530
1721
|
const error = Cause.squash(cause);
|
|
1722
|
+
if (error instanceof CreateCancellationError) {
|
|
1723
|
+
clearProgress();
|
|
1724
|
+
cancel(error.message ?? "Operation cancelled.", { output });
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1531
1727
|
if (deploymentLog) {
|
|
1532
1728
|
deploymentLog.error("Deployment failed.");
|
|
1533
1729
|
deploymentLog = void 0;
|
|
1534
1730
|
} else progress?.error("Deployment failed.");
|
|
1535
1731
|
progressRunning = false;
|
|
1536
|
-
|
|
1732
|
+
log.error(`Deploy failed: ${getErrorMessage(error)}`, { output });
|
|
1537
1733
|
})), Effect.mapError((error) => error instanceof CreateFailure ? new CreateFailure({
|
|
1538
1734
|
stage: error.stage,
|
|
1539
1735
|
reason: error.reason,
|
|
@@ -2285,7 +2481,7 @@ const createProjectEffect = Effect.fn("Create.project")(function* (rawInput, inp
|
|
|
2285
2481
|
yield* Effect.sync(() => intro(getCreatePrismaIntro(), { output }));
|
|
2286
2482
|
const context = yield* atCreateStage(collectCreateContext(input), "collect_context", "unexpected_error");
|
|
2287
2483
|
yield* Ref.set(contextRef, Option.some(context));
|
|
2288
|
-
yield* atCreateStage(verifyPackageManagerEffect(context.prismaSetupContext.packageManager), "
|
|
2484
|
+
yield* atCreateStage(verifyPackageManagerEffect(context.prismaSetupContext.packageManager), "validate_input", "package_manager_check_failed");
|
|
2289
2485
|
return {
|
|
2290
2486
|
input,
|
|
2291
2487
|
context,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-prisma",
|
|
3
|
-
"version": "0.13.1",
|
|
3
|
+
"version": "0.13.2-pr.111.376.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Create Prisma 8 projects with first-party templates and great DX.",
|
|
6
6
|
"homepage": "https://github.com/prisma/create-prisma",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dev": "tsdown --watch",
|
|
38
38
|
"start": "bun run ./dist/cli.mjs",
|
|
39
39
|
"test": "bun run test:unit && bun run test:e2e",
|
|
40
|
-
"test:unit": "bun test ./tests/dependencies.test.ts ./tests/deploy-with-composer.test.ts ./tests/initialize-git.test.ts ./tests/install.test.ts ./tests/json-output.test.ts ./tests/node-version.test.ts ./tests/setup-prisma.test.ts ./tests/telemetry-client.test.ts ./tests/telemetry.test.ts",
|
|
40
|
+
"test:unit": "bun test ./tests/dependencies.test.ts ./tests/deploy-with-composer.test.ts ./tests/initialize-git.test.ts ./tests/install.test.ts ./tests/json-output.test.ts ./tests/node-version.test.ts ./tests/package-manager-error-code.test.ts ./tests/setup-prisma.test.ts ./tests/telemetry-client.test.ts ./tests/telemetry.test.ts",
|
|
41
41
|
"test:e2e": "bun test --timeout 180000 ./tests/e2e/create-prisma.e2e.test.ts",
|
|
42
42
|
"check": "bun run format:check && bun run lint",
|
|
43
43
|
"lint": "oxlint . --deny-warnings",
|