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 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 npm
25
- version before writing project files and never upgrades your package manager automatically.
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-CPdx9Prn.mjs";
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-CPdx9Prn.mjs";
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.1";
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: getChildProcessFailure(result)
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.1",
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 verifyPackageManagerEffect = Effect.fn("PackageManager.verify")(function* (packageManager) {
639
- if (packageManager !== "npm") return;
640
- const version = (yield* (yield* CommandRunner).runChecked({
641
- command: "npm",
642
- args: ["--version"],
643
- cwd: process.cwd()
644
- })).stdout.trim();
645
- const parts = version.split(".").map(Number);
646
- if (!/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(version) || parts.some((part) => !Number.isInteger(part))) return yield* Effect.fail(/* @__PURE__ */ new Error(`Could not determine the installed npm version: ${version}`));
647
- const [major, minor] = parts;
648
- if (major < 11 || major === 11 && minor < 6) return yield* new CreateFailure({
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: `npm ${version} is unsupported. Required: npm 11.6.0 or newer. Older npm releases can crash while resolving Prisma dependencies. Run npm install --global npm@11, then retry create-prisma.`
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(runPrismaJsonCommandEffect({
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
- if (!(error instanceof CreateCancellationError)) log.error(`Deploy failed: ${getErrorMessage(error)}`, { output });
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), "install_dependencies", "dependency_install_failed");
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.1",
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",