create-prisma 0.13.1 → 0.13.2
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-Ey4ovDiE.mjs} +242 -40
- 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-Ey4ovDiE.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-Ey4ovDiE.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.
|
|
7
|
+
const CLI_VERSION = "0.13.2";
|
|
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,6 +417,37 @@ 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
453
|
const TELEMETRY_API_KEY = "phc_cmc85avbWyuJ2JyKdGPdv7dxXli8xLdWDBPbvIXWJfs";
|
|
@@ -424,7 +486,7 @@ const getAnonymousIdEffect = Effect.fn("Telemetry.getAnonymousId")(function* ()
|
|
|
424
486
|
return anonymousId;
|
|
425
487
|
});
|
|
426
488
|
const getCommonProperties = () => ({
|
|
427
|
-
"cli-version": "0.13.
|
|
489
|
+
"cli-version": "0.13.2",
|
|
428
490
|
"node-version": process.version,
|
|
429
491
|
platform: process.platform,
|
|
430
492
|
arch: process.arch
|
|
@@ -464,6 +526,7 @@ const expectedRejectionReasons = new Set([
|
|
|
464
526
|
"invalid_input",
|
|
465
527
|
"unsupported_node_version",
|
|
466
528
|
"unsupported_package_manager_version",
|
|
529
|
+
"package_manager_not_found",
|
|
467
530
|
"invalid_project_name",
|
|
468
531
|
"target_path_not_directory",
|
|
469
532
|
"target_directory_not_empty",
|
|
@@ -513,11 +576,18 @@ function getErrorCode(error) {
|
|
|
513
576
|
function getChildProcessFailureProperty(error) {
|
|
514
577
|
return error instanceof CommandExecutionError || error instanceof PrismaCliCommandError ? error.childProcessFailure ?? null : null;
|
|
515
578
|
}
|
|
579
|
+
function getPackageManagerErrorCodeProperty(error) {
|
|
580
|
+
return error instanceof CommandExecutionError ? getPackageManagerErrorCode(error.command, error) ?? null : null;
|
|
581
|
+
}
|
|
516
582
|
function getPrismaCliFailureProperty(error, property) {
|
|
517
583
|
if (typeof error !== "object" || error === null) return null;
|
|
518
584
|
const value = Reflect.get(error, property);
|
|
519
585
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
520
586
|
}
|
|
587
|
+
function getPrismaCliCauseCodeProperty(error) {
|
|
588
|
+
const causeCode = getPrismaCliFailureProperty(error, "prismaCliCauseCode");
|
|
589
|
+
return isStructuredErrorCode(causeCode) ? causeCode : null;
|
|
590
|
+
}
|
|
521
591
|
const trackCreateCompletedEffect = Effect.fn("Telemetry.createCompleted")(function* (params) {
|
|
522
592
|
yield* trackCliTelemetryEffect(CREATE_PRISMA_NEXT_COMPLETED_EVENT, {
|
|
523
593
|
...getBaseCreateProperties(params.input, params.context),
|
|
@@ -535,7 +605,9 @@ const trackCreateFailedEffect = Effect.fn("Telemetry.createFailed")(function* (p
|
|
|
535
605
|
"error-code": getErrorCode(params.error),
|
|
536
606
|
"child-process-failure": getChildProcessFailureProperty(params.error),
|
|
537
607
|
"prisma-cli-command": getPrismaCliFailureProperty(params.error, "prismaCliCommand"),
|
|
538
|
-
"prisma-cli-error-code": getPrismaCliFailureProperty(params.error, "prismaCliErrorCode")
|
|
608
|
+
"prisma-cli-error-code": getPrismaCliFailureProperty(params.error, "prismaCliErrorCode"),
|
|
609
|
+
"prisma-cli-cause-code": getPrismaCliCauseCodeProperty(params.error),
|
|
610
|
+
"package-manager-error-code": params.stage === "install_dependencies" ? getPackageManagerErrorCodeProperty(params.error) : null
|
|
539
611
|
}).pipe(Effect.scoped, Effect.timeout(TELEMETRY_TIMEOUT_MS), Effect.catch(() => Effect.void));
|
|
540
612
|
});
|
|
541
613
|
const trackCreateCancelledEffect = Effect.fn("Telemetry.createCancelled")(function* (params) {
|
|
@@ -626,6 +698,20 @@ function getCreateTemplateDependencies(template, packageManager) {
|
|
|
626
698
|
return targets;
|
|
627
699
|
}
|
|
628
700
|
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region src/utils/errors.ts
|
|
703
|
+
function redactSecrets(message) {
|
|
704
|
+
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>");
|
|
705
|
+
}
|
|
706
|
+
function getErrorMessage(error) {
|
|
707
|
+
if (error instanceof PrismaCliCommandError) return redactSecrets(error.message);
|
|
708
|
+
if (error instanceof Error && "stderr" in error) {
|
|
709
|
+
const stderr = String(error.stderr ?? "").trim();
|
|
710
|
+
if (stderr) return redactSecrets(stderr);
|
|
711
|
+
}
|
|
712
|
+
return redactSecrets(error instanceof Error ? error.message : String(error));
|
|
713
|
+
}
|
|
714
|
+
|
|
629
715
|
//#endregion
|
|
630
716
|
//#region src/utils/package-manager.ts
|
|
631
717
|
const DENO_ALLOW_FRESH_DEPENDENCIES = "--minimum-dependency-age=0";
|
|
@@ -635,22 +721,108 @@ const packageManagerManifestValues = {
|
|
|
635
721
|
yarn: "yarn@4.13.0",
|
|
636
722
|
bun: "bun@1.4.1"
|
|
637
723
|
};
|
|
638
|
-
const
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
724
|
+
const packageManagerChecks = {
|
|
725
|
+
npm: {
|
|
726
|
+
name: "npm",
|
|
727
|
+
versionArgs: ["--version"],
|
|
728
|
+
install: "Install Node.js from https://nodejs.org to get npm",
|
|
729
|
+
minimum: {
|
|
730
|
+
version: [
|
|
731
|
+
11,
|
|
732
|
+
6,
|
|
733
|
+
0
|
|
734
|
+
],
|
|
735
|
+
guidance: "Older npm releases can crash while resolving Prisma dependencies. Run npm install --global npm@11, then retry create-prisma."
|
|
736
|
+
}
|
|
737
|
+
},
|
|
738
|
+
pnpm: {
|
|
739
|
+
name: "pnpm",
|
|
740
|
+
versionArgs: ["--version"],
|
|
741
|
+
install: "Install it from https://pnpm.io/installation"
|
|
742
|
+
},
|
|
743
|
+
yarn: {
|
|
744
|
+
name: "Yarn",
|
|
745
|
+
versionArgs: ["--version"],
|
|
746
|
+
install: "Install it with Corepack (https://yarnpkg.com/corepack)",
|
|
747
|
+
minimum: {
|
|
748
|
+
version: [
|
|
749
|
+
2,
|
|
750
|
+
0,
|
|
751
|
+
0
|
|
752
|
+
],
|
|
753
|
+
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.`
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
bun: {
|
|
757
|
+
name: "Bun",
|
|
758
|
+
versionArgs: ["--version"],
|
|
759
|
+
install: "Install it from https://bun.sh"
|
|
760
|
+
},
|
|
761
|
+
deno: {
|
|
762
|
+
name: "Deno",
|
|
763
|
+
versionArgs: ["-V"],
|
|
764
|
+
install: "Install it from https://docs.deno.com/runtime/getting_started/installation"
|
|
765
|
+
}
|
|
766
|
+
};
|
|
767
|
+
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.-]+)?$/;
|
|
768
|
+
function parsePackageManagerVersion(packageManager, version) {
|
|
769
|
+
const prefix = `${packageManager} `;
|
|
770
|
+
const match = PACKAGE_MANAGER_VERSION_PATTERN.exec(version.startsWith(prefix) ? version.slice(prefix.length) : version);
|
|
771
|
+
if (!match) return void 0;
|
|
772
|
+
const parts = [
|
|
773
|
+
Number(match[1]),
|
|
774
|
+
Number(match[2]),
|
|
775
|
+
Number(match[3])
|
|
776
|
+
];
|
|
777
|
+
return parts.every(Number.isSafeInteger) ? parts : void 0;
|
|
778
|
+
}
|
|
779
|
+
function isOlderVersion(version, minimum) {
|
|
780
|
+
for (const [index, part] of version.entries()) if (part !== minimum[index]) return part < minimum[index];
|
|
781
|
+
return false;
|
|
782
|
+
}
|
|
783
|
+
const probePackageManagerEffect = Effect.fn("PackageManager.probe")(function* (packageManager, cwd) {
|
|
784
|
+
const runner = yield* CommandRunner;
|
|
785
|
+
const { name, versionArgs, install, minimum } = packageManagerChecks[packageManager];
|
|
786
|
+
const output = (yield* runner.runChecked({
|
|
787
|
+
command: packageManager,
|
|
788
|
+
args: versionArgs,
|
|
789
|
+
cwd
|
|
790
|
+
}).pipe(Effect.mapError((cause) => cause.childProcessFailure === "command_not_found" ? new CreateFailure({
|
|
791
|
+
stage: "validate_input",
|
|
792
|
+
reason: "package_manager_not_found",
|
|
793
|
+
message: `${name} is not installed or is not on your PATH. ${install}, then retry create-prisma, or choose another package manager with --package-manager.`,
|
|
794
|
+
cause
|
|
795
|
+
}) : new CreateFailure({
|
|
796
|
+
stage: "validate_input",
|
|
797
|
+
reason: "package_manager_check_failed",
|
|
798
|
+
message: `Could not run ${[packageManager, ...versionArgs].join(" ")}: ${getErrorMessage(cause)}`,
|
|
799
|
+
cause
|
|
800
|
+
})))).stdout.trim();
|
|
801
|
+
const version = parsePackageManagerVersion(packageManager, output);
|
|
802
|
+
if (!version) return yield* new CreateFailure({
|
|
803
|
+
stage: "validate_input",
|
|
804
|
+
reason: "package_manager_check_failed",
|
|
805
|
+
message: `Could not determine the installed ${name} version: ${output}`
|
|
806
|
+
});
|
|
807
|
+
if (minimum && isOlderVersion(version, minimum.version)) return yield* new CreateFailure({
|
|
649
808
|
stage: "validate_input",
|
|
650
809
|
reason: "unsupported_package_manager_version",
|
|
651
|
-
message:
|
|
810
|
+
message: `${name} ${version.join(".")} is unsupported. Required: ${name} ${minimum.version.join(".")} or newer. ${minimum.guidance}`
|
|
652
811
|
});
|
|
653
812
|
});
|
|
813
|
+
const verifyPackageManagerEffect = Effect.fn("PackageManager.verify")(function* (packageManager) {
|
|
814
|
+
const fs = yield* FileSystem.FileSystem;
|
|
815
|
+
yield* probePackageManagerEffect(packageManager, yield* fs.makeTempDirectoryScoped({ prefix: "create-prisma-" }).pipe(Effect.tap((directory) => fs.writeFileString(path.join(directory, "package.json"), JSON.stringify({
|
|
816
|
+
name: "create-prisma-probe",
|
|
817
|
+
private: true,
|
|
818
|
+
packageManager: getPackageManagerManifestValue(packageManager)
|
|
819
|
+
}))), Effect.mapError((cause) => new CreateFailure({
|
|
820
|
+
stage: "validate_input",
|
|
821
|
+
reason: "package_manager_check_failed",
|
|
822
|
+
message: `Could not prepare a directory to check ${packageManagerChecks[packageManager].name}: ${getErrorMessage(cause)}`,
|
|
823
|
+
cause
|
|
824
|
+
}))));
|
|
825
|
+
}, Effect.scoped);
|
|
654
826
|
function parseUserAgent(userAgent) {
|
|
655
827
|
if (userAgent?.startsWith("pnpm")) return "pnpm";
|
|
656
828
|
if (userAgent?.startsWith("yarn")) return "yarn";
|
|
@@ -1127,20 +1299,6 @@ const installProjectDependenciesEffect = Effect.fn("Dependencies.install")(funct
|
|
|
1127
1299
|
});
|
|
1128
1300
|
});
|
|
1129
1301
|
|
|
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
1302
|
//#endregion
|
|
1145
1303
|
//#region src/workflow/failure.ts
|
|
1146
1304
|
const atCreateStage = (effect, stage, reason) => effect.pipe(Effect.mapError((error) => error instanceof CreateFailure || error instanceof CreateCancellationError ? error : new CreateFailure({
|
|
@@ -1256,7 +1414,7 @@ const ensureAuthentication = Effect.fn("Deployment.ensureAuthentication")(functi
|
|
|
1256
1414
|
cwd: options.projectDir,
|
|
1257
1415
|
env: process.env,
|
|
1258
1416
|
stdio: "inherit"
|
|
1259
|
-
});
|
|
1417
|
+
}).pipe(Effect.mapError((error) => error.childProcessFailure === "interrupted" || error.childProcessFailure === "cancelled" ? new CreateCancellationError({ stage: "authenticate" }) : error));
|
|
1260
1418
|
const authenticatedState = yield* whoami();
|
|
1261
1419
|
if (!authenticatedState.authenticated) return yield* new CreateFailure({
|
|
1262
1420
|
stage: "authenticate",
|
|
@@ -1321,10 +1479,7 @@ const selectDeploymentWorkspace = Effect.fn("Deployment.selectWorkspace")(functi
|
|
|
1321
1479
|
})),
|
|
1322
1480
|
output: options.output
|
|
1323
1481
|
}));
|
|
1324
|
-
if (isCancel(selectedWorkspaceId)) {
|
|
1325
|
-
yield* Effect.sync(() => cancel("Operation cancelled.", { output: options.output }));
|
|
1326
|
-
return yield* new CreateCancellationError({ stage: "select_workspace" });
|
|
1327
|
-
}
|
|
1482
|
+
if (isCancel(selectedWorkspaceId)) return yield* new CreateCancellationError({ stage: "select_workspace" });
|
|
1328
1483
|
yield* Effect.sync(() => options.afterPrompt?.());
|
|
1329
1484
|
if (selectedWorkspaceId === activeWorkspace.id) return activeWorkspace;
|
|
1330
1485
|
return yield* useWorkspace({
|
|
@@ -1354,6 +1509,49 @@ function parseComposerDeployResult(result) {
|
|
|
1354
1509
|
};
|
|
1355
1510
|
}
|
|
1356
1511
|
|
|
1512
|
+
//#endregion
|
|
1513
|
+
//#region src/tasks/composer/deploy-report.ts
|
|
1514
|
+
const ComposerRunReportSchema = Schema.fromJsonString(Schema.Struct({
|
|
1515
|
+
version: Schema.Literal(1),
|
|
1516
|
+
failure: Schema.NullOr(Schema.Struct({ code: Schema.String }))
|
|
1517
|
+
}));
|
|
1518
|
+
const decodeComposerRunReport = Schema.decodeUnknownOption(ComposerRunReportSchema);
|
|
1519
|
+
function parseComposerDeployFailureCode(report) {
|
|
1520
|
+
const code = Option.getOrUndefined(decodeComposerRunReport(report))?.failure?.code;
|
|
1521
|
+
return isStructuredErrorCode(code) ? code : void 0;
|
|
1522
|
+
}
|
|
1523
|
+
function withCauseCode(error, causeCode) {
|
|
1524
|
+
return new PrismaCliCommandError({
|
|
1525
|
+
message: error.message,
|
|
1526
|
+
...error.command === void 0 ? {} : { command: error.command },
|
|
1527
|
+
...error.code === void 0 ? {} : { code: error.code },
|
|
1528
|
+
causeCode,
|
|
1529
|
+
...error.stderr === void 0 ? {} : { stderr: error.stderr },
|
|
1530
|
+
...error.exitCode === void 0 ? {} : { exitCode: error.exitCode },
|
|
1531
|
+
childProcessFailure: error.childProcessFailure
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
const readComposerDeployFailureCode = Effect.fn("Deployment.readFailureCode")(function* (reportPath) {
|
|
1535
|
+
const report = yield* (yield* FileSystem.FileSystem).readFileString(reportPath).pipe(Effect.option);
|
|
1536
|
+
return Option.isSome(report) ? parseComposerDeployFailureCode(report.value) : void 0;
|
|
1537
|
+
});
|
|
1538
|
+
const runComposerDeployEffect = Effect.fn("Deployment.runComposerDeploy")(function* (options) {
|
|
1539
|
+
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));
|
|
1540
|
+
return yield* runPrismaJsonCommandEffect({
|
|
1541
|
+
packageManager: options.packageManager,
|
|
1542
|
+
projectDir: options.projectDir,
|
|
1543
|
+
args: [
|
|
1544
|
+
"deploy",
|
|
1545
|
+
"module.ts",
|
|
1546
|
+
...reportPath ? ["--report", reportPath] : []
|
|
1547
|
+
],
|
|
1548
|
+
...options.onStderrLine ? { onStderrLine: options.onStderrLine } : {}
|
|
1549
|
+
}).pipe(Effect.catchTag("PrismaCliCommandError", (error) => Effect.gen(function* () {
|
|
1550
|
+
const causeCode = reportPath ? yield* readComposerDeployFailureCode(reportPath) : void 0;
|
|
1551
|
+
return yield* Effect.fail(causeCode ? withCauseCode(error, causeCode) : error);
|
|
1552
|
+
})));
|
|
1553
|
+
}, Effect.scoped);
|
|
1554
|
+
|
|
1357
1555
|
//#endregion
|
|
1358
1556
|
//#region src/tasks/composer/projects.ts
|
|
1359
1557
|
const ProjectShowResultSchema = Schema.Struct({
|
|
@@ -1493,10 +1691,9 @@ const deployNewProjectWithComposerEffect = Effect.fn("Deployment.deploy")(functi
|
|
|
1493
1691
|
deploymentLog.message(`$ ${deployCommand}`);
|
|
1494
1692
|
}
|
|
1495
1693
|
});
|
|
1496
|
-
const deployment = parseComposerDeployResult(yield* atCreateStage(decodePrismaCommandResult(ComposerDeployCommandResultSchema, yield* atCreateStage(
|
|
1694
|
+
const deployment = parseComposerDeployResult(yield* atCreateStage(decodePrismaCommandResult(ComposerDeployCommandResultSchema, yield* atCreateStage(runComposerDeployEffect({
|
|
1497
1695
|
packageManager: options.packageManager,
|
|
1498
1696
|
projectDir: options.projectDir,
|
|
1499
|
-
args: ["deploy", "module.ts"],
|
|
1500
1697
|
onStderrLine: (line) => {
|
|
1501
1698
|
const redacted = redactSecrets(line);
|
|
1502
1699
|
if (options.verbose) output.write(`${redacted}\n`);
|
|
@@ -1528,12 +1725,17 @@ const deployNewProjectWithComposerEffect = Effect.fn("Deployment.deploy")(functi
|
|
|
1528
1725
|
};
|
|
1529
1726
|
}).pipe(Effect.tapCause((cause) => Effect.sync(() => {
|
|
1530
1727
|
const error = Cause.squash(cause);
|
|
1728
|
+
if (error instanceof CreateCancellationError) {
|
|
1729
|
+
clearProgress();
|
|
1730
|
+
cancel(error.message ?? "Operation cancelled.", { output });
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1531
1733
|
if (deploymentLog) {
|
|
1532
1734
|
deploymentLog.error("Deployment failed.");
|
|
1533
1735
|
deploymentLog = void 0;
|
|
1534
1736
|
} else progress?.error("Deployment failed.");
|
|
1535
1737
|
progressRunning = false;
|
|
1536
|
-
|
|
1738
|
+
log.error(`Deploy failed: ${getErrorMessage(error)}`, { output });
|
|
1537
1739
|
})), Effect.mapError((error) => error instanceof CreateFailure ? new CreateFailure({
|
|
1538
1740
|
stage: error.stage,
|
|
1539
1741
|
reason: error.reason,
|
|
@@ -2285,7 +2487,7 @@ const createProjectEffect = Effect.fn("Create.project")(function* (rawInput, inp
|
|
|
2285
2487
|
yield* Effect.sync(() => intro(getCreatePrismaIntro(), { output }));
|
|
2286
2488
|
const context = yield* atCreateStage(collectCreateContext(input), "collect_context", "unexpected_error");
|
|
2287
2489
|
yield* Ref.set(contextRef, Option.some(context));
|
|
2288
|
-
yield* atCreateStage(verifyPackageManagerEffect(context.prismaSetupContext.packageManager), "
|
|
2490
|
+
yield* atCreateStage(verifyPackageManagerEffect(context.prismaSetupContext.packageManager), "validate_input", "package_manager_check_failed");
|
|
2289
2491
|
return {
|
|
2290
2492
|
input,
|
|
2291
2493
|
context,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-prisma",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
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",
|