From 7a73c31a12dedadd91312132fed54bd6e6ef5708 Mon Sep 17 00:00:00 2001 From: Jason Connolly Date: Mon, 24 Mar 2025 16:52:42 +0000 Subject: [PATCH 1/2] Updated packages in template and added correct configs for wrangler --- cli/template/base-assets/base-package.json | 42 +++++++++++----------- cli/template/base/wrangler.json | 19 ++++++++-- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/cli/template/base-assets/base-package.json b/cli/template/base-assets/base-package.json index 40722f9..4dfac26 100644 --- a/cli/template/base-assets/base-package.json +++ b/cli/template/base-assets/base-package.json @@ -9,31 +9,31 @@ "lint": "next lint" }, "dependencies": { - "@tailwindcss/postcss": "^4.0.0", - "@tanstack/react-query": "^5.51.23", + "@tailwindcss/postcss": "^4.0.15", + "@tanstack/react-query": "^5.69.0", "clsx": "^2.1.1", - "drizzle-orm": "^0.39.0", - "hono": "^4.7.0", - "jstack": "^1.0.6", - "next": "^15.1.6", + "drizzle-orm": "^0.41.0", + "hono": "^4.7.5", + "jstack": "^1.0.8", + "next": "^15.2.3", "react": "^19.0.0", "react-dom": "^19.0.0", - "superjson": "^2.2.1", - "tailwind-merge": "^2.5.2", - "zod": "^3.24.1" + "superjson": "^2.2.2", + "tailwind-merge": "^3.0.2", + "zod": "^3.24.2" }, "devDependencies": { - "dotenv": "^16.4.5", - "@cloudflare/workers-types": "^4.20250214.0", - "@types/node": "^22.10.6", - "@types/react": "^19.0.7", - "@types/react-dom": "^19.0.3", - "drizzle-kit": "^0.30.1", - "eslint": "^9.18.0", - "eslint-config-next": "^15.1.4", - "postcss": "^8", - "tailwindcss": "^4.0.0", - "typescript": "^5", - "wrangler": "^3.109.1" + "dotenv": "^16.4.7", + "@cloudflare/workers-types": "^4.20250321.0", + "@types/node": "^22.13.12", + "@types/react": "^19.0.12", + "@types/react-dom": "^19.0.4", + "drizzle-kit": "^0.30.5", + "eslint": "^9.23.0", + "eslint-config-next": "^15.2.3", + "postcss": "^8.5.3", + "tailwindcss": "^4.0.15", + "typescript": "^5.8.2", + "wrangler": "^4.4.0" } } diff --git a/cli/template/base/wrangler.json b/cli/template/base/wrangler.json index de84a51..d931670 100644 --- a/cli/template/base/wrangler.json +++ b/cli/template/base/wrangler.json @@ -2,9 +2,24 @@ "$schema": "node_modules/wrangler/config-schema.json", "name": "jstack-app", "main": "src/server/index.ts", - "compatibility_date": "2025-02-14", + "compatibility_date": "2025-03-22", + "compatibility_flags": [ + "nodejs_compat", + "nodejs_als", + "no_handle_cross_request_promise_resolution" + ], + // Add these in if you want to use a custom domain + // "routes": [ + // { + // "pattern": "sub.domain.com", + // "custom_domain": true + // } + // ], + // "workers_dev": false, + // "preview_urls": false, "observability": { - "enabled": true + "enabled": true, + "head_sampling_rate": 1 }, "placement": { "mode": "smart" From 104416fc4dc6fbe0bad656d1c3550301262e599b Mon Sep 17 00:00:00 2001 From: Jason Connolly Date: Wed, 29 Oct 2025 13:12:20 +0000 Subject: [PATCH 2/2] feat(cli): add Prisma ORM support and update scaffolding deps/templates --- cli/bun.lockb | Bin 91206 -> 93546 bytes cli/package.json | 1 + cli/src/cli/index.ts | 9 +-- cli/src/helpers/install-base-template.ts | 10 +++ cli/src/installers/dep-version-map.ts | 27 ++++---- cli/src/installers/index.ts | 7 ++- cli/src/installers/prisma.ts | 64 +++++++++++++++++++ cli/template/base-assets/base-package.json | 68 ++++++++------------- package.json | 7 ++- 9 files changed, 132 insertions(+), 61 deletions(-) create mode 100644 cli/src/installers/prisma.ts diff --git a/cli/bun.lockb b/cli/bun.lockb index b48249e421c0a35166f75b13b1787823e6f23e1e..68b1839e363c5ecd5d1266f5cec0bc6256118e45 100755 GIT binary patch delta 12486 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 { return undefined } - const orm = await select<"none" | "drizzle">({ + const orm = await select<"none" | "drizzle" | "prisma">({ message: "Which database ORM would you like to use?", options: [ { value: "none", label: "None" }, { value: "drizzle", label: "Drizzle ORM" }, + { value: "prisma", label: "Prisma ORM" }, ], }) @@ -57,7 +58,6 @@ export async function runCli(): Promise { let provider = undefined if (orm === "drizzle") { dialect = "postgres" as const // Only offering postgres - provider = await select({ message: "Which Postgres provider would you like to use?", options: [ @@ -66,11 +66,12 @@ export async function runCli(): Promise { { value: "vercel-postgres", label: "Vercel Postgres" }, ], }) - if (isCancel(provider)) { outro("Setup cancelled.") return undefined } + } else if (orm === "prisma") { + // Prisma CLI does not need a separate provider installer } let noInstall = noInstallFlag diff --git a/cli/src/helpers/install-base-template.ts b/cli/src/helpers/install-base-template.ts index 93bf415..bbe1d76 100644 --- a/cli/src/helpers/install-base-template.ts +++ b/cli/src/helpers/install-base-template.ts @@ -3,6 +3,7 @@ import * as p from "@clack/prompts" import chalk from "chalk" import fs from "fs-extra" import ora from "ora" +import { execa } from "execa" import { PKG_ROOT } from "@/constants.js" import { type InstallerOptions } from "@/installers/index.js" @@ -103,4 +104,13 @@ export const installBaseTemplate = async ({ spinner.succeed( `${scaffoldedName} ${chalk.green("scaffolded successfully!")}\n`, ) + // Initialize a git repository and make initial commit + try { + await execa("git", ["init"], { cwd: projectDir }) + await execa("git", ["add", "."], { cwd: projectDir }) + await execa("git", ["commit", "-m", "Initial commit"], { cwd: projectDir }) + logger.info("Initialized git repository") + } catch { + // ignore if git is not available + } } diff --git a/cli/src/installers/dep-version-map.ts b/cli/src/installers/dep-version-map.ts index e565cba..70b430a 100644 --- a/cli/src/installers/dep-version-map.ts +++ b/cli/src/installers/dep-version-map.ts @@ -4,22 +4,27 @@ */ export const dependencyVersionMap = { // neon - "@neondatabase/serverless": "^0.10.4", + "@neondatabase/serverless": "*", // vercel postgres - "@vercel/postgres": "^0.10.0", + "@vercel/postgres": "*", // Drizzle - "drizzle-kit": "^0.30.1", - "drizzle-orm": "^0.39.0", - "eslint-plugin-drizzle": "^0.2.3", - "@planetscale/database": "^1.19.0", - postgres: "^3.4.5", + "drizzle-kit": "*", + "drizzle-orm": "*", + "eslint-plugin-drizzle": "*", + "@planetscale/database": "*", + postgres: "*", // TailwindCSS - tailwindcss: "^4.0.0", - postcss: "^8.5.1", - prettier: "^3.3.2", - "prettier-plugin-tailwindcss": "^0.6.11", + tailwindcss: "*", + postcss: "*", + prettier: "*", + "prettier-plugin-tailwindcss": "*", + + // Prisma + prisma: "*", + "@prisma/client": "*", + "@prisma/extension-accelerate": "*", } as const export type AvailableDependencies = keyof typeof dependencyVersionMap diff --git a/cli/src/installers/index.ts b/cli/src/installers/index.ts index 1d3091a..0d78184 100644 --- a/cli/src/installers/index.ts +++ b/cli/src/installers/index.ts @@ -1,5 +1,6 @@ import { PackageManager } from "@/utils/get-user-pkg-manager.js" import { drizzleInstaller } from "./drizzle.js" +import { prismaInstaller } from "./prisma.js" import { neonInstaller } from "./neon.js" import { noOrmInstaller } from "./no-orm.js" import { postgresInstaller } from "./postgres.js" @@ -8,7 +9,7 @@ import { planetscaleInstaller } from "./planetscale.js" // Turning this into a const allows the list to be iterated over for programmatically creating prompt options // Should increase extensibility in the future -export const orms = ["none", "drizzle"] as const +export const orms = ["none", "drizzle", "prisma"] as const export type Orm = (typeof orms)[number] export const dialects = ["postgres"] as const @@ -57,6 +58,10 @@ export const buildInstallerMap = ( inUse: selectedOrm === "drizzle", installer: drizzleInstaller, }, + prisma: { + inUse: selectedOrm === "prisma", + installer: prismaInstaller, + }, }, provider: { postgres: { diff --git a/cli/src/installers/prisma.ts b/cli/src/installers/prisma.ts new file mode 100644 index 0000000..f0731cb --- /dev/null +++ b/cli/src/installers/prisma.ts @@ -0,0 +1,64 @@ +import fs from "fs-extra" +import path from "path" +import { type PackageJson } from "type-fest" + +import { PKG_ROOT } from "@/constants.js" +import { addPackageDependency } from "@/utils/add-package-dep.js" +import { Installer } from "./index.js" + +export const prismaInstaller: Installer = ({ projectDir }) => { + // Add Prisma CLI as a dev dependency and Prisma Client as a dependency + addPackageDependency({ + projectDir, + dependencies: ["prisma"], + devDependencies: true, + }) + // Add Prisma Accelerate for Edge support + addPackageDependency({ + projectDir, + dependencies: ["@prisma/extension-accelerate"], + devDependencies: false, + }) + addPackageDependency({ + projectDir, + dependencies: ["@prisma/client"], + devDependencies: false, + }) + + const extrasDir = path.join(PKG_ROOT, "template/extras") + + // Copy .env template + const envSrc = path.join(extrasDir, "config/_env-prisma") + const envDest = path.join(projectDir, ".env") + + // Copy Prisma schema + const schemaSrc = path.join(extrasDir, "config/schema.prisma") + const schemaDest = path.join(projectDir, "prisma/schema.prisma") + + // Copy Prisma client helper + const clientSrc = path.join(extrasDir, "src/lib/prisma.ts") + const clientDest = path.join(projectDir, "src/lib/prisma.ts") + + fs.ensureDirSync(path.dirname(envDest)) + fs.ensureDirSync(path.dirname(schemaDest)) + fs.ensureDirSync(path.dirname(clientDest)) + + fs.copySync(envSrc, envDest) + fs.copySync(schemaSrc, schemaDest) + fs.copySync(clientSrc, clientDest) + // Copy JStack middleware for Prisma + const jstackSrc = path.join(extrasDir, "src/server/jstack/prisma.ts") + const jstackDest = path.join(projectDir, "src/server/jstack.ts") + fs.ensureDirSync(path.dirname(jstackDest)) + fs.copySync(jstackSrc, jstackDest) + + // Update package.json scripts + const pkgJsonPath = path.join(projectDir, "package.json") + const pkgJson = fs.readJSONSync(pkgJsonPath) as PackageJson + pkgJson.scripts = { + ...pkgJson.scripts, + "prisma:migrate": "prisma migrate dev", + "prisma:generate": "prisma generate --no-engine", + } + fs.writeJSONSync(pkgJsonPath, pkgJson, { spaces: 2 }) +} diff --git a/cli/template/base-assets/base-package.json b/cli/template/base-assets/base-package.json index 55dd0cb..9750a81 100644 --- a/cli/template/base-assets/base-package.json +++ b/cli/template/base-assets/base-package.json @@ -9,51 +9,31 @@ "lint": "next lint" }, "dependencies": { - "@tailwindcss/postcss": "^4.0.15", - "@tanstack/react-query": "^5.69.0", - "clsx": "^2.1.1", -<<<<<<< HEAD - "drizzle-orm": "^0.41.0", - "hono": "^4.7.5", - "jstack": "^1.0.8", - "next": "^15.2.3", -======= - "hono": "^4.7.0", - "jstack": "^1.1.1", - "next": "^15.1.6", ->>>>>>> 4c241093d6beb4a9ffcb2863439af87355f70327 - "react": "^19.0.0", - "react-dom": "^19.0.0", - "superjson": "^2.2.2", - "tailwind-merge": "^3.0.2", - "zod": "^3.24.2" + "@tailwindcss/postcss": "*", + "@tanstack/react-query": "*", + "clsx": "*", + "drizzle-orm": "*", + "hono": "*", + "jstack": "*", + "next": "*", + "react": "*", + "react-dom": "*", + "superjson": "*", + "tailwind-merge": "*", + "zod": "*" }, "devDependencies": { -<<<<<<< HEAD - "dotenv": "^16.4.7", - "@cloudflare/workers-types": "^4.20250321.0", - "@types/node": "^22.13.12", - "@types/react": "^19.0.12", - "@types/react-dom": "^19.0.4", - "drizzle-kit": "^0.30.5", - "eslint": "^9.23.0", - "eslint-config-next": "^15.2.3", - "postcss": "^8.5.3", - "tailwindcss": "^4.0.15", - "typescript": "^5.8.2", - "wrangler": "^4.4.0" -======= - "dotenv": "^16.4.5", - "@cloudflare/workers-types": "^4.20250214.0", - "@types/node": "^22.10.6", - "@types/react": "^19.0.7", - "@types/react-dom": "^19.0.3", - "eslint": "^9.18.0", - "eslint-config-next": "^15.1.4", - "postcss": "^8", - "tailwindcss": "^4.0.0", - "typescript": "^5", - "wrangler": "^4.0.0" ->>>>>>> 4c241093d6beb4a9ffcb2863439af87355f70327 + "dotenv": "*", + "@cloudflare/workers-types": "*", + "@types/node": "*", + "@types/react": "*", + "@types/react-dom": "*", + "drizzle-kit": "*", + "eslint": "*", + "eslint-config-next": "*", + "postcss": "*", + "tailwindcss": "*", + "typescript": "*", + "wrangler": "*" } } diff --git a/package.json b/package.json index d92c531..7ab5e8d 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,12 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, - "keywords": ["jstack", "next.js", "typescript", "hono"], + "keywords": [ + "jstack", + "next.js", + "typescript", + "hono" + ], "dependencies": { "prettier": "^3.4.2" }