create-prisma 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +1 -1
- package/dist/{create-DPrHKEg5.mjs → create-CJa0JTWf.mjs} +136 -14
- package/dist/index.mjs +2 -2
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { cancel, confirm, intro, isCancel, log, note, outro, select, spinner, text } from "@clack/prompts";
|
|
3
|
+
import { cancel, confirm, intro, isCancel, log, note, outro, select, spinner, taskLog, text } from "@clack/prompts";
|
|
4
4
|
import fs from "fs-extra";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
@@ -10,6 +10,7 @@ import Handlebars from "handlebars";
|
|
|
10
10
|
import { existsSync } from "node:fs";
|
|
11
11
|
import { fileURLToPath } from "node:url";
|
|
12
12
|
import { execa } from "execa";
|
|
13
|
+
import { createInterface } from "node:readline";
|
|
13
14
|
import { styleText } from "node:util";
|
|
14
15
|
|
|
15
16
|
//#region src/telemetry/client.ts
|
|
@@ -49,7 +50,7 @@ async function getAnonymousId() {
|
|
|
49
50
|
}
|
|
50
51
|
function getCommonProperties() {
|
|
51
52
|
return {
|
|
52
|
-
"cli-version": "0.9.
|
|
53
|
+
"cli-version": "0.9.3",
|
|
53
54
|
"node-version": process.version,
|
|
54
55
|
platform: process.platform,
|
|
55
56
|
arch: process.arch
|
|
@@ -668,7 +669,7 @@ async function installProjectDependencies(packageManager, projectDir = process.c
|
|
|
668
669
|
//#endregion
|
|
669
670
|
//#region src/tasks/deploy-with-composer.ts
|
|
670
671
|
function redactSecrets(message) {
|
|
671
|
-
return message.replace(/\b((?:prisma\+)?postgres(?:ql)
|
|
672
|
+
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>");
|
|
672
673
|
}
|
|
673
674
|
function getErrorMessage(error) {
|
|
674
675
|
if (error instanceof Error) return redactSecrets(error.message);
|
|
@@ -703,12 +704,16 @@ async function runPrismaJsonCommand(options) {
|
|
|
703
704
|
"--json",
|
|
704
705
|
"--no-interactive"
|
|
705
706
|
]);
|
|
706
|
-
const
|
|
707
|
+
const subprocess = execa(invocation.command, invocation.args, {
|
|
707
708
|
cwd: options.projectDir,
|
|
708
709
|
env: process.env,
|
|
709
710
|
reject: false
|
|
710
711
|
});
|
|
711
|
-
|
|
712
|
+
const stderrLines = options.onStderrLine && subprocess.stderr ? (async () => {
|
|
713
|
+
const lines = createInterface({ input: subprocess.stderr });
|
|
714
|
+
for await (const line of lines) if (line.trim()) options.onStderrLine?.(line);
|
|
715
|
+
})() : Promise.resolve();
|
|
716
|
+
const [result] = await Promise.all([subprocess, stderrLines]);
|
|
712
717
|
let envelope;
|
|
713
718
|
try {
|
|
714
719
|
envelope = parsePrismaCliEnvelope(result.stdout);
|
|
@@ -722,6 +727,19 @@ async function runPrismaJsonCommand(options) {
|
|
|
722
727
|
}
|
|
723
728
|
return envelope.result;
|
|
724
729
|
}
|
|
730
|
+
function findProjectNameCollisions(projects, appName) {
|
|
731
|
+
return projects.filter((project) => project.name === appName);
|
|
732
|
+
}
|
|
733
|
+
async function ensureProjectNameAvailable(options) {
|
|
734
|
+
const collisions = findProjectNameCollisions((await runPrismaJsonCommand({
|
|
735
|
+
packageManager: options.packageManager,
|
|
736
|
+
projectDir: options.projectDir,
|
|
737
|
+
args: ["project", "list"]
|
|
738
|
+
})).items, options.appName);
|
|
739
|
+
if (collisions.length === 0) return;
|
|
740
|
+
const projectIds = collisions.map((project) => project.id).join(", ");
|
|
741
|
+
throw new Error(`A Prisma project named "${options.appName}" already exists in workspace ${workspaceLabel(options.workspace)} (${options.workspace.id}). Choose a different project name or delete the existing project (${projectIds}) in Prisma Console, then retry.`);
|
|
742
|
+
}
|
|
725
743
|
async function ensureAuthentication(packageManager, projectDir, beforeInteractiveLogin) {
|
|
726
744
|
const whoami = () => runPrismaJsonCommand({
|
|
727
745
|
packageManager,
|
|
@@ -843,8 +861,13 @@ async function getProjectDetails(options) {
|
|
|
843
861
|
return;
|
|
844
862
|
}
|
|
845
863
|
}
|
|
846
|
-
|
|
864
|
+
/**
|
|
865
|
+
* Performs the optional one-shot deployment at the end of a create-prisma scaffold.
|
|
866
|
+
* Generated projects use their own `deploy` script for every subsequent deployment.
|
|
867
|
+
*/
|
|
868
|
+
async function deployNewProjectWithComposer(options) {
|
|
847
869
|
const progress = options.verbose ? void 0 : spinner();
|
|
870
|
+
let deploymentLog;
|
|
848
871
|
let progressRunning = false;
|
|
849
872
|
const showProgress = (message) => {
|
|
850
873
|
if (!progress) return;
|
|
@@ -875,6 +898,14 @@ async function deployWithComposer(options) {
|
|
|
875
898
|
...options.workspace ? { workspace: options.workspace } : {}
|
|
876
899
|
});
|
|
877
900
|
if (!selectedWorkspace) return;
|
|
901
|
+
showProgress("Checking Prisma project name...");
|
|
902
|
+
if (options.verbose) log.step("Checking Prisma project name.");
|
|
903
|
+
await ensureProjectNameAvailable({
|
|
904
|
+
appName: options.appName,
|
|
905
|
+
packageManager: options.packageManager,
|
|
906
|
+
projectDir: options.projectDir,
|
|
907
|
+
workspace: selectedWorkspace
|
|
908
|
+
});
|
|
878
909
|
showProgress("Building for deployment...");
|
|
879
910
|
if (options.verbose) log.step("Building for deployment.");
|
|
880
911
|
const build = getRunScriptArgs(options.packageManager, "build");
|
|
@@ -883,22 +914,40 @@ async function deployWithComposer(options) {
|
|
|
883
914
|
env: process.env,
|
|
884
915
|
stdio: options.verbose ? "inherit" : "pipe"
|
|
885
916
|
});
|
|
886
|
-
|
|
887
|
-
|
|
917
|
+
clearProgress();
|
|
918
|
+
const deployCommand = getPackageExecutionCommand(options.packageManager, [
|
|
919
|
+
PRISMA_PLATFORM_CLI_PACKAGE,
|
|
920
|
+
"deploy",
|
|
921
|
+
"module.ts"
|
|
922
|
+
]);
|
|
923
|
+
if (options.verbose) log.step(`Deploying to Prisma with ${deployCommand}.`);
|
|
924
|
+
else {
|
|
925
|
+
deploymentLog = taskLog({
|
|
926
|
+
title: "Deploying to Prisma...",
|
|
927
|
+
limit: 10
|
|
928
|
+
});
|
|
929
|
+
deploymentLog.message(`$ ${deployCommand}`);
|
|
930
|
+
}
|
|
888
931
|
const deployment = parseComposerDeployResult(await runPrismaJsonCommand({
|
|
889
932
|
packageManager: options.packageManager,
|
|
890
933
|
projectDir: options.projectDir,
|
|
891
934
|
args: ["deploy", "module.ts"],
|
|
892
|
-
|
|
935
|
+
onStderrLine: (line) => {
|
|
936
|
+
const redactedLine = redactSecrets(line);
|
|
937
|
+
if (options.verbose) process.stderr.write(`${redactedLine}\n`);
|
|
938
|
+
else deploymentLog?.message(redactedLine);
|
|
939
|
+
}
|
|
893
940
|
}));
|
|
894
941
|
const appName = deployment?.appName ?? options.appName;
|
|
895
|
-
|
|
942
|
+
if (options.verbose) log.step("Loading deployment details.");
|
|
943
|
+
else deploymentLog?.message("Loading deployment details...");
|
|
896
944
|
const details = await getProjectDetails({
|
|
897
945
|
packageManager: options.packageManager,
|
|
898
946
|
projectDir: options.projectDir,
|
|
899
947
|
appName
|
|
900
948
|
});
|
|
901
|
-
|
|
949
|
+
deploymentLog?.success("Deployed to Prisma.");
|
|
950
|
+
deploymentLog = void 0;
|
|
902
951
|
progressRunning = false;
|
|
903
952
|
if (options.verbose) log.success("Deployed to Prisma.");
|
|
904
953
|
const workspace = details?.workspace ?? selectedWorkspace;
|
|
@@ -909,13 +958,73 @@ async function deployWithComposer(options) {
|
|
|
909
958
|
project: details?.project ?? { name: appName }
|
|
910
959
|
};
|
|
911
960
|
} catch (error) {
|
|
912
|
-
|
|
961
|
+
if (deploymentLog) {
|
|
962
|
+
deploymentLog.error("Deployment failed.");
|
|
963
|
+
deploymentLog = void 0;
|
|
964
|
+
} else progress?.error("Deployment failed.");
|
|
913
965
|
progressRunning = false;
|
|
914
966
|
log.error(`Deploy failed: ${getErrorMessage(error)}`);
|
|
915
967
|
return;
|
|
916
968
|
}
|
|
917
969
|
}
|
|
918
970
|
|
|
971
|
+
//#endregion
|
|
972
|
+
//#region src/tasks/initialize-git.ts
|
|
973
|
+
function errorMessage(error) {
|
|
974
|
+
if (error instanceof Error && "stderr" in error) {
|
|
975
|
+
const stderr = String(error.stderr ?? "").trim();
|
|
976
|
+
if (stderr) return stderr;
|
|
977
|
+
}
|
|
978
|
+
return error instanceof Error ? error.message : String(error);
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Initializes a standalone scaffold as a Git repository and records its generated files.
|
|
982
|
+
* Projects created inside an existing repository remain part of that repository.
|
|
983
|
+
*/
|
|
984
|
+
async function initializeGitRepository(projectDir, env = process.env) {
|
|
985
|
+
try {
|
|
986
|
+
const existing = await execa("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
987
|
+
cwd: projectDir,
|
|
988
|
+
env,
|
|
989
|
+
reject: false
|
|
990
|
+
});
|
|
991
|
+
if (existing.exitCode === 0 && existing.stdout.trim() === "true") return { status: "already-in-repository" };
|
|
992
|
+
} catch (error) {
|
|
993
|
+
return {
|
|
994
|
+
status: "skipped",
|
|
995
|
+
reason: errorMessage(error)
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
let initialized = false;
|
|
999
|
+
try {
|
|
1000
|
+
await execa("git", ["init"], {
|
|
1001
|
+
cwd: projectDir,
|
|
1002
|
+
env
|
|
1003
|
+
});
|
|
1004
|
+
initialized = true;
|
|
1005
|
+
await execa("git", ["add", "--all"], {
|
|
1006
|
+
cwd: projectDir,
|
|
1007
|
+
env
|
|
1008
|
+
});
|
|
1009
|
+
await execa("git", [
|
|
1010
|
+
"commit",
|
|
1011
|
+
"--no-verify",
|
|
1012
|
+
"-m",
|
|
1013
|
+
"Initial commit from create-prisma"
|
|
1014
|
+
], {
|
|
1015
|
+
cwd: projectDir,
|
|
1016
|
+
env
|
|
1017
|
+
});
|
|
1018
|
+
return { status: "initialized" };
|
|
1019
|
+
} catch (error) {
|
|
1020
|
+
if (initialized) await fs.remove(path.join(projectDir, ".git"));
|
|
1021
|
+
return {
|
|
1022
|
+
status: "skipped",
|
|
1023
|
+
reason: errorMessage(error)
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
919
1028
|
//#endregion
|
|
920
1029
|
//#region src/tasks/setup-prisma.ts
|
|
921
1030
|
const DEFAULT_DATABASE_PROVIDER = "postgres";
|
|
@@ -1166,7 +1275,9 @@ async function executePrismaSetupContext(context, options = {}) {
|
|
|
1166
1275
|
const projectName = options.projectName ?? path.basename(projectDir);
|
|
1167
1276
|
const template = options.template ?? "minimal";
|
|
1168
1277
|
const progress = context.verbose ? void 0 : options.progressSpinner ?? spinner();
|
|
1169
|
-
|
|
1278
|
+
const ownsProgress = progress !== void 0 && !options.progressSpinner;
|
|
1279
|
+
let gitInitialization;
|
|
1280
|
+
if (ownsProgress) progress.start("Creating Prisma 8 project...");
|
|
1170
1281
|
try {
|
|
1171
1282
|
progress?.message("Preparing Prisma 8 project files...");
|
|
1172
1283
|
await runPrismaInit(context, projectDir);
|
|
@@ -1181,13 +1292,23 @@ async function executePrismaSetupContext(context, options = {}) {
|
|
|
1181
1292
|
await writePrismaDependencies(context.databaseProvider, context.packageManager, context.authoring, projectDir);
|
|
1182
1293
|
await ensureComposerTypeScriptOptions(projectDir);
|
|
1183
1294
|
if (context.databaseProvider === "mongo") await ensureMongoEnvironment(projectDir);
|
|
1295
|
+
if (context.packageManager !== "deno") {
|
|
1296
|
+
await ensureGitignoreEntry(projectDir, "/.alchemy");
|
|
1297
|
+
await ensureGitignoreEntry(projectDir, "/.prisma-composer");
|
|
1298
|
+
}
|
|
1184
1299
|
progress?.message(`Installing dependencies with ${getInstallCommand(context.packageManager)}...`);
|
|
1185
1300
|
await installProjectDependencies(context.packageManager, projectDir, { verbose: context.verbose });
|
|
1186
1301
|
progress?.message("Installing Prisma agent skills...");
|
|
1187
1302
|
await initializeAgentSkills(context, projectDir);
|
|
1188
1303
|
progress?.message("Generating Prisma 8 contract artifacts...");
|
|
1189
1304
|
await emitContract(context, projectDir);
|
|
1305
|
+
if (options.initializeGit) {
|
|
1306
|
+
progress?.message("Initializing Git repository...");
|
|
1307
|
+
gitInitialization = await initializeGitRepository(projectDir);
|
|
1308
|
+
}
|
|
1190
1309
|
progress?.stop("Prisma 8 project ready.");
|
|
1310
|
+
if (gitInitialization?.status === "initialized" && context.verbose) log.success("Initialized Git repository with an initial commit.");
|
|
1311
|
+
else if (gitInitialization?.status === "skipped") log.warn(`Could not initialize Git repository: ${gitInitialization.reason}`);
|
|
1191
1312
|
} catch (error) {
|
|
1192
1313
|
progress?.error("Could not create Prisma 8 project.");
|
|
1193
1314
|
cancel(getCommandErrorMessage(error));
|
|
@@ -1195,7 +1316,7 @@ async function executePrismaSetupContext(context, options = {}) {
|
|
|
1195
1316
|
}
|
|
1196
1317
|
let deployment;
|
|
1197
1318
|
if (context.shouldDeploy) {
|
|
1198
|
-
deployment = await
|
|
1319
|
+
deployment = await deployNewProjectWithComposer({
|
|
1199
1320
|
appName: projectName,
|
|
1200
1321
|
packageManager: context.packageManager,
|
|
1201
1322
|
projectDir,
|
|
@@ -1490,6 +1611,7 @@ async function executeCreateContext(context) {
|
|
|
1490
1611
|
template: context.template,
|
|
1491
1612
|
createdProjectPath: context.targetDirectory,
|
|
1492
1613
|
includeDevNextStep: true,
|
|
1614
|
+
initializeGit: !context.targetPathState.exists || context.targetPathState.isEmptyDirectory,
|
|
1493
1615
|
progressSpinner: createSpinner
|
|
1494
1616
|
})) return {
|
|
1495
1617
|
ok: false,
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as DatabaseProviderSchema, i as CreateTemplateSchema, n as AuthoringStyleSchema, o as PackageManagerSchema, r as CreateCommandInputSchema, t as runCreateCommand } from "./create-
|
|
2
|
+
import { a as DatabaseProviderSchema, i as CreateTemplateSchema, n as AuthoringStyleSchema, o as PackageManagerSchema, r as CreateCommandInputSchema, t as runCreateCommand } from "./create-CJa0JTWf.mjs";
|
|
3
3
|
import { os } from "@orpc/server";
|
|
4
4
|
import { createCli } from "trpc-cli";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
|
|
7
7
|
//#region src/index.ts
|
|
8
|
-
const CLI_VERSION = "0.9.
|
|
8
|
+
const CLI_VERSION = "0.9.3";
|
|
9
9
|
const CreateCliInputSchema = z.tuple([z.string().trim().min(1, "Please enter a valid project name").optional().describe("Project name / directory"), CreateCommandInputSchema]);
|
|
10
10
|
function normalizeCreateCliInput(input) {
|
|
11
11
|
const [projectName, options] = input;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-prisma",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
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/install.test.ts ./tests/node-version.test.ts ./tests/setup-prisma.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/node-version.test.ts ./tests/setup-prisma.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",
|