create-stackkit-app 0.4.4 → 0.4.6
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/README.md +1 -1
- package/dist/index.js +61 -4
- package/dist/lib/code-generator.d.ts +80 -0
- package/dist/lib/code-generator.js +541 -0
- package/dist/lib/create-project.d.ts +20 -1
- package/dist/lib/create-project.js +154 -96
- package/dist/lib/framework-utils.d.ts +22 -0
- package/dist/lib/framework-utils.js +74 -0
- package/dist/lib/utils/logger.d.ts +16 -0
- package/dist/lib/utils/logger.js +59 -0
- package/dist/lib/utils/module-discovery.d.ts +62 -0
- package/dist/lib/utils/module-discovery.js +180 -0
- package/dist/lib/utils/package-utils.js +2 -2
- package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +6 -0
- package/modules/auth/authjs/files/lib/auth-client.ts +11 -0
- package/modules/auth/authjs/files/lib/auth.ts +36 -0
- package/modules/auth/authjs/files/schemas/prisma-schema.prisma +45 -0
- package/modules/auth/authjs/module.json +22 -0
- package/modules/auth/better-auth/files/lib/auth-client.ts +7 -0
- package/modules/auth/better-auth/files/lib/auth.ts +77 -1
- package/modules/auth/better-auth/files/lib/email-service.ts +34 -0
- package/modules/auth/better-auth/files/lib/email-templates.ts +89 -0
- package/modules/auth/better-auth/files/schemas/prisma-schema.prisma +7 -7
- package/modules/auth/better-auth/generator.json +83 -0
- package/modules/auth/better-auth/module.json +17 -34
- package/modules/database/mongoose/files/lib/db.ts +63 -0
- package/modules/database/{mongoose-mongodb → mongoose}/files/models/User.ts +0 -5
- package/modules/database/mongoose/generator.json +33 -0
- package/modules/database/mongoose/module.json +15 -0
- package/modules/database/prisma/files/lib/prisma.ts +7 -4
- package/modules/database/prisma/files/prisma/schema.prisma +1 -1
- package/modules/database/prisma/files/prisma.config.ts +2 -2
- package/modules/database/prisma/generator.json +46 -0
- package/modules/database/prisma/module.json +6 -132
- package/package.json +1 -1
- package/templates/express/.env.example +0 -1
- package/templates/express/package.json +4 -4
- package/templates/express/src/app.ts +2 -2
- package/templates/express/src/features/health/health.controller.ts +18 -0
- package/templates/express/src/features/health/health.route.ts +9 -0
- package/templates/express/src/features/health/health.service.ts +6 -0
- package/templates/express/template.json +6 -19
- package/templates/nextjs/lib/env.ts +8 -0
- package/templates/nextjs/package.json +7 -7
- package/templates/nextjs/template.json +5 -1
- package/templates/react-vite/.env.example +1 -2
- package/templates/react-vite/.prettierignore +4 -0
- package/templates/react-vite/.prettierrc +9 -0
- package/templates/react-vite/README.md +22 -0
- package/templates/react-vite/package.json +16 -16
- package/templates/react-vite/src/router.tsx +0 -12
- package/templates/react-vite/template.json +6 -14
- package/templates/react-vite/vite.config.ts +0 -6
- package/dist/lib/utils/config-utils.d.ts +0 -2
- package/dist/lib/utils/config-utils.js +0 -33
- package/dist/lib/utils/file-utils.d.ts +0 -8
- package/dist/lib/utils/file-utils.js +0 -75
- package/dist/lib/utils/module-utils.d.ts +0 -2
- package/dist/lib/utils/module-utils.js +0 -311
- package/modules/auth/clerk/files/express/auth.ts +0 -7
- package/modules/auth/clerk/files/nextjs/auth-provider.tsx +0 -5
- package/modules/auth/clerk/files/nextjs/middleware.ts +0 -9
- package/modules/auth/clerk/files/react/auth-provider.tsx +0 -15
- package/modules/auth/clerk/module.json +0 -115
- package/modules/database/mongoose-mongodb/files/lib/db.ts +0 -78
- package/modules/database/mongoose-mongodb/module.json +0 -70
- package/templates/express/src/features/auth/auth.controller.ts +0 -48
- package/templates/express/src/features/auth/auth.route.ts +0 -10
- package/templates/express/src/features/auth/auth.service.ts +0 -21
- package/templates/react-vite/src/api/services/user.service.ts +0 -18
- package/templates/react-vite/src/pages/UserProfile.tsx +0 -40
- package/templates/react-vite/src/types/user.d.ts +0 -6
|
@@ -14,6 +14,7 @@ A production-ready React starter template with TypeScript, Vite, and essential l
|
|
|
14
14
|
- **SEO Ready** with React Helmet Async
|
|
15
15
|
- **Error Boundaries** for graceful error handling
|
|
16
16
|
- **ESLint** for code quality
|
|
17
|
+
- **Prettier** for code formatting
|
|
17
18
|
- **Custom Hooks** included
|
|
18
19
|
|
|
19
20
|
## Quick Start
|
|
@@ -30,6 +31,18 @@ pnpm build
|
|
|
30
31
|
|
|
31
32
|
# Preview production build
|
|
32
33
|
pnpm preview
|
|
34
|
+
|
|
35
|
+
# Run linter
|
|
36
|
+
pnpm lint
|
|
37
|
+
|
|
38
|
+
# Fix linting issues
|
|
39
|
+
pnpm lint:fix
|
|
40
|
+
|
|
41
|
+
# Format code
|
|
42
|
+
pnpm format
|
|
43
|
+
|
|
44
|
+
# Check formatting
|
|
45
|
+
pnpm format:check
|
|
33
46
|
```
|
|
34
47
|
|
|
35
48
|
## Project Structure
|
|
@@ -44,6 +57,7 @@ src/
|
|
|
44
57
|
├── pages/ # Route pages
|
|
45
58
|
├── types/ # TypeScript types
|
|
46
59
|
├── utils/ # Helper functions
|
|
60
|
+
├── test/ # Test setup
|
|
47
61
|
├── App.tsx # Main app component
|
|
48
62
|
├── main.tsx # Entry point
|
|
49
63
|
└── index.css # Global styles
|
|
@@ -51,6 +65,14 @@ src/
|
|
|
51
65
|
|
|
52
66
|
## Environment Variables
|
|
53
67
|
|
|
68
|
+
Copy `.env.example` to `.env` and update the values:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cp .env.example .env
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Environment Variables
|
|
75
|
+
|
|
54
76
|
Create a `.env` file:
|
|
55
77
|
|
|
56
78
|
```env
|
|
@@ -12,33 +12,33 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@tailwindcss/vite": "^4.1.18",
|
|
15
|
-
"@tanstack/react-query": "^5.
|
|
16
|
-
"@tanstack/react-query-devtools": "^5.
|
|
17
|
-
"axios": "^1.
|
|
15
|
+
"@tanstack/react-query": "^5.90.16",
|
|
16
|
+
"@tanstack/react-query-devtools": "^5.91.2",
|
|
17
|
+
"axios": "^1.13.2",
|
|
18
18
|
"class-variance-authority": "^0.7.1",
|
|
19
19
|
"clsx": "^2.1.1",
|
|
20
|
-
"react": "^19.2.
|
|
21
|
-
"react-dom": "^19.2.
|
|
20
|
+
"react": "^19.2.3",
|
|
21
|
+
"react-dom": "^19.2.3",
|
|
22
22
|
"react-helmet-async": "^2.0.5",
|
|
23
|
-
"react-hot-toast": "^2.
|
|
23
|
+
"react-hot-toast": "^2.6.0",
|
|
24
24
|
"react-router": "^7.12.0",
|
|
25
25
|
"tailwind-merge": "^3.4.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@eslint/js": "^9.39.
|
|
29
|
-
"@types/node": "^
|
|
30
|
-
"@types/react": "^19.2.
|
|
28
|
+
"@eslint/js": "^9.39.2",
|
|
29
|
+
"@types/node": "^25.0.8",
|
|
30
|
+
"@types/react": "^19.2.8",
|
|
31
31
|
"@types/react-dom": "^19.2.3",
|
|
32
|
-
"@vitejs/plugin-react": "^5.1.
|
|
32
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
33
33
|
"autoprefixer": "^10.4.23",
|
|
34
|
-
"eslint": "^9.39.
|
|
34
|
+
"eslint": "^9.39.2",
|
|
35
35
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
36
|
-
"eslint-plugin-react-refresh": "^0.4.
|
|
37
|
-
"globals": "^
|
|
36
|
+
"eslint-plugin-react-refresh": "^0.4.26",
|
|
37
|
+
"globals": "^17.0.0",
|
|
38
38
|
"postcss": "^8.5.6",
|
|
39
39
|
"tailwindcss": "^4.1.18",
|
|
40
40
|
"typescript": "~5.9.3",
|
|
41
|
-
"typescript-eslint": "^8.
|
|
42
|
-
"vite": "^7.
|
|
41
|
+
"typescript-eslint": "^8.53.0",
|
|
42
|
+
"vite": "^7.3.1"
|
|
43
43
|
}
|
|
44
|
-
}
|
|
44
|
+
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { createBrowserRouter } from "react-router";
|
|
2
|
-
import { userService } from "./api/services/user.service";
|
|
3
2
|
import { ErrorBoundary } from "./components/ErrorBoundary";
|
|
4
3
|
import Layout from "./components/Layout";
|
|
5
4
|
import About from "./pages/About";
|
|
6
5
|
import Home from "./pages/Home";
|
|
7
6
|
import NotFound from "./pages/NotFound";
|
|
8
|
-
import UserProfile from "./pages/UserProfile";
|
|
9
7
|
|
|
10
8
|
export const router = createBrowserRouter([
|
|
11
9
|
{
|
|
@@ -15,16 +13,6 @@ export const router = createBrowserRouter([
|
|
|
15
13
|
children: [
|
|
16
14
|
{ index: true, Component: Home },
|
|
17
15
|
{ path: "about", Component: About },
|
|
18
|
-
{
|
|
19
|
-
path: "users/:userId",
|
|
20
|
-
loader: async ({ params }) => {
|
|
21
|
-
const id = params.userId;
|
|
22
|
-
if (!id) throw new Response("Missing user id", { status: 400 });
|
|
23
|
-
const user = await userService.getUser(id);
|
|
24
|
-
return user;
|
|
25
|
-
},
|
|
26
|
-
Component: UserProfile,
|
|
27
|
-
},
|
|
28
16
|
{ path: "*", Component: NotFound },
|
|
29
17
|
],
|
|
30
18
|
},
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "react-vite
|
|
2
|
+
"name": "react-vite",
|
|
3
3
|
"displayName": "React (Vite)",
|
|
4
4
|
"framework": "react-vite",
|
|
5
5
|
"description": "Production-ready React 19 + Vite with TypeScript, Router, TanStack Query, and more",
|
|
6
|
+
"compatibility": {
|
|
7
|
+
"databases": [],
|
|
8
|
+
"auth": ["better-auth"]
|
|
9
|
+
},
|
|
6
10
|
"files": [
|
|
7
11
|
"src/",
|
|
8
12
|
"public/",
|
|
@@ -30,17 +34,5 @@
|
|
|
30
34
|
"lint": "eslint .",
|
|
31
35
|
"lint:fix": "eslint . --fix",
|
|
32
36
|
"preview": "vite preview"
|
|
33
|
-
}
|
|
34
|
-
"fileReplacements": [
|
|
35
|
-
{
|
|
36
|
-
"file": "index.html",
|
|
37
|
-
"from": "/src/main.tsx",
|
|
38
|
-
"to": "/src/main.jsx"
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"file": "vite.config.ts",
|
|
42
|
-
"from": "main.tsx",
|
|
43
|
-
"to": "main.jsx"
|
|
44
|
-
}
|
|
45
|
-
]
|
|
37
|
+
}
|
|
46
38
|
}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import tailwindcss from "@tailwindcss/vite";
|
|
2
2
|
import react from "@vitejs/plugin-react";
|
|
3
|
-
import path from "path";
|
|
4
3
|
import { defineConfig } from "vite";
|
|
5
4
|
|
|
6
5
|
export default defineConfig({
|
|
7
6
|
plugins: [react(), tailwindcss()],
|
|
8
|
-
resolve: {
|
|
9
|
-
alias: {
|
|
10
|
-
"@": path.resolve(__dirname, "./src"),
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
7
|
});
|
|
@@ -1,33 +0,0 @@
|
|
|
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
|
-
exports.deepMerge = deepMerge;
|
|
7
|
-
exports.applyFrameworkPatches = applyFrameworkPatches;
|
|
8
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
-
const path_1 = require("path");
|
|
10
|
-
function deepMerge(target, source) {
|
|
11
|
-
const result = { ...target };
|
|
12
|
-
for (const key in source) {
|
|
13
|
-
if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
|
|
14
|
-
result[key] = deepMerge(result[key] || {}, source[key]);
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
result[key] = source[key];
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return result;
|
|
21
|
-
}
|
|
22
|
-
async function applyFrameworkPatches(targetDir, patches) {
|
|
23
|
-
for (const [filename, patchConfig] of Object.entries(patches)) {
|
|
24
|
-
const filePath = (0, path_1.join)(targetDir, filename);
|
|
25
|
-
if (await fs_extra_1.default.pathExists(filePath)) {
|
|
26
|
-
const fileContent = await fs_extra_1.default.readJson(filePath);
|
|
27
|
-
if (patchConfig && typeof patchConfig === "object" && "merge" in patchConfig) {
|
|
28
|
-
const merged = deepMerge(fileContent, patchConfig.merge);
|
|
29
|
-
await fs_extra_1.default.writeJson(filePath, merged, { spaces: 2 });
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export interface PackageJsonConfig {
|
|
2
|
-
dependencies?: Record<string, string>;
|
|
3
|
-
devDependencies?: Record<string, string>;
|
|
4
|
-
scripts?: Record<string, string>;
|
|
5
|
-
}
|
|
6
|
-
export declare function copyBaseFramework(templatesDir: string, targetDir: string, framework: string): Promise<void>;
|
|
7
|
-
export declare function mergePackageJson(targetDir: string, config: PackageJsonConfig): Promise<void>;
|
|
8
|
-
export declare function mergeEnvFile(targetDir: string, envVars: Record<string, string>): Promise<void>;
|
|
@@ -1,75 +0,0 @@
|
|
|
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
|
-
exports.copyBaseFramework = copyBaseFramework;
|
|
7
|
-
exports.mergePackageJson = mergePackageJson;
|
|
8
|
-
exports.mergeEnvFile = mergeEnvFile;
|
|
9
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
-
const path_1 = __importDefault(require("path"));
|
|
11
|
-
async function copyBaseFramework(templatesDir, targetDir, framework) {
|
|
12
|
-
const baseDir = path_1.default.join(templatesDir, framework);
|
|
13
|
-
if (!(await fs_extra_1.default.pathExists(baseDir))) {
|
|
14
|
-
throw new Error(`Base template not found for framework: ${framework}\n` + `Expected at: ${baseDir}`);
|
|
15
|
-
}
|
|
16
|
-
await fs_extra_1.default.copy(baseDir, targetDir, {
|
|
17
|
-
filter: (src) => {
|
|
18
|
-
const basename = path_1.default.basename(src);
|
|
19
|
-
return !["template.json", "config.json", "node_modules", ".git"].includes(basename);
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
async function mergePackageJson(targetDir, config) {
|
|
24
|
-
const pkgPath = path_1.default.join(targetDir, "package.json");
|
|
25
|
-
if (!(await fs_extra_1.default.pathExists(pkgPath))) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
const pkg = await fs_extra_1.default.readJson(pkgPath);
|
|
29
|
-
if (config.dependencies) {
|
|
30
|
-
pkg.dependencies = { ...pkg.dependencies, ...config.dependencies };
|
|
31
|
-
}
|
|
32
|
-
if (config.devDependencies) {
|
|
33
|
-
pkg.devDependencies = { ...pkg.devDependencies, ...config.devDependencies };
|
|
34
|
-
}
|
|
35
|
-
if (config.scripts) {
|
|
36
|
-
pkg.scripts = { ...pkg.scripts, ...config.scripts };
|
|
37
|
-
}
|
|
38
|
-
await fs_extra_1.default.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
39
|
-
}
|
|
40
|
-
async function mergeEnvFile(targetDir, envVars) {
|
|
41
|
-
if (Object.keys(envVars).length === 0) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
const envExamplePath = path_1.default.join(targetDir, ".env.example");
|
|
45
|
-
const envPath = path_1.default.join(targetDir, ".env");
|
|
46
|
-
const envContent = Object.entries(envVars)
|
|
47
|
-
.map(([key, value]) => `${key}="${value}"`)
|
|
48
|
-
.join("\n") + "\n";
|
|
49
|
-
// Update .env.example
|
|
50
|
-
if (await fs_extra_1.default.pathExists(envExamplePath)) {
|
|
51
|
-
const existing = await fs_extra_1.default.readFile(envExamplePath, "utf-8");
|
|
52
|
-
const existingKeys = existing.split("\n").map((line) => line.split("=")[0]);
|
|
53
|
-
const newVars = Object.keys(envVars).filter((key) => !existingKeys.includes(key));
|
|
54
|
-
if (newVars.length > 0) {
|
|
55
|
-
const newContent = newVars.map((key) => `${key}="${envVars[key]}"`).join("\n");
|
|
56
|
-
await fs_extra_1.default.appendFile(envExamplePath, "\n" + newContent + "\n");
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
await fs_extra_1.default.writeFile(envExamplePath, envContent);
|
|
61
|
-
}
|
|
62
|
-
// Update .env (create if doesn't exist, or append new vars if it does)
|
|
63
|
-
if (await fs_extra_1.default.pathExists(envPath)) {
|
|
64
|
-
const existing = await fs_extra_1.default.readFile(envPath, "utf-8");
|
|
65
|
-
const existingKeys = existing.split("\n").map((line) => line.split("=")[0]);
|
|
66
|
-
const newVars = Object.keys(envVars).filter((key) => !existingKeys.includes(key));
|
|
67
|
-
if (newVars.length > 0) {
|
|
68
|
-
const newContent = newVars.map((key) => `${key}="${envVars[key]}"`).join("\n");
|
|
69
|
-
await fs_extra_1.default.appendFile(envPath, "\n" + newContent + "\n");
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
await fs_extra_1.default.writeFile(envPath, envContent);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
export declare function mergeDatabaseConfig(templatesDir: string, targetDir: string, database: string, framework: string, dbProvider?: string): Promise<string[]>;
|
|
2
|
-
export declare function mergeAuthConfig(templatesDir: string, targetDir: string, framework: string, auth: string, database?: string, dbProvider?: string): Promise<void>;
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.mergeDatabaseConfig = mergeDatabaseConfig;
|
|
40
|
-
exports.mergeAuthConfig = mergeAuthConfig;
|
|
41
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
42
|
-
const path_1 = __importStar(require("path"));
|
|
43
|
-
const config_utils_1 = require("./config-utils");
|
|
44
|
-
const file_utils_1 = require("./file-utils");
|
|
45
|
-
async function mergeDatabaseConfig(templatesDir, targetDir, database, framework, dbProvider) {
|
|
46
|
-
const modulesDir = (0, path_1.join)(templatesDir, "..", "modules");
|
|
47
|
-
const dbModulePath = (0, path_1.join)(modulesDir, "database", database);
|
|
48
|
-
if (!(await fs_extra_1.default.pathExists(dbModulePath))) {
|
|
49
|
-
// eslint-disable-next-line no-console
|
|
50
|
-
console.warn(`Database module not found: ${database}`);
|
|
51
|
-
return [];
|
|
52
|
-
}
|
|
53
|
-
// Read module.json
|
|
54
|
-
const moduleJsonPath = (0, path_1.join)(dbModulePath, "module.json");
|
|
55
|
-
if (!(await fs_extra_1.default.pathExists(moduleJsonPath))) {
|
|
56
|
-
return [];
|
|
57
|
-
}
|
|
58
|
-
const moduleData = await fs_extra_1.default.readJson(moduleJsonPath);
|
|
59
|
-
const variables = {};
|
|
60
|
-
if (dbProvider) {
|
|
61
|
-
variables.provider = dbProvider;
|
|
62
|
-
if (dbProvider === "postgresql") {
|
|
63
|
-
variables.connectionString = "postgresql://user:password@localhost:5432/mydb?schema=public";
|
|
64
|
-
variables.prismaClientInit = `
|
|
65
|
-
import { PrismaPg } from "@prisma/adapter-pg";
|
|
66
|
-
|
|
67
|
-
const globalForPrisma = global as unknown as {
|
|
68
|
-
prisma: PrismaClient | undefined;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const adapter = new PrismaPg({
|
|
72
|
-
connectionString: process.env.DATABASE_URL!,
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const prisma = globalForPrisma.prisma ?? new PrismaClient({
|
|
76
|
-
adapter,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
|
|
80
|
-
`;
|
|
81
|
-
}
|
|
82
|
-
else if (dbProvider === "mongodb") {
|
|
83
|
-
variables.connectionString = "mongodb+srv://username:password@cluster.mongodb.net/mydb";
|
|
84
|
-
variables.prismaClientInit = `
|
|
85
|
-
const prisma = new PrismaClient()
|
|
86
|
-
`;
|
|
87
|
-
}
|
|
88
|
-
else if (dbProvider === "mysql") {
|
|
89
|
-
variables.connectionString = "mysql://user:password@localhost:3306/mydb";
|
|
90
|
-
variables.prismaClientInit = `
|
|
91
|
-
import { PrismaMariaDb } from '@prisma/adapter-mariadb';
|
|
92
|
-
|
|
93
|
-
const adapter = new PrismaMariaDb({
|
|
94
|
-
host: process.env.DATABASE_HOST,
|
|
95
|
-
user: process.env.DATABASE_USER,
|
|
96
|
-
password: process.env.DATABASE_PASSWORD,
|
|
97
|
-
database: process.env.DATABASE_NAME,
|
|
98
|
-
connectionLimit: 5
|
|
99
|
-
});
|
|
100
|
-
const prisma = new PrismaClient({ adapter });
|
|
101
|
-
`;
|
|
102
|
-
}
|
|
103
|
-
else if (dbProvider === "sqlite") {
|
|
104
|
-
variables.connectionString = "file:./dev.db";
|
|
105
|
-
variables.prismaClientInit = `
|
|
106
|
-
import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
|
|
107
|
-
|
|
108
|
-
const adapter = new PrismaBetterSqlite3({ url: process.env.DATABASE_URL });
|
|
109
|
-
const prisma = new PrismaClient({ adapter });
|
|
110
|
-
`;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
const filesDir = (0, path_1.join)(dbModulePath, "files");
|
|
114
|
-
if (await fs_extra_1.default.pathExists(filesDir)) {
|
|
115
|
-
const libDir = framework === "nextjs" ? "lib" : "src";
|
|
116
|
-
for (const patch of moduleData.patches || []) {
|
|
117
|
-
if (patch.type === "create-file") {
|
|
118
|
-
const sourceFile = (0, path_1.join)(filesDir, patch.source);
|
|
119
|
-
let destFile = (0, path_1.join)(targetDir, patch.destination);
|
|
120
|
-
destFile = destFile
|
|
121
|
-
.replace("{{lib}}", libDir)
|
|
122
|
-
.replace("{{src}}", "src")
|
|
123
|
-
.replace("{{models}}", framework === "nextjs" ? "models" : "src/models");
|
|
124
|
-
if (await fs_extra_1.default.pathExists(sourceFile)) {
|
|
125
|
-
await fs_extra_1.default.ensureDir((0, path_1.join)(destFile, ".."));
|
|
126
|
-
// Check if text file
|
|
127
|
-
const ext = path_1.default.extname(sourceFile);
|
|
128
|
-
if ([".ts", ".js", ".prisma", ".json"].includes(ext)) {
|
|
129
|
-
let content = await fs_extra_1.default.readFile(sourceFile, "utf-8");
|
|
130
|
-
for (const [key, value] of Object.entries(variables)) {
|
|
131
|
-
content = content.replace(new RegExp(`{{${key}}}`, "g"), value);
|
|
132
|
-
}
|
|
133
|
-
await fs_extra_1.default.writeFile(destFile, content);
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
await fs_extra_1.default.copy(sourceFile, destFile, { overwrite: false });
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
const dependencies = {
|
|
143
|
-
...moduleData.dependencies.common,
|
|
144
|
-
...(dbProvider ? moduleData.dependencies.providers[dbProvider] : {}),
|
|
145
|
-
};
|
|
146
|
-
const devDependencies = {
|
|
147
|
-
...moduleData.devDependencies.common,
|
|
148
|
-
...(dbProvider ? moduleData.devDependencies.providers[dbProvider] : {}),
|
|
149
|
-
};
|
|
150
|
-
await (0, file_utils_1.mergePackageJson)(targetDir, {
|
|
151
|
-
dependencies,
|
|
152
|
-
devDependencies,
|
|
153
|
-
});
|
|
154
|
-
const envVars = {};
|
|
155
|
-
const commonEnvVars = Array.isArray(moduleData.envVars) ? moduleData.envVars : moduleData.envVars?.common || [];
|
|
156
|
-
const providerEnvVars = dbProvider && moduleData.envVars?.providers?.[dbProvider] ? moduleData.envVars.providers[dbProvider] : [];
|
|
157
|
-
const allEnvVars = [...commonEnvVars, ...providerEnvVars];
|
|
158
|
-
for (const envVar of allEnvVars) {
|
|
159
|
-
let value = envVar.value;
|
|
160
|
-
for (const [key, val] of Object.entries(variables)) {
|
|
161
|
-
value = value.replace(new RegExp(`{{${key}}}`, "g"), val);
|
|
162
|
-
}
|
|
163
|
-
envVars[envVar.key] = value;
|
|
164
|
-
}
|
|
165
|
-
await (0, file_utils_1.mergeEnvFile)(targetDir, envVars);
|
|
166
|
-
if (moduleData.frameworkPatches) {
|
|
167
|
-
const frameworkKey = framework === "react-vite" ? "react" : framework;
|
|
168
|
-
const patches = moduleData.frameworkPatches[frameworkKey];
|
|
169
|
-
if (patches) {
|
|
170
|
-
await (0, config_utils_1.applyFrameworkPatches)(targetDir, patches);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return moduleData.postInstall || [];
|
|
174
|
-
}
|
|
175
|
-
async function mergeAuthConfig(templatesDir, targetDir, framework, auth, database = "none", dbProvider) {
|
|
176
|
-
const modulesDir = (0, path_1.join)(templatesDir, "..", "modules");
|
|
177
|
-
const authKey = auth;
|
|
178
|
-
const authModulePath = (0, path_1.join)(modulesDir, "auth", authKey);
|
|
179
|
-
if (!(await fs_extra_1.default.pathExists(authModulePath))) {
|
|
180
|
-
// eslint-disable-next-line no-console
|
|
181
|
-
console.warn(`Auth module not found: ${authKey}`);
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
// Read module.json
|
|
185
|
-
const moduleJsonPath = (0, path_1.join)(authModulePath, "module.json");
|
|
186
|
-
if (!(await fs_extra_1.default.pathExists(moduleJsonPath))) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
const moduleData = await fs_extra_1.default.readJson(moduleJsonPath);
|
|
190
|
-
if (moduleData.supportedFrameworks && !moduleData.supportedFrameworks.includes(framework)) {
|
|
191
|
-
// eslint-disable-next-line no-console
|
|
192
|
-
console.warn(`Auth ${authKey} does not support framework ${framework}`);
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
let frameworkConfig = null;
|
|
196
|
-
if (moduleData.frameworkConfigs) {
|
|
197
|
-
frameworkConfig = moduleData.frameworkConfigs[framework];
|
|
198
|
-
if (!frameworkConfig) {
|
|
199
|
-
// eslint-disable-next-line no-console
|
|
200
|
-
console.warn(`No config for framework ${framework} in ${authKey}`);
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
const variables = {};
|
|
205
|
-
if (framework === "nextjs") {
|
|
206
|
-
variables.dbImport = "@/lib/db";
|
|
207
|
-
}
|
|
208
|
-
else if (framework === "express") {
|
|
209
|
-
variables.dbImport = "../db";
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
variables.dbImport = "../db";
|
|
213
|
-
}
|
|
214
|
-
const filesDir = (0, path_1.join)(authModulePath, "files");
|
|
215
|
-
if (await fs_extra_1.default.pathExists(filesDir)) {
|
|
216
|
-
const getReplacements = () => {
|
|
217
|
-
if (framework === "nextjs") {
|
|
218
|
-
return { lib: "lib", router: "app" };
|
|
219
|
-
}
|
|
220
|
-
else if (framework === "express") {
|
|
221
|
-
return { lib: "src", router: "src" };
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
return { lib: "src", router: "src" };
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
const replacements = getReplacements();
|
|
228
|
-
const patches = frameworkConfig?.patches || moduleData.patches || [];
|
|
229
|
-
for (const patch of patches) {
|
|
230
|
-
if (patch.type === "create-file") {
|
|
231
|
-
const sourceFile = (0, path_1.join)(filesDir, patch.source);
|
|
232
|
-
let destFile = (0, path_1.join)(targetDir, patch.destination);
|
|
233
|
-
destFile = destFile
|
|
234
|
-
.replace("{{lib}}", replacements.lib)
|
|
235
|
-
.replace("{{router}}", replacements.router);
|
|
236
|
-
if (await fs_extra_1.default.pathExists(sourceFile)) {
|
|
237
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(destFile));
|
|
238
|
-
// Check if text file
|
|
239
|
-
const ext = path_1.default.extname(sourceFile);
|
|
240
|
-
if ([".ts", ".js", ".json"].includes(ext)) {
|
|
241
|
-
let content = await fs_extra_1.default.readFile(sourceFile, "utf-8");
|
|
242
|
-
for (const [key, value] of Object.entries(variables)) {
|
|
243
|
-
content = content.replace(new RegExp(`{{${key}}}`, "g"), value);
|
|
244
|
-
}
|
|
245
|
-
await fs_extra_1.default.writeFile(destFile, content);
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
await fs_extra_1.default.copy(sourceFile, destFile, { overwrite: false });
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
// Add framework-specific patches
|
|
255
|
-
if (framework === "nextjs") {
|
|
256
|
-
const apiSource = (0, path_1.join)(filesDir, "api/auth/[...all]/route.ts");
|
|
257
|
-
const apiDest = (0, path_1.join)(targetDir, "app/api/auth/[...all]/route.ts");
|
|
258
|
-
if (await fs_extra_1.default.pathExists(apiSource)) {
|
|
259
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(apiDest));
|
|
260
|
-
await fs_extra_1.default.copy(apiSource, apiDest, { overwrite: false });
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
if (database !== "none" && moduleData.databaseAdapters) {
|
|
264
|
-
let adapterKey = database;
|
|
265
|
-
if (database === "prisma" && dbProvider) {
|
|
266
|
-
adapterKey = `prisma-${dbProvider}`;
|
|
267
|
-
}
|
|
268
|
-
const adapterConfig = moduleData.databaseAdapters[adapterKey];
|
|
269
|
-
if (adapterConfig) {
|
|
270
|
-
variables.databaseAdapter = adapterConfig.adapterCode;
|
|
271
|
-
if (adapterConfig.schema && adapterConfig.schemaDestination) {
|
|
272
|
-
const schemaSource = (0, path_1.join)(authModulePath, adapterConfig.schema);
|
|
273
|
-
const schemaDest = (0, path_1.join)(targetDir, adapterConfig.schemaDestination);
|
|
274
|
-
if (await fs_extra_1.default.pathExists(schemaSource)) {
|
|
275
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(schemaDest));
|
|
276
|
-
let content = await fs_extra_1.default.readFile(schemaSource, "utf-8");
|
|
277
|
-
// Set schema variables
|
|
278
|
-
if (dbProvider === "postgresql") {
|
|
279
|
-
variables.provider = "postgresql";
|
|
280
|
-
variables.idDefault = "@default(cuid())";
|
|
281
|
-
variables.userIdType = "";
|
|
282
|
-
}
|
|
283
|
-
else if (dbProvider === "mongodb") {
|
|
284
|
-
variables.provider = "mongodb";
|
|
285
|
-
variables.idDefault = '@default(auto()) @map("_id") @db.ObjectId';
|
|
286
|
-
variables.userIdType = "@db.ObjectId";
|
|
287
|
-
}
|
|
288
|
-
for (const [key, value] of Object.entries(variables)) {
|
|
289
|
-
content = content.replace(new RegExp(`{{${key}}}`, "g"), value);
|
|
290
|
-
}
|
|
291
|
-
await fs_extra_1.default.writeFile(schemaDest, content, { flag: "a" }); // append
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
if (adapterConfig.dependencies) {
|
|
295
|
-
await (0, file_utils_1.mergePackageJson)(targetDir, {
|
|
296
|
-
dependencies: adapterConfig.dependencies,
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
await (0, file_utils_1.mergePackageJson)(targetDir, {
|
|
302
|
-
dependencies: frameworkConfig?.dependencies || moduleData.dependencies,
|
|
303
|
-
devDependencies: frameworkConfig?.devDependencies || moduleData.devDependencies,
|
|
304
|
-
});
|
|
305
|
-
const envVars = {};
|
|
306
|
-
const envVarList = frameworkConfig?.envVars || moduleData.envVars || [];
|
|
307
|
-
for (const envVar of envVarList) {
|
|
308
|
-
envVars[envVar.key] = envVar.value;
|
|
309
|
-
}
|
|
310
|
-
await (0, file_utils_1.mergeEnvFile)(targetDir, envVars);
|
|
311
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { ClerkProvider } from "@clerk/clerk-react";
|
|
2
|
-
|
|
3
|
-
const publishableKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY;
|
|
4
|
-
|
|
5
|
-
if (!publishableKey) {
|
|
6
|
-
throw new Error("Missing Publishable Key");
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|
10
|
-
return (
|
|
11
|
-
<ClerkProvider publishableKey={publishableKey} afterSignOutUrl="/">
|
|
12
|
-
{children}
|
|
13
|
-
</ClerkProvider>
|
|
14
|
-
);
|
|
15
|
-
}
|