create-saas-app-cli 1.2.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 create-saas-app contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # create-saas-app
2
+
3
+ > Scaffold a production-ready **Multi-Tenant SaaS** Turborepo monorepo in seconds.
4
+
5
+ ```bash
6
+ npx create-saas-app-cli my-project
7
+ # or
8
+ npx create-saas-app-cli # prompts for project name
9
+ ```
10
+
11
+ ---
12
+
13
+ ## What it generates
14
+
15
+ An opinionated but flexible Turborepo monorepo with:
16
+
17
+ | Layer | Options |
18
+ | ------------------- | ---------------------------------------------------------------------------------- |
19
+ | **Apps** | `api` (Express) + optional `worker` (BullMQ) |
20
+ | **Database** | PostgreSQL + Drizzle · PostgreSQL + Prisma · MongoDB + Mongoose · SQLite + Drizzle |
21
+ | **Auth** | JWT (jsonwebtoken + bcryptjs) |
22
+ | **Queue** | BullMQ + Redis |
23
+ | **Rate Limiting** | None · In-memory · Redis-backed |
24
+ | **Observability** | Prometheus + Grafana (Docker Compose) |
25
+ | **CI/CD** | Optional GitHub Actions workflow (`.github/workflows/ci.yml`) |
26
+ | **Package Manager** | bun · pnpm · npm |
27
+
28
+ ---
29
+
30
+ ## Interactive prompts
31
+
32
+ ```
33
+ ◆ What is your project name?
34
+ │ my-saas-app
35
+ ◆ Which package manager do you prefer?
36
+ │ ● bun ○ pnpm ○ npm
37
+ ◆ Which database / ORM?
38
+ │ ● PostgreSQL + Drizzle ORM ○ PostgreSQL + Prisma
39
+ │ ○ MongoDB + Mongoose ○ SQLite + Drizzle ORM
40
+ ◆ Include CI/CD workflow? yes
41
+ ◆ Include a background worker app? yes
42
+ ◆ Include observability stack? no
43
+ ◆ Include auth package? yes
44
+ ◆ Include queue package? yes
45
+ ◆ Rate limiting strategy?
46
+ │ ● None ○ In-memory ○ Redis-backed
47
+ ◆ Initialize a git repository? yes
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Generated structure
53
+
54
+ ```
55
+ my-saas-app/
56
+ ├── apps/
57
+ │ ├── api/ # Express REST API
58
+ │ └── worker/ # BullMQ background worker (optional)
59
+ ├── packages/
60
+ │ ├── config/ # Shared env config
61
+ │ ├── database/ # DB client & models/schema
62
+ │ ├── logger/ # Pino structured logger
63
+ │ ├── auth/ # JWT auth helpers (optional)
64
+ │ ├── queue/ # BullMQ queues (optional)
65
+ │ ├── redis/ # ioredis client (optional)
66
+ │ ├── types/ # Shared TypeScript interfaces
67
+ │ └── typescript-config/
68
+ ├── docker/
69
+ │ └── docker-compose.yml
70
+ ├── turbo.json
71
+ └── package.json
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Getting started after scaffold
77
+
78
+ ```bash
79
+ cd my-saas-app
80
+
81
+ # Install dependencies
82
+ bun install # or pnpm install / npm install
83
+
84
+ # Start infrastructure
85
+ docker compose -f docker/docker-compose.yml up -d
86
+
87
+ # Copy env file and fill in secrets
88
+ cp apps/api/.env.example apps/api/.env
89
+
90
+ # Run DB migrations (Drizzle / Prisma only)
91
+ bun run db:migrate
92
+
93
+ # Start all apps in dev mode
94
+ bun run dev
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Publishing
100
+
101
+ ```bash
102
+ npm run build # compile TypeScript
103
+ npm publish # publish to npm registry
104
+ ```
105
+
106
+ ---
107
+
108
+ ## License
109
+
110
+ MIT
@@ -0,0 +1,4 @@
1
+ import type { ProjectAnswers } from "./prompts.js";
2
+ export declare function projectDirectoryExists(name: string): boolean;
3
+ export declare function generateProject(a: ProjectAnswers): Promise<void>;
4
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAsFnD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AAID,wBAAsB,eAAe,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAgNtE"}
@@ -0,0 +1,175 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs";
3
+ import { write, mkdirp, runCommand } from "./utils.js";
4
+ import { rootPackageJson, turboJson, gitignoreTemplate, npmrcTemplate, envExampleTemplate, apiPackageJson, workerPackageJson, appTsconfig, appTsconfigBuild, apiIndexTs, apiAppTs, apiHealthRouteTs, apiRateLimitTs, workerIndexTs, dbPackageJson, dbIndexTs, drizzleConfigTs, drizzleSchemaTs, prismaSchemaTemplate, configPackageJson, configIndexTs, loggerPackageJson, loggerIndexTs, authPackageJson, authIndexTs, queuePackageJson, queueIndexTs, redisPackageJson, redisIndexTs, typesPackageJson, typesIndexTs, typescriptConfigPackageJson, typescriptConfigBase, dockerComposeTemplate, apiDockerfile, workerDockerfile, rootReadme, vitestConfigTs, eslintConfigTs, prettierRc, tenantMiddlewareTs, workerEnvExampleTemplate, grafanaDatasourceYaml,
5
+ // Next.js web app
6
+ webPackageJson, webNextConfig, webTsconfig, webRootLayout, webGlobalsCss, webHomePage, webDashboardPage, webLoginPage, webMiddleware, webEnvExample, webDockerfile, githubActionsCiWorkflow,
7
+ // Payments
8
+ paymentsPackageJson, paymentsIndexTs, paymentsRouteTs,
9
+ // Email
10
+ emailPackageJson, emailIndexTs, } from "./templates.js";
11
+ // ─── Shared tsconfig.json for every package ───────────────────────────────────
12
+ function pkgTsconfig() {
13
+ return JSON.stringify({
14
+ extends: "@saas/typescript-config/base.json",
15
+ compilerOptions: {
16
+ outDir: "./dist",
17
+ rootDir: "./src",
18
+ },
19
+ include: ["src"],
20
+ }, null, 2);
21
+ }
22
+ // ─── Directory exists guard ───────────────────────────────────────────────────
23
+ export function projectDirectoryExists(name) {
24
+ return fs.existsSync(path.resolve(process.cwd(), name));
25
+ }
26
+ // ─── Main orchestrator ────────────────────────────────────────────────────────
27
+ export async function generateProject(a) {
28
+ const root = path.resolve(process.cwd(), a.projectName);
29
+ // ── Root files ──────────────────────────────────────────────────────────────
30
+ mkdirp(root);
31
+ write(path.join(root, "package.json"), rootPackageJson(a));
32
+ write(path.join(root, "turbo.json"), turboJson());
33
+ write(path.join(root, ".gitignore"), gitignoreTemplate());
34
+ const npmrc = npmrcTemplate(a);
35
+ if (npmrc)
36
+ write(path.join(root, ".npmrc"), npmrc);
37
+ write(path.join(root, "README.md"), rootReadme(a));
38
+ write(path.join(root, ".prettierrc"), prettierRc());
39
+ write(path.join(root, "eslint.config.ts"), eslintConfigTs());
40
+ if (a.includeCI) {
41
+ write(path.join(root, ".github", "workflows", "ci.yml"), githubActionsCiWorkflow(a));
42
+ }
43
+ // ── TypeScript config package ───────────────────────────────────────────────
44
+ const tsConfigPkg = path.join(root, "packages", "typescript-config");
45
+ write(path.join(tsConfigPkg, "package.json"), typescriptConfigPackageJson());
46
+ write(path.join(tsConfigPkg, "base.json"), typescriptConfigBase());
47
+ // ── Config package ──────────────────────────────────────────────────────────
48
+ const configPkg = path.join(root, "packages", "config");
49
+ write(path.join(configPkg, "package.json"), configPackageJson());
50
+ write(path.join(configPkg, "src", "index.ts"), configIndexTs());
51
+ write(path.join(configPkg, "tsconfig.json"), pkgTsconfig());
52
+ // ── Logger package ──────────────────────────────────────────────────────────
53
+ const loggerPkg = path.join(root, "packages", "logger");
54
+ write(path.join(loggerPkg, "package.json"), loggerPackageJson());
55
+ write(path.join(loggerPkg, "src", "index.ts"), loggerIndexTs());
56
+ write(path.join(loggerPkg, "tsconfig.json"), pkgTsconfig());
57
+ // ── Types package ───────────────────────────────────────────────────────────
58
+ const typesPkg = path.join(root, "packages", "types");
59
+ write(path.join(typesPkg, "package.json"), typesPackageJson());
60
+ write(path.join(typesPkg, "src", "index.ts"), typesIndexTs());
61
+ write(path.join(typesPkg, "tsconfig.json"), pkgTsconfig());
62
+ // ── Database package ────────────────────────────────────────────────────────
63
+ const dbPkg = path.join(root, "packages", "database");
64
+ write(path.join(dbPkg, "package.json"), dbPackageJson(a.database));
65
+ write(path.join(dbPkg, "src", "index.ts"), dbIndexTs(a.database));
66
+ write(path.join(dbPkg, "tsconfig.json"), pkgTsconfig());
67
+ if (a.database === "postgres-drizzle" || a.database === "sqlite-drizzle") {
68
+ write(path.join(dbPkg, "src", "schema.ts"), drizzleSchemaTs(a.database));
69
+ write(path.join(dbPkg, "drizzle.config.ts"), drizzleConfigTs(a.database));
70
+ }
71
+ if (a.database === "postgres-prisma") {
72
+ write(path.join(dbPkg, "prisma", "schema.prisma"), prismaSchemaTemplate(a.projectName));
73
+ }
74
+ // ── Auth package (optional) ─────────────────────────────────────────────────
75
+ if (a.includeAuth) {
76
+ const authPkg = path.join(root, "packages", "auth");
77
+ write(path.join(authPkg, "package.json"), authPackageJson());
78
+ write(path.join(authPkg, "src", "index.ts"), authIndexTs());
79
+ write(path.join(authPkg, "tsconfig.json"), pkgTsconfig());
80
+ }
81
+ // ── Redis package ───────────────────────────────────────────────────────────
82
+ const needsRedis = a.includeQueue || a.rateLimit === "redis" || a.includeWorker;
83
+ if (needsRedis) {
84
+ const redisPkg = path.join(root, "packages", "redis");
85
+ write(path.join(redisPkg, "package.json"), redisPackageJson());
86
+ write(path.join(redisPkg, "src", "index.ts"), redisIndexTs());
87
+ write(path.join(redisPkg, "tsconfig.json"), pkgTsconfig());
88
+ }
89
+ // ── Queue package (optional) ────────────────────────────────────────────────
90
+ if (a.includeQueue) {
91
+ const queuePkg = path.join(root, "packages", "queue");
92
+ write(path.join(queuePkg, "package.json"), queuePackageJson());
93
+ write(path.join(queuePkg, "src", "index.ts"), queueIndexTs());
94
+ write(path.join(queuePkg, "tsconfig.json"), pkgTsconfig());
95
+ }
96
+ // ── Payments package (optional) ─────────────────────────────────────────────
97
+ if (a.includePayments) {
98
+ const paymentsPkg = path.join(root, "packages", "payments");
99
+ write(path.join(paymentsPkg, "package.json"), paymentsPackageJson());
100
+ write(path.join(paymentsPkg, "src", "index.ts"), paymentsIndexTs());
101
+ write(path.join(paymentsPkg, "tsconfig.json"), pkgTsconfig());
102
+ }
103
+ // ── Email package (optional) ────────────────────────────────────────────────
104
+ if (a.emailProvider !== "none") {
105
+ const emailPkg = path.join(root, "packages", "email");
106
+ write(path.join(emailPkg, "package.json"), emailPackageJson(a.emailProvider));
107
+ write(path.join(emailPkg, "src", "index.ts"), emailIndexTs(a.emailProvider));
108
+ write(path.join(emailPkg, "tsconfig.json"), pkgTsconfig());
109
+ }
110
+ // ── API app ─────────────────────────────────────────────────────────────────
111
+ const apiApp = path.join(root, "apps", "api");
112
+ write(path.join(apiApp, "package.json"), apiPackageJson(a));
113
+ write(path.join(apiApp, "tsconfig.json"), appTsconfig());
114
+ write(path.join(apiApp, "tsconfig.build.json"), appTsconfigBuild());
115
+ write(path.join(apiApp, ".env.example"), envExampleTemplate(a));
116
+ write(path.join(apiApp, "vitest.config.ts"), vitestConfigTs());
117
+ write(path.join(apiApp, "src", "index.ts"), apiIndexTs());
118
+ write(path.join(apiApp, "src", "app.ts"), apiAppTs(a));
119
+ write(path.join(apiApp, "src", "routes", "health.ts"), apiHealthRouteTs());
120
+ write(path.join(apiApp, "src", "middleware", "tenant.ts"), tenantMiddlewareTs());
121
+ write(path.join(apiApp, "Dockerfile"), apiDockerfile(a));
122
+ if (a.rateLimit !== "none") {
123
+ write(path.join(apiApp, "src", "middleware", "rateLimit.ts"), apiRateLimitTs(a.rateLimit));
124
+ }
125
+ if (a.includePayments) {
126
+ write(path.join(apiApp, "src", "routes", "payments.ts"), paymentsRouteTs());
127
+ }
128
+ // ── Worker app (optional) ───────────────────────────────────────────────────
129
+ if (a.includeWorker) {
130
+ const workerApp = path.join(root, "apps", "worker");
131
+ write(path.join(workerApp, "package.json"), workerPackageJson(a));
132
+ write(path.join(workerApp, "tsconfig.json"), appTsconfig());
133
+ write(path.join(workerApp, "tsconfig.build.json"), appTsconfigBuild());
134
+ write(path.join(workerApp, ".env.example"), workerEnvExampleTemplate(a));
135
+ write(path.join(workerApp, "vitest.config.ts"), vitestConfigTs());
136
+ write(path.join(workerApp, "src", "index.ts"), workerIndexTs());
137
+ write(path.join(workerApp, "Dockerfile"), workerDockerfile(a));
138
+ }
139
+ // ── Next.js web app (optional) ──────────────────────────────────────────────
140
+ if (a.includeWeb) {
141
+ const webApp = path.join(root, "apps", "web");
142
+ write(path.join(webApp, "package.json"), webPackageJson(a));
143
+ write(path.join(webApp, "next.config.ts"), webNextConfig());
144
+ write(path.join(webApp, "tsconfig.json"), webTsconfig());
145
+ write(path.join(webApp, ".env.example"), webEnvExample(a));
146
+ write(path.join(webApp, "Dockerfile"), webDockerfile(a));
147
+ // App Router pages
148
+ write(path.join(webApp, "src", "app", "layout.tsx"), webRootLayout(a));
149
+ write(path.join(webApp, "src", "app", "globals.css"), webGlobalsCss());
150
+ write(path.join(webApp, "src", "app", "page.tsx"), webHomePage(a));
151
+ write(path.join(webApp, "src", "app", "dashboard", "page.tsx"), webDashboardPage());
152
+ write(path.join(webApp, "src", "app", "(auth)", "login", "page.tsx"), webLoginPage());
153
+ // Next.js middleware (auth guard)
154
+ write(path.join(webApp, "src", "middleware.ts"), webMiddleware());
155
+ }
156
+ // ── Docker compose ──────────────────────────────────────────────────────────
157
+ const dockerDir = path.join(root, "docker");
158
+ write(path.join(dockerDir, "docker-compose.yml"), dockerComposeTemplate(a));
159
+ if (a.includeObservability) {
160
+ write(path.join(dockerDir, "observability", "prometheus.yml"), `global:\n scrape_interval: 15s\n\nscrape_configs:\n - job_name: "api"\n static_configs:\n - targets: ["api:3000"]\n`);
161
+ write(path.join(dockerDir, "observability", "grafana", "provisioning", "datasources", "datasources.yaml"), grafanaDatasourceYaml());
162
+ }
163
+ // ── Git init (optional) ─────────────────────────────────────────────────────
164
+ if (a.gitInit) {
165
+ try {
166
+ await runCommand("git", ["init"], root);
167
+ await runCommand("git", ["add", "."], root);
168
+ await runCommand("git", ["commit", "-m", "chore: initial scaffold via create-saas-app"], root);
169
+ }
170
+ catch {
171
+ // git errors are non-fatal
172
+ }
173
+ }
174
+ }
175
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+ import * as p from "@clack/prompts";
3
+ import pc from "picocolors";
4
+ import { readFileSync } from "node:fs";
5
+ import { fileURLToPath } from "node:url";
6
+ import { dirname, join } from "node:path";
7
+ import { runPrompts } from "./prompts.js";
8
+ import { generateProject, projectDirectoryExists } from "./generator.js";
9
+ import { execa } from "execa";
10
+ // ─── Resolve package version ─────────────────────────────────────────────────
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+ const pkgJson = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
13
+ const VERSION = pkgJson.version;
14
+ // ─── CLI flags ────────────────────────────────────────────────────────────────
15
+ const args = process.argv.slice(2);
16
+ function buildNextSteps(answers, didInstall) {
17
+ const pm = answers.packageManager;
18
+ const devCmd = pm === "bun" ? "bun dev" : `${pm} run dev`;
19
+ const dbMigrateCmd = `${pm} run db:migrate`;
20
+ const lines = [
21
+ `${pc.green("✔")} Done! Next steps:`,
22
+ "",
23
+ ` ${pc.cyan(`cd ${answers.projectName}`)}`,
24
+ ];
25
+ if (!didInstall) {
26
+ lines.push(` ${pc.cyan(`${pm} install`)}`);
27
+ }
28
+ lines.push(` ${pc.dim("# Start infrastructure")}`, ` ${pc.cyan("docker compose -f docker/docker-compose.yml up -d")}`, ` ${pc.dim("# Copy env files")}`, ` ${pc.cyan("cp apps/api/.env.example apps/api/.env")}`);
29
+ if (answers.includeWorker) {
30
+ lines.push(` ${pc.cyan("cp apps/worker/.env.example apps/worker/.env")}`);
31
+ }
32
+ if (answers.includeWeb) {
33
+ lines.push(` ${pc.cyan("cp apps/web/.env.example apps/web/.env.local")}`);
34
+ }
35
+ lines.push(` ${pc.dim("# Windows (PowerShell) copy alternative")}`, ` ${pc.cyan('Copy-Item "apps/api/.env.example" "apps/api/.env"')}`);
36
+ if (answers.includeWorker) {
37
+ lines.push(` ${pc.cyan('Copy-Item "apps/worker/.env.example" "apps/worker/.env"')}`);
38
+ }
39
+ if (answers.includeWeb) {
40
+ lines.push(` ${pc.cyan('Copy-Item "apps/web/.env.example" "apps/web/.env.local"')}`);
41
+ }
42
+ if (answers.database !== "mongodb-mongoose") {
43
+ lines.push(` ${pc.dim("# Run database migrations")}`, ` ${pc.cyan(dbMigrateCmd)}`);
44
+ }
45
+ lines.push(` ${pc.dim("# Start dev")}`, ` ${pc.cyan(devCmd)}`, "");
46
+ return lines.join("\n");
47
+ }
48
+ if (args.includes("--version") || args.includes("-v")) {
49
+ console.log(`create-saas-app v${VERSION}`);
50
+ process.exit(0);
51
+ }
52
+ if (args.includes("--help") || args.includes("-h")) {
53
+ console.log(`
54
+ ${pc.bold("create-saas-app")} v${VERSION}
55
+
56
+ ${pc.dim("Scaffold a production-ready Multi-Tenant SaaS Turborepo monorepo.")}
57
+
58
+ ${pc.bold("Usage:")}
59
+ npx create-saas-app [project-name] [options]
60
+
61
+ ${pc.bold("Options:")}
62
+ --help, -h Show this help message
63
+ --version, -v Show version number
64
+
65
+ ${pc.bold("Examples:")}
66
+ npx create-saas-app
67
+ npx create-saas-app my-startup
68
+ `);
69
+ process.exit(0);
70
+ }
71
+ // ─── Main ─────────────────────────────────────────────────────────────────────
72
+ async function main() {
73
+ console.log();
74
+ p.intro(`${pc.bgCyan(pc.black(" create-saas-app "))} ${pc.dim(`v${VERSION} · Multi-Tenant SaaS Boilerplate`)}`);
75
+ const projectName = args.find((a) => !a.startsWith("-"));
76
+ const answers = await runPrompts(projectName);
77
+ if (p.isCancel(answers)) {
78
+ p.cancel("Operation cancelled.");
79
+ process.exit(0);
80
+ }
81
+ // ── Directory conflict guard ─────────────────────────────────────────────────
82
+ if (projectDirectoryExists(answers.projectName)) {
83
+ const overwrite = await p.confirm({
84
+ message: `Directory ${pc.yellow(answers.projectName)} already exists. Overwrite?`,
85
+ initialValue: false,
86
+ });
87
+ if (p.isCancel(overwrite) || !overwrite) {
88
+ p.cancel("Aborted.");
89
+ process.exit(0);
90
+ }
91
+ }
92
+ const spinner = p.spinner();
93
+ spinner.start("Scaffolding your project...");
94
+ try {
95
+ await generateProject(answers);
96
+ spinner.stop("Project scaffolded successfully!");
97
+ }
98
+ catch (err) {
99
+ spinner.stop("Failed to scaffold project.");
100
+ console.error(err);
101
+ process.exit(1);
102
+ }
103
+ // ── Offer to install dependencies ────────────────────────────────────────────
104
+ const pm = answers.packageManager;
105
+ const runInstall = await p.confirm({
106
+ message: `Run ${pc.cyan(`${pm} install`)} now?`,
107
+ initialValue: true,
108
+ });
109
+ const didInstall = !p.isCancel(runInstall) && runInstall;
110
+ if (didInstall) {
111
+ const installSpinner = p.spinner();
112
+ installSpinner.start(`Installing dependencies with ${pm}...`);
113
+ try {
114
+ await execa(pm, ["install"], {
115
+ cwd: answers.projectName,
116
+ stdio: "pipe",
117
+ });
118
+ installSpinner.stop("Dependencies installed!");
119
+ }
120
+ catch {
121
+ installSpinner.stop(pc.yellow("Install failed — run it manually after reviewing the logs."));
122
+ }
123
+ }
124
+ p.outro(buildNextSteps(answers, didInstall));
125
+ }
126
+ main().catch(console.error);
127
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export type DatabaseChoice = "postgres-drizzle" | "postgres-prisma" | "mongodb-mongoose" | "sqlite-drizzle";
2
+ export type RateLimitChoice = "none" | "memory" | "redis";
3
+ export type PackageManager = "bun" | "pnpm" | "npm";
4
+ export type EmailProvider = "none" | "resend" | "nodemailer";
5
+ export interface ProjectAnswers {
6
+ projectName: string;
7
+ packageManager: PackageManager;
8
+ database: DatabaseChoice;
9
+ includeCI: boolean;
10
+ includeWeb: boolean;
11
+ includeWorker: boolean;
12
+ includeObservability: boolean;
13
+ includeAuth: boolean;
14
+ includeQueue: boolean;
15
+ includePayments: boolean;
16
+ emailProvider: EmailProvider;
17
+ rateLimit: RateLimitChoice;
18
+ gitInit: boolean;
19
+ }
20
+ export declare function runPrompts(nameArg?: string): Promise<ProjectAnswers | symbol>;
21
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,iBAAiB,GACjB,kBAAkB,GAClB,gBAAgB,CAAC;AAErB,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1D,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;AAEpD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,UAAU,CAC9B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC,CAmJlC"}
@@ -0,0 +1,120 @@
1
+ import * as p from "@clack/prompts";
2
+ export async function runPrompts(nameArg) {
3
+ const group = await p.group({
4
+ projectName: () => p.text({
5
+ message: "What is your project name?",
6
+ placeholder: "my-saas-app",
7
+ defaultValue: nameArg ?? "my-saas-app",
8
+ validate: (v) => {
9
+ if (!v)
10
+ return "Project name is required";
11
+ if (!/^[a-z0-9-_]+$/i.test(v))
12
+ return "Only letters, numbers, dashes and underscores are allowed";
13
+ },
14
+ }),
15
+ packageManager: () => p.select({
16
+ message: "Which package manager do you prefer?",
17
+ options: [
18
+ { value: "bun", label: "bun", hint: "fastest" },
19
+ { value: "pnpm", label: "pnpm", hint: "efficient" },
20
+ { value: "npm", label: "npm", hint: "classic" },
21
+ ],
22
+ }),
23
+ database: () => p.select({
24
+ message: "Which database / ORM?",
25
+ options: [
26
+ {
27
+ value: "postgres-drizzle",
28
+ label: "PostgreSQL + Drizzle ORM",
29
+ hint: "type-safe SQL",
30
+ },
31
+ {
32
+ value: "postgres-prisma",
33
+ label: "PostgreSQL + Prisma",
34
+ hint: "schema-first",
35
+ },
36
+ {
37
+ value: "mongodb-mongoose",
38
+ label: "MongoDB + Mongoose",
39
+ hint: "document model",
40
+ },
41
+ {
42
+ value: "sqlite-drizzle",
43
+ label: "SQLite + Drizzle ORM",
44
+ hint: "zero-infra",
45
+ },
46
+ ],
47
+ }),
48
+ includeCI: () => p.confirm({
49
+ message: "Include CI/CD workflow? (.github/workflows/ci.yml)",
50
+ initialValue: true,
51
+ }),
52
+ includeWeb: () => p.confirm({
53
+ message: "Include a Next.js 15 web app? (apps/web/)",
54
+ initialValue: true,
55
+ }),
56
+ includeWorker: () => p.confirm({
57
+ message: "Include a background worker app? (long-running process + BullMQ ready)",
58
+ initialValue: true,
59
+ }),
60
+ includeObservability: () => p.confirm({
61
+ message: "Include observability stack? (Prometheus + Loki + Grafana via Docker)",
62
+ initialValue: false,
63
+ }),
64
+ includeAuth: () => p.confirm({
65
+ message: "Include auth package? (JWT-based)",
66
+ initialValue: true,
67
+ }),
68
+ includeQueue: () => p.confirm({
69
+ message: "Include queue package? (BullMQ + Redis)",
70
+ initialValue: true,
71
+ }),
72
+ includePayments: () => p.confirm({
73
+ message: "Include payments package? (Razorpay — orders + webhooks)",
74
+ initialValue: false,
75
+ }),
76
+ emailProvider: () => p.select({
77
+ message: "Email provider?",
78
+ options: [
79
+ { value: "none", label: "None", hint: "skip email" },
80
+ {
81
+ value: "resend",
82
+ label: "Resend",
83
+ hint: "modern API-first email",
84
+ },
85
+ {
86
+ value: "nodemailer",
87
+ label: "Nodemailer",
88
+ hint: "SMTP / self-hosted",
89
+ },
90
+ ],
91
+ }),
92
+ rateLimit: () => p.select({
93
+ message: "Rate limiting strategy?",
94
+ options: [
95
+ { value: "none", label: "None", hint: "skip rate limiting" },
96
+ {
97
+ value: "memory",
98
+ label: "In-memory",
99
+ hint: "express-rate-limit (single node)",
100
+ },
101
+ {
102
+ value: "redis",
103
+ label: "Redis-backed",
104
+ hint: "rate-limit-redis (distributed)",
105
+ },
106
+ ],
107
+ }),
108
+ gitInit: () => p.confirm({
109
+ message: "Initialize a git repository?",
110
+ initialValue: true,
111
+ }),
112
+ }, {
113
+ onCancel: () => {
114
+ p.cancel("Operation cancelled.");
115
+ process.exit(0);
116
+ },
117
+ });
118
+ return group;
119
+ }
120
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}