create-pba 1.0.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/.env.example ADDED
@@ -0,0 +1,18 @@
1
+ BETTER_AUTH_SECRET="mehul"
2
+ BETTER_AUTH_URL=`http://localhost:${PORT}` # Base URL of your app
3
+ GITHUB_CLIENT_ID=
4
+ GITHUB_CLIENT_SECRET=
5
+ PORT=3005
6
+ # This was inserted by `prisma init`:
7
+ # Environment variables declared in this file are NOT automatically loaded by Prisma.
8
+ # Please add `import "dotenv/config";` to your `prisma.config.ts` file, or use the Prisma CLI with Bun
9
+ # to load environment variables from .env files: https://pris.ly/prisma-config-env-vars.
10
+
11
+ # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
12
+ # See the documentation for all the connection string options: https://pris.ly/d/connection-strings
13
+
14
+ # The following `prisma+postgres` URL is similar to the URL produced by running a local Prisma Postgres
15
+ # server with the `prisma dev` CLI command, when not choosing any non-default ports or settings. The API key, unlike the
16
+ # one found in a remote Prisma Postgres URL, does not contain any sensitive information.
17
+
18
+ DATABASE_URL=""
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const child_process_1 = require("child_process");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const readline_1 = __importDefault(require("readline"));
11
+ const rl = readline_1.default.createInterface({
12
+ input: process.stdin,
13
+ output: process.stdout
14
+ });
15
+ const ask = (query) => new Promise((resolve) => rl.question(query, resolve));
16
+ async function main() {
17
+ const args = process.argv.slice(2);
18
+ let projectName = "";
19
+ // Parse arguments
20
+ for (let i = 0; i < args.length; i++) {
21
+ if (args[i] === "--name" || args[i] === "-n") {
22
+ projectName = args[i + 1] || "";
23
+ break;
24
+ }
25
+ }
26
+ // If no name found via flag, check positional argument
27
+ if (!projectName && args[0] && !args[0].startsWith("-")) {
28
+ projectName = args[0];
29
+ }
30
+ // If still no name, prompt the user
31
+ if (!projectName) {
32
+ projectName = await ask("📁 Enter project name (default: my-pba-app): ");
33
+ projectName = projectName.trim() || "my-pba-app";
34
+ }
35
+ const templateDir = path_1.default.resolve(__dirname, "..");
36
+ console.log(`🚀 Creating a new Prisma Better Auth project in: ${projectName}`);
37
+ if (fs_1.default.existsSync(projectName)) {
38
+ console.error(`❌ Error: Directory "${projectName}" already exists.`);
39
+ rl.close();
40
+ process.exit(1);
41
+ }
42
+ // 1. Create project directory
43
+ fs_1.default.mkdirSync(projectName);
44
+ process.chdir(projectName);
45
+ // 2. Initialize npm
46
+ console.log("📦 Initializing project...");
47
+ (0, child_process_1.execSync)("npm init -y", { stdio: "inherit" });
48
+ // 3. Copy files from template
49
+ console.log("📂 Copying template files...");
50
+ const itemsToCopy = [
51
+ "src",
52
+ "prisma",
53
+ "tsconfig.json",
54
+ "prisma.config.ts",
55
+ ".env.example",
56
+ ".gitignore"
57
+ ];
58
+ itemsToCopy.forEach((item) => {
59
+ const srcPath = path_1.default.join(templateDir, item);
60
+ const destPath = path_1.default.join(process.cwd(), item);
61
+ if (fs_1.default.existsSync(srcPath)) {
62
+ if (item === "src") {
63
+ // Copy src while excluding cli.ts
64
+ if (!fs_1.default.existsSync(destPath))
65
+ fs_1.default.mkdirSync(destPath, { recursive: true });
66
+ const files = fs_1.default.readdirSync(srcPath);
67
+ files.forEach(file => {
68
+ if (file !== "cli.ts") {
69
+ fs_1.default.cpSync(path_1.default.join(srcPath, file), path_1.default.join(destPath, file), { recursive: true });
70
+ }
71
+ });
72
+ }
73
+ else {
74
+ fs_1.default.cpSync(srcPath, destPath, { recursive: true });
75
+ }
76
+ }
77
+ });
78
+ // 4. Ask to install dependencies
79
+ const installDeps = await ask("📥 Do you want to install dependencies now? (y/n): ");
80
+ rl.close();
81
+ if (installDeps.toLowerCase() === "y" || installDeps.toLowerCase() === "yes") {
82
+ console.log("📥 Installing dependencies...");
83
+ const deps = [
84
+ "express",
85
+ "prisma",
86
+ "better-auth",
87
+ "@prisma/client",
88
+ "cors",
89
+ "dotenv"
90
+ ];
91
+ const devDeps = [
92
+ "typescript",
93
+ "ts-node",
94
+ "nodemon",
95
+ "@types/express",
96
+ "@types/cors",
97
+ "@types/node"
98
+ ];
99
+ (0, child_process_1.execSync)(`npm install ${deps.join(" ")}`, { stdio: "inherit" });
100
+ (0, child_process_1.execSync)(`npm install -D ${devDeps.join(" ")}`, { stdio: "inherit" });
101
+ }
102
+ else {
103
+ console.log("⚠️ Skipping dependency installation. You will need to run 'npm install' manually.");
104
+ }
105
+ // 5. Update package.json in the new project to include scripts
106
+ const pkgPath = path_1.default.join(process.cwd(), "package.json");
107
+ const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, "utf-8"));
108
+ pkg.scripts = {
109
+ "dev": "nodemon --exec ts-node src/server.ts",
110
+ "build": "tsc",
111
+ "start": "node dist/server.js",
112
+ "generate": "prisma generate",
113
+ "studio": "prisma studio"
114
+ };
115
+ fs_1.default.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
116
+ console.log(`
117
+ ✅ Project "${projectName}" created successfully!
118
+ `);
119
+ }
120
+ main().catch(err => {
121
+ console.error(err);
122
+ process.exit(1);
123
+ });
124
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import "dotenv/config";
2
+ export declare const auth: import("better-auth").Auth<{
3
+ database: (options: import("better-auth").BetterAuthOptions) => import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>;
4
+ socialProviders: {
5
+ github: {
6
+ clientId: string;
7
+ clientSecret: string;
8
+ };
9
+ };
10
+ trustedOrigins: string[];
11
+ }>;
12
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAIA,OAAO,eAAe,CAAA;AAItB,eAAO,MAAM,IAAI;;;;sBAMiC,MAAM;0BACE,MAAM;;;;EAM9D,CAAC"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.auth = void 0;
4
+ const better_auth_1 = require("better-auth");
5
+ const prisma_1 = require("better-auth/adapters/prisma");
6
+ const client_1 = require("@prisma/client");
7
+ require("dotenv/config");
8
+ const prisma = new client_1.PrismaClient();
9
+ exports.auth = (0, better_auth_1.betterAuth)({
10
+ database: (0, prisma_1.prismaAdapter)(prisma, {
11
+ provider: "postgresql", // or "mysql", "postgresql", ...etc
12
+ }),
13
+ socialProviders: {
14
+ github: {
15
+ clientId: process.env.GITHUB_CLIENT_ID,
16
+ clientSecret: process.env.GITHUB_CLIENT_SECRET,
17
+ },
18
+ },
19
+ trustedOrigins: [
20
+ "http://localhost:3000" //change this to your frontend url
21
+ ],
22
+ });
23
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AACzC,wDAA4D;AAC5D,2CAA8C;AAE9C,yBAAsB;AACtB,MAAM,MAAM,GAAG,IAAI,qBAAY,EAAE,CAAC;AAGrB,QAAA,IAAI,GAAG,IAAA,wBAAU,EAAC;IAC3B,QAAQ,EAAE,IAAA,sBAAa,EAAC,MAAM,EAAE;QAC5B,QAAQ,EAAE,YAAY,EAAE,mCAAmC;KAC9D,CAAC;IACF,eAAe,EAAE;QACf,MAAM,EAAE;YACN,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAA0B;YAChD,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,oBAA8B;SACzD;KACF;IACD,cAAc,EAAE;QACZ,uBAAuB,CAAC,kCAAkC;KAC3D;CACN,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
package/dist/server.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const express_1 = __importDefault(require("express"));
7
+ const node_1 = require("better-auth/node");
8
+ const cors_1 = __importDefault(require("cors")); // Import the CORS middleware
9
+ const auth_1 = require("./lib/auth");
10
+ const app = (0, express_1.default)();
11
+ const port = process.env.PORT;
12
+ app.use((0, cors_1.default)({
13
+ origin: "http://localhost:3000", // Replace with your frontend's origin
14
+ methods: ["GET", "POST", "PUT", "DELETE"], // Specify allowed HTTP methods
15
+ credentials: true, // Allow credentials (cookies, authorization headers, etc.)
16
+ }));
17
+ // app.all("/api/auth/*", toNodeHandler(auth)); // For ExpressJS v4
18
+ app.all("/api/auth/*splat", (0, node_1.toNodeHandler)(auth_1.auth)); // For ExpressJS v5
19
+ // Mount express json middleware after Better Auth handler
20
+ // or only apply it to routes that don't interact with Better Auth
21
+ app.get("/api/me", async (req, res) => {
22
+ const session = await auth_1.auth.api.getSession({
23
+ headers: (0, node_1.fromNodeHeaders)(req.headers),
24
+ });
25
+ return res.json(session);
26
+ });
27
+ app.use(express_1.default.json());
28
+ app.listen(port, () => {
29
+ console.log(`Example app listening on port ${port}`);
30
+ });
31
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,2CAAkE;AAClE,gDAAwB,CAAC,6BAA6B;AACtD,qCAAkC;AAClC,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAA;AAE7B,GAAG,CAAC,GAAG,CACL,IAAA,cAAI,EAAC;IACH,MAAM,EAAE,uBAAuB,EAAE,sCAAsC;IACvE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,+BAA+B;IAC1E,WAAW,EAAE,IAAI,EAAE,2DAA2D;CAC/E,CAAC,CACH,CAAC;AAEF,mEAAmE;AACnE,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAA,oBAAa,EAAC,WAAI,CAAC,CAAC,CAAC,CAAC,oBAAoB;AAEtE,0DAA0D;AAC1D,kEAAkE;AAElE,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACpC,MAAM,OAAO,GAAG,MAAM,WAAI,CAAC,GAAG,CAAC,UAAU,CAAC;QACtC,OAAO,EAAE,IAAA,sBAAe,EAAC,GAAG,CAAC,OAAO,CAAC;KACtC,CAAC,CAAC;IACN,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC,CAAC,CAAC;AAUH,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AACxB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACrB,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "create-pba",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "dist/server.js",
6
+ "bin": {
7
+ "create-pba": "./dist/cli.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1",
11
+ "dev": "nodemon --exec ts-node src/server.ts",
12
+ "build": "tsc",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "src",
18
+ "prisma",
19
+ "tsconfig.json",
20
+ "prisma.config.ts",
21
+ ".env.example"
22
+ ],
23
+ "keywords": [],
24
+ "author": "",
25
+ "license": "ISC",
26
+ "type": "commonjs",
27
+ "dependencies": {
28
+ "@prisma/client": "^6.19.2",
29
+ "better-auth": "^1.5.4",
30
+ "cors": "^2.8.6",
31
+ "dotenv": "^17.3.1",
32
+ "express": "^5.2.1",
33
+ "nodemon": "^3.1.14",
34
+ "prisma": "^6.19.2"
35
+ },
36
+ "devDependencies": {
37
+ "@types/cors": "^2.8.19",
38
+ "@types/express": "^5.0.6",
39
+ "@types/node": "^25.5.0",
40
+ "ts-node": "^10.9.2",
41
+ "typescript": "^5.9.3"
42
+ }
43
+ }
@@ -0,0 +1,105 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - You are about to drop the `Account` table. If the table is not empty, all the data it contains will be lost.
5
+ - You are about to drop the `Session` table. If the table is not empty, all the data it contains will be lost.
6
+ - You are about to drop the `User` table. If the table is not empty, all the data it contains will be lost.
7
+ - You are about to drop the `Verification` table. If the table is not empty, all the data it contains will be lost.
8
+
9
+ */
10
+ -- DropForeignKey
11
+ ALTER TABLE "Account" DROP CONSTRAINT "Account_userId_fkey";
12
+
13
+ -- DropForeignKey
14
+ ALTER TABLE "Session" DROP CONSTRAINT "Session_userId_fkey";
15
+
16
+ -- DropTable
17
+ DROP TABLE "Account";
18
+
19
+ -- DropTable
20
+ DROP TABLE "Session";
21
+
22
+ -- DropTable
23
+ DROP TABLE "User";
24
+
25
+ -- DropTable
26
+ DROP TABLE "Verification";
27
+
28
+ -- CreateTable
29
+ CREATE TABLE "user" (
30
+ "id" TEXT NOT NULL,
31
+ "name" TEXT NOT NULL,
32
+ "email" TEXT NOT NULL,
33
+ "emailVerified" BOOLEAN NOT NULL DEFAULT false,
34
+ "image" TEXT,
35
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
36
+ "updatedAt" TIMESTAMP(3) NOT NULL,
37
+
38
+ CONSTRAINT "user_pkey" PRIMARY KEY ("id")
39
+ );
40
+
41
+ -- CreateTable
42
+ CREATE TABLE "session" (
43
+ "id" TEXT NOT NULL,
44
+ "expiresAt" TIMESTAMP(3) NOT NULL,
45
+ "token" TEXT NOT NULL,
46
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
47
+ "updatedAt" TIMESTAMP(3) NOT NULL,
48
+ "ipAddress" TEXT,
49
+ "userAgent" TEXT,
50
+ "userId" TEXT NOT NULL,
51
+
52
+ CONSTRAINT "session_pkey" PRIMARY KEY ("id")
53
+ );
54
+
55
+ -- CreateTable
56
+ CREATE TABLE "account" (
57
+ "id" TEXT NOT NULL,
58
+ "accountId" TEXT NOT NULL,
59
+ "providerId" TEXT NOT NULL,
60
+ "userId" TEXT NOT NULL,
61
+ "accessToken" TEXT,
62
+ "refreshToken" TEXT,
63
+ "idToken" TEXT,
64
+ "accessTokenExpiresAt" TIMESTAMP(3),
65
+ "refreshTokenExpiresAt" TIMESTAMP(3),
66
+ "scope" TEXT,
67
+ "password" TEXT,
68
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
69
+ "updatedAt" TIMESTAMP(3) NOT NULL,
70
+
71
+ CONSTRAINT "account_pkey" PRIMARY KEY ("id")
72
+ );
73
+
74
+ -- CreateTable
75
+ CREATE TABLE "verification" (
76
+ "id" TEXT NOT NULL,
77
+ "identifier" TEXT NOT NULL,
78
+ "value" TEXT NOT NULL,
79
+ "expiresAt" TIMESTAMP(3) NOT NULL,
80
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
81
+ "updatedAt" TIMESTAMP(3) NOT NULL,
82
+
83
+ CONSTRAINT "verification_pkey" PRIMARY KEY ("id")
84
+ );
85
+
86
+ -- CreateIndex
87
+ CREATE UNIQUE INDEX "user_email_key" ON "user"("email");
88
+
89
+ -- CreateIndex
90
+ CREATE INDEX "session_userId_idx" ON "session"("userId");
91
+
92
+ -- CreateIndex
93
+ CREATE UNIQUE INDEX "session_token_key" ON "session"("token");
94
+
95
+ -- CreateIndex
96
+ CREATE INDEX "account_userId_idx" ON "account"("userId");
97
+
98
+ -- CreateIndex
99
+ CREATE INDEX "verification_identifier_idx" ON "verification"("identifier");
100
+
101
+ -- AddForeignKey
102
+ ALTER TABLE "session" ADD CONSTRAINT "session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
103
+
104
+ -- AddForeignKey
105
+ ALTER TABLE "account" ADD CONSTRAINT "account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,3 @@
1
+ # Please do not edit this file manually
2
+ # It should be added in your version-control system (e.g., Git)
3
+ provider = "postgresql"
@@ -0,0 +1,73 @@
1
+
2
+ generator client {
3
+ provider = "prisma-client-js"
4
+ }
5
+
6
+ datasource db {
7
+ provider = "postgresql"
8
+ url = env("DATABASE_URL")
9
+ }
10
+
11
+
12
+ model User {
13
+ id String @id
14
+ name String
15
+ email String
16
+ emailVerified Boolean @default(false)
17
+ image String?
18
+ createdAt DateTime @default(now())
19
+ updatedAt DateTime @updatedAt
20
+ sessions Session[]
21
+ accounts Account[]
22
+
23
+ @@unique([email])
24
+ @@map("user")
25
+ }
26
+
27
+ model Session {
28
+ id String @id
29
+ expiresAt DateTime
30
+ token String
31
+ createdAt DateTime @default(now())
32
+ updatedAt DateTime @updatedAt
33
+ ipAddress String?
34
+ userAgent String?
35
+ userId String
36
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
37
+
38
+ @@unique([token])
39
+ @@index([userId])
40
+ @@map("session")
41
+ }
42
+
43
+ model Account {
44
+ id String @id
45
+ accountId String
46
+ providerId String
47
+ userId String
48
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
49
+ accessToken String?
50
+ refreshToken String?
51
+ idToken String?
52
+ accessTokenExpiresAt DateTime?
53
+ refreshTokenExpiresAt DateTime?
54
+ scope String?
55
+ password String?
56
+ createdAt DateTime @default(now())
57
+ updatedAt DateTime @updatedAt
58
+
59
+ @@index([userId])
60
+ @@map("account")
61
+ }
62
+
63
+ model Verification {
64
+ id String @id
65
+ identifier String
66
+ value String
67
+ expiresAt DateTime
68
+ createdAt DateTime @default(now())
69
+ updatedAt DateTime @updatedAt
70
+
71
+ @@index([identifier])
72
+ @@map("verification")
73
+ }
@@ -0,0 +1,14 @@
1
+ // This file was generated by Prisma, and assumes you have installed the following:
2
+ // npm install --save-dev prisma dotenv
3
+ import "dotenv/config";
4
+ import { defineConfig } from "prisma/config";
5
+
6
+ export default defineConfig({
7
+ schema: "prisma/schema.prisma",
8
+ migrations: {
9
+ path: "prisma/migrations",
10
+ },
11
+ datasource: {
12
+ url: process.env["DATABASE_URL"],
13
+ },
14
+ });
package/src/cli.ts ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execSync } from "child_process";
4
+ import fs from "fs";
5
+ import path from "path";
6
+ import readline from "readline";
7
+
8
+ const rl = readline.createInterface({
9
+ input: process.stdin,
10
+ output: process.stdout
11
+ });
12
+
13
+ const ask = (query: string): Promise<string> => new Promise((resolve) => rl.question(query, resolve));
14
+
15
+ async function main() {
16
+ const args = process.argv.slice(2);
17
+ let projectName = "";
18
+
19
+ // Parse arguments
20
+ for (let i = 0; i < args.length; i++) {
21
+ if (args[i] === "--name" || args[i] === "-n") {
22
+ projectName = args[i + 1] || "";
23
+ break;
24
+ }
25
+ }
26
+
27
+ // If no name found via flag, check positional argument
28
+ if (!projectName && args[0] && !args[0].startsWith("-")) {
29
+ projectName = args[0];
30
+ }
31
+
32
+ // If still no name, prompt the user
33
+ if (!projectName) {
34
+ projectName = await ask("📁 Enter project name (default: my-pba-app): ");
35
+ projectName = projectName.trim() || "my-pba-app";
36
+ }
37
+
38
+ const templateDir = path.resolve(__dirname, "..");
39
+
40
+ console.log(`🚀 Creating a new Prisma Better Auth project in: ${projectName}`);
41
+
42
+ if (fs.existsSync(projectName)) {
43
+ console.error(`❌ Error: Directory "${projectName}" already exists.`);
44
+ rl.close();
45
+ process.exit(1);
46
+ }
47
+
48
+ // 1. Create project directory
49
+ fs.mkdirSync(projectName);
50
+ process.chdir(projectName);
51
+
52
+ // 2. Initialize npm
53
+ console.log("📦 Initializing project...");
54
+ execSync("npm init -y", { stdio: "inherit" });
55
+
56
+ // 3. Copy files from template
57
+ console.log("📂 Copying template files...");
58
+ const itemsToCopy = [
59
+ "src",
60
+ "prisma",
61
+ "tsconfig.json",
62
+ "prisma.config.ts",
63
+ ".env.example",
64
+ ".gitignore"
65
+ ];
66
+
67
+ itemsToCopy.forEach((item) => {
68
+ const srcPath = path.join(templateDir, item);
69
+ const destPath = path.join(process.cwd(), item);
70
+
71
+ if (fs.existsSync(srcPath)) {
72
+ if (item === "src") {
73
+ // Copy src while excluding cli.ts
74
+ if (!fs.existsSync(destPath)) fs.mkdirSync(destPath, { recursive: true });
75
+ const files = fs.readdirSync(srcPath);
76
+ files.forEach(file => {
77
+ if (file !== "cli.ts") {
78
+ fs.cpSync(path.join(srcPath, file), path.join(destPath, file), { recursive: true });
79
+ }
80
+ });
81
+ } else {
82
+ fs.cpSync(srcPath, destPath, { recursive: true });
83
+ }
84
+ }
85
+ });
86
+
87
+ // 4. Ask to install dependencies
88
+ const installDeps = await ask("📥 Do you want to install dependencies now? (y/n): ");
89
+ rl.close();
90
+
91
+ if (installDeps.toLowerCase() === "y" || installDeps.toLowerCase() === "yes") {
92
+ console.log("📥 Installing dependencies...");
93
+ const deps = [
94
+ "express",
95
+ "prisma",
96
+ "better-auth",
97
+ "@prisma/client",
98
+ "cors",
99
+ "dotenv"
100
+ ];
101
+ const devDeps = [
102
+ "typescript",
103
+ "ts-node",
104
+ "nodemon",
105
+ "@types/express",
106
+ "@types/cors",
107
+ "@types/node"
108
+ ];
109
+
110
+ execSync(`npm install ${deps.join(" ")}`, { stdio: "inherit" });
111
+ execSync(`npm install -D ${devDeps.join(" ")}`, { stdio: "inherit" });
112
+ } else {
113
+ console.log("⚠️ Skipping dependency installation. You will need to run 'npm install' manually.");
114
+ }
115
+
116
+ // 5. Update package.json in the new project to include scripts
117
+ const pkgPath = path.join(process.cwd(), "package.json");
118
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
119
+ pkg.scripts = {
120
+ "dev": "nodemon --exec ts-node src/server.ts",
121
+ "build": "tsc",
122
+ "start": "node dist/server.js",
123
+ "generate": "prisma generate",
124
+ "studio": "prisma studio"
125
+ };
126
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
127
+
128
+ console.log(`
129
+ ✅ Project "${projectName}" created successfully!
130
+ `);
131
+ }
132
+
133
+ main().catch(err => {
134
+ console.error(err);
135
+ process.exit(1);
136
+ });
@@ -0,0 +1,22 @@
1
+ import { betterAuth } from "better-auth";
2
+ import { prismaAdapter } from "better-auth/adapters/prisma";
3
+ import { PrismaClient } from "@prisma/client";
4
+ import dotenv from "dotenv";
5
+ import "dotenv/config"
6
+ const prisma = new PrismaClient();
7
+
8
+
9
+ export const auth = betterAuth({
10
+ database: prismaAdapter(prisma, {
11
+ provider: "postgresql", // or "mysql", "postgresql", ...etc
12
+ }),
13
+ socialProviders: {
14
+ github: {
15
+ clientId: process.env.GITHUB_CLIENT_ID as string,
16
+ clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
17
+ },
18
+ },
19
+ trustedOrigins: [
20
+ "http://localhost:3000" //change this to your frontend url
21
+ ],
22
+ });
package/src/server.ts ADDED
@@ -0,0 +1,40 @@
1
+ import express from "express";
2
+ import { toNodeHandler, fromNodeHeaders } from "better-auth/node";
3
+ import cors from "cors"; // Import the CORS middleware
4
+ import { auth } from "./lib/auth";
5
+ const app = express();
6
+ const port = process.env.PORT
7
+
8
+ app.use(
9
+ cors({
10
+ origin: "http://localhost:3000", // Replace with your frontend's origin
11
+ methods: ["GET", "POST", "PUT", "DELETE"], // Specify allowed HTTP methods
12
+ credentials: true, // Allow credentials (cookies, authorization headers, etc.)
13
+ })
14
+ );
15
+
16
+ // app.all("/api/auth/*", toNodeHandler(auth)); // For ExpressJS v4
17
+ app.all("/api/auth/*splat", toNodeHandler(auth)); // For ExpressJS v5
18
+
19
+ // Mount express json middleware after Better Auth handler
20
+ // or only apply it to routes that don't interact with Better Auth
21
+
22
+ app.get("/api/me", async (req, res) => {
23
+ const session = await auth.api.getSession({
24
+ headers: fromNodeHeaders(req.headers),
25
+ });
26
+ return res.json(session);
27
+ });
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+ app.use(express.json());
38
+ app.listen(port, () => {
39
+ console.log(`Example app listening on port ${port}`);
40
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ // Visit https://aka.ms/tsconfig to read more about this file
3
+ "compilerOptions": {
4
+ // File Layout
5
+ "rootDir": "./src",
6
+ "outDir": "./dist",
7
+
8
+
9
+
10
+ // Environment Settings
11
+ // See also https://aka.ms/tsconfig/module
12
+ "module": "CommonJS",
13
+ "target": "ES2020",
14
+ "esModuleInterop": true,
15
+ "types": [],
16
+ // For nodejs:
17
+ // "lib": ["esnext"],
18
+ // "types": ["node"],
19
+ // and npm install -D @types/node
20
+
21
+ // Other Outputs
22
+ "sourceMap": true,
23
+ "declaration": true,
24
+ "declarationMap": true,
25
+
26
+ // Stricter Typechecking Options
27
+ "noUncheckedIndexedAccess": true,
28
+ "exactOptionalPropertyTypes": true,
29
+
30
+ // Style Options
31
+ // "noImplicitReturns": true,
32
+ // "noImplicitOverride": true,
33
+ // "noUnusedLocals": true,
34
+ // "noUnusedParameters": true,
35
+ // "noFallthroughCasesInSwitch": true,
36
+ // "noPropertyAccessFromIndexSignature": true,
37
+
38
+ // Recommended Options
39
+ "strict": true,
40
+ "jsx": "react-jsx",
41
+ "verbatimModuleSyntax": false,
42
+ "isolatedModules": true,
43
+ "noUncheckedSideEffectImports": true,
44
+ "moduleDetection": "force",
45
+ "skipLibCheck": true,
46
+ },
47
+ "include": ["src"],
48
+ "exclude": ["node_modules"],
49
+ }