Skip to content

Commit d6f7243

Browse files
feat: Add Deno and Yarn package manager support (#14)
1 parent 079cb28 commit d6f7243

40 files changed

Lines changed: 305 additions & 215 deletions

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,18 @@ Run directly with Bun:
2020
bunx create-prisma@latest
2121
```
2222

23+
Run directly with Yarn:
24+
25+
```bash
26+
yarn dlx create-prisma@latest
27+
```
28+
29+
Run directly with Deno:
30+
31+
```bash
32+
deno run -A npm:create-prisma@latest
33+
```
34+
2335
Create a new project (default command):
2436

2537
```bash
@@ -122,7 +134,7 @@ The CLI updates `package.json` with Prisma dependencies, optionally runs depende
122134

123135
`create` prompts for database choice, package manager, and whether to install dependencies now.
124136
Supported providers in this flow: `postgresql`, `mysql`, `sqlite`, `sqlserver`, `cockroachdb`.
125-
Supported package managers: `bun`, `pnpm`, `npm`.
137+
Supported package managers: `bun`, `deno`, `npm`, `pnpm`, `yarn`.
126138
Package manager prompt auto-detects from `package.json`/lockfiles/user agent and uses that as the initial selection.
127139
`--yes` accepts defaults (`postgresql`, detected package manager, Prisma Postgres enabled for PostgreSQL, install enabled) and skips prompts.
128140
`--no-generate` skips automatic `prisma generate`.

src/commands/create.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ async function promptForCreateTemplate(): Promise<CreateTemplate | undefined> {
9191
{
9292
value: "hono",
9393
label: "Hono",
94-
hint: "Bun + TypeScript API starter",
94+
hint: "TypeScript API starter",
9595
},
9696
{
9797
value: "next",

src/constants/dependencies.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export const dependencyVersionMap = {
55
"@prisma/adapter-better-sqlite3": "^7.4.0",
66
"@prisma/adapter-mssql": "^7.4.0",
77
dotenv: "^17.2.3",
8+
"node-gyp": "^11.5.0",
89
prisma: "^7.4.0",
910
} as const;
1011

src/tasks/install.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { execa } from "execa";
22
import fs from "fs-extra";
33
import path from "node:path";
44

5+
import { getDenoPrismaSpecifier } from "../utils/package-manager";
56
import {
67
dependencyVersionMap,
78
type AvailableDependency,
@@ -14,12 +15,25 @@ import type {
1415
} from "../types";
1516
import { getInstallArgs } from "../utils/package-manager";
1617

17-
const prismaScriptMap = {
18-
"db:generate": "prisma generate",
19-
"db:push": "prisma db push",
20-
"db:migrate": "prisma migrate dev",
21-
"db:seed": "prisma db seed",
22-
} as const;
18+
function getPrismaScriptMap(packageManager: PackageManager) {
19+
if (packageManager === "deno") {
20+
const prismaSpecifier = getDenoPrismaSpecifier();
21+
22+
return {
23+
"db:generate": `deno run -A ${prismaSpecifier} generate`,
24+
"db:push": `deno run -A ${prismaSpecifier} db push`,
25+
"db:migrate": `deno run -A ${prismaSpecifier} migrate dev`,
26+
"db:seed": `deno run -A ${prismaSpecifier} db seed`,
27+
} as const;
28+
}
29+
30+
return {
31+
"db:generate": "prisma generate",
32+
"db:push": "prisma db push",
33+
"db:migrate": "prisma migrate dev",
34+
"db:seed": "prisma db seed",
35+
} as const;
36+
}
2337

2438
function getVersion(packageName: string): string | undefined {
2539
return dependencyVersionMap[packageName as AvailableDependency];
@@ -137,13 +151,21 @@ export async function addPackageDependency(opts: {
137151

138152
export async function writePrismaDependencies(
139153
provider: DatabaseProvider,
154+
packageManager: PackageManager,
140155
projectDir = process.cwd()
141156
): Promise<DependencyWriteResult> {
142157
const dependencies: string[] = ["@prisma/client", "dotenv"];
143158
const devDependencies: string[] = ["prisma"];
144159
const { adapterPackage } = getDbPackages(provider);
145160
dependencies.push(adapterPackage);
146161

162+
// Deno needs node-gyp available when sqlite pulls in better-sqlite3.
163+
if (provider === "sqlite" && packageManager === "deno") {
164+
devDependencies.push("node-gyp");
165+
}
166+
167+
const prismaScriptMap = getPrismaScriptMap(packageManager);
168+
147169
const scriptWriteResult = await addPackageDependency({
148170
dependencies,
149171
devDependencies,

src/tasks/setup-prisma.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ function getPackageManagerHint(
108108
return "Fast runtime + package manager";
109109
}
110110

111+
if (option === "deno") {
112+
return "Runtime + package manager";
113+
}
114+
111115
return undefined;
112116
}
113117

@@ -128,11 +132,21 @@ async function promptForPackageManager(
128132
label: "pnpm",
129133
hint: getPackageManagerHint("pnpm", detectedPackageManager),
130134
},
135+
{
136+
value: "yarn",
137+
label: "yarn",
138+
hint: getPackageManagerHint("yarn", detectedPackageManager),
139+
},
131140
{
132141
value: "bun",
133142
label: "bun",
134143
hint: getPackageManagerHint("bun", detectedPackageManager),
135144
},
145+
{
146+
value: "deno",
147+
label: "deno",
148+
hint: getPackageManagerHint("deno", detectedPackageManager),
149+
},
136150
],
137151
});
138152

@@ -530,6 +544,7 @@ async function writeDependenciesForContext(
530544
try {
531545
return await writePrismaDependencies(
532546
context.databaseProvider,
547+
context.packageManager,
533548
prismaProjectDir
534549
);
535550
} catch (error) {

src/templates/shared.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,29 @@ import { existsSync } from "node:fs";
44
import path from "node:path";
55
import { fileURLToPath } from "node:url";
66

7+
import type { PackageManager } from "../types";
8+
import {
9+
getInstallCommand,
10+
getPackageManagerManifestValue,
11+
getRunScriptCommand,
12+
} from "../utils/package-manager";
13+
714
Handlebars.registerHelper("eq", (left: unknown, right: unknown) => left === right);
15+
Handlebars.registerHelper(
16+
"installCommand",
17+
(packageManager: PackageManager | undefined) =>
18+
packageManager ? getInstallCommand(packageManager) : ""
19+
);
20+
Handlebars.registerHelper(
21+
"runScriptCommand",
22+
(packageManager: PackageManager | undefined, scriptName: string) =>
23+
packageManager ? getRunScriptCommand(packageManager, scriptName) : ""
24+
);
25+
Handlebars.registerHelper(
26+
"packageManagerManifestValue",
27+
(packageManager: PackageManager | undefined) =>
28+
getPackageManagerManifestValue(packageManager) ?? ""
29+
);
830

931
export function findPackageRoot(startDir: string): string {
1032
let currentDir = startDir;
@@ -80,6 +102,13 @@ export async function renderTemplateFile<TContext>(opts: {
80102
})(context)
81103
: templateContent;
82104

105+
if (
106+
templateFilePath.endsWith(".hbs") &&
107+
outputContent.trim().length === 0
108+
) {
109+
return;
110+
}
111+
83112
await fs.outputFile(outputPath, ensureTrailingNewline(outputContent), "utf8");
84113
}
85114

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const databaseProviders = [
88
"cockroachdb",
99
] as const;
1010

11-
export const packageManagers = ["npm", "pnpm", "bun"] as const;
11+
export const packageManagers = ["npm", "pnpm", "yarn", "bun", "deno"] as const;
1212
export const schemaPresets = ["empty", "basic"] as const;
1313
export const createTemplates = ["hono", "next", "svelte", "astro", "nuxt", "turborepo"] as const;
1414
export const createAddons = ["skills", "mcp", "extension"] as const;

0 commit comments

Comments
 (0)