create-stackkit-app 0.1.5 → 0.3.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/README.md +46 -31
- package/dist/index.js +4 -12
- package/dist/index.js.map +1 -1
- package/dist/lib/create-project.d.ts +2 -0
- package/dist/lib/create-project.d.ts.map +1 -0
- package/dist/lib/create-project.js +380 -0
- package/dist/lib/create-project.js.map +1 -0
- package/dist/lib/template-composer.d.ts +17 -0
- package/dist/lib/template-composer.d.ts.map +1 -0
- package/dist/lib/template-composer.js +199 -0
- package/dist/lib/template-composer.js.map +1 -0
- package/package.json +17 -5
- package/templates/auth/better-auth-express/config.json +18 -0
- package/templates/auth/better-auth-express/src/lib/auth.ts +12 -0
- package/templates/auth/better-auth-express/src/routes/auth.ts +10 -0
- package/templates/auth/better-auth-nextjs/app/api/auth/[...all]/route.ts +4 -0
- package/templates/auth/better-auth-nextjs/config.json +18 -0
- package/templates/auth/better-auth-nextjs/lib/auth.ts +14 -0
- package/templates/auth/nextauth/app/api/auth/[...nextauth]/route.ts +3 -0
- package/templates/auth/nextauth/config.json +18 -0
- package/templates/auth/nextauth/lib/auth.ts +31 -0
- package/templates/bases/express-base/.env.example +2 -0
- package/templates/bases/express-base/package.json +23 -0
- package/templates/bases/express-base/src/index.ts +27 -0
- package/templates/bases/express-base/template.json +7 -0
- package/templates/bases/express-base/tsconfig.json +17 -0
- package/templates/bases/nextjs-base/.eslintrc.json +3 -0
- package/templates/bases/nextjs-base/app/globals.css +3 -0
- package/templates/bases/nextjs-base/app/layout.tsx +19 -0
- package/templates/bases/nextjs-base/app/page.tsx +8 -0
- package/templates/bases/nextjs-base/next.config.ts +5 -0
- package/templates/bases/nextjs-base/package.json +24 -0
- package/templates/bases/nextjs-base/template.json +7 -0
- package/templates/bases/nextjs-base/tsconfig.json +27 -0
- package/templates/databases/prisma-mongodb/config.json +21 -0
- package/templates/databases/prisma-mongodb/lib/db.ts +13 -0
- package/templates/databases/prisma-mongodb/prisma/schema.prisma +16 -0
- package/templates/databases/prisma-postgresql/config.json +22 -0
- package/templates/databases/prisma-postgresql/lib/db.ts +13 -0
- package/templates/databases/prisma-postgresql/prisma/schema.prisma +16 -0
- package/src/index.ts +0 -21
- package/tsconfig.json +0 -9
|
@@ -0,0 +1,199 @@
|
|
|
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.TemplateComposer = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
class TemplateComposer {
|
|
10
|
+
templatesDir;
|
|
11
|
+
constructor(templatesDir) {
|
|
12
|
+
this.templatesDir = templatesDir;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Compose a project from base + database + auth selections
|
|
16
|
+
*/
|
|
17
|
+
async compose(targetDir, framework, database, auth) {
|
|
18
|
+
const configs = [];
|
|
19
|
+
const filesToCopy = [];
|
|
20
|
+
// 1. Load base framework template
|
|
21
|
+
const baseConfig = await this.loadConfig(path_1.default.join(this.templatesDir, 'bases', `${framework}-base`));
|
|
22
|
+
configs.push(baseConfig);
|
|
23
|
+
// Copy base files
|
|
24
|
+
const baseFiles = await this.getBaseFiles(framework);
|
|
25
|
+
filesToCopy.push(...baseFiles);
|
|
26
|
+
// 2. Load database configuration if not "none"
|
|
27
|
+
if (database !== 'none') {
|
|
28
|
+
const dbConfig = await this.loadConfig(path_1.default.join(this.templatesDir, 'databases', database));
|
|
29
|
+
// Check compatibility
|
|
30
|
+
if (dbConfig.compatibleWith?.frameworks &&
|
|
31
|
+
!dbConfig.compatibleWith.frameworks.includes(framework)) {
|
|
32
|
+
throw new Error(`${dbConfig.displayName} is not compatible with ${framework}`);
|
|
33
|
+
}
|
|
34
|
+
configs.push(dbConfig);
|
|
35
|
+
// Copy database files
|
|
36
|
+
const dbDir = path_1.default.join(this.templatesDir, 'databases', database);
|
|
37
|
+
const dbFiles = await this.collectFiles(dbDir);
|
|
38
|
+
filesToCopy.push(...dbFiles.map((f) => ({
|
|
39
|
+
source: f,
|
|
40
|
+
dest: path_1.default.join(targetDir, f.replace(dbDir + path_1.default.sep, '')),
|
|
41
|
+
})));
|
|
42
|
+
}
|
|
43
|
+
// 3. Load auth configuration if not "none"
|
|
44
|
+
if (auth !== 'none') {
|
|
45
|
+
const authKey = this.getAuthKey(framework, auth);
|
|
46
|
+
const authDir = path_1.default.join(this.templatesDir, 'auth', authKey);
|
|
47
|
+
if (await fs_extra_1.default.pathExists(authDir)) {
|
|
48
|
+
const authConfig = await this.loadConfig(authDir);
|
|
49
|
+
// Check compatibility
|
|
50
|
+
if (authConfig.compatibleWith?.frameworks &&
|
|
51
|
+
!authConfig.compatibleWith.frameworks.includes(framework)) {
|
|
52
|
+
throw new Error(`${authConfig.displayName} is not compatible with ${framework}`);
|
|
53
|
+
}
|
|
54
|
+
if (authConfig.compatibleWith?.databases &&
|
|
55
|
+
!authConfig.compatibleWith.databases.includes(database)) {
|
|
56
|
+
throw new Error(`${authConfig.displayName} is not compatible with ${database}`);
|
|
57
|
+
}
|
|
58
|
+
configs.push(authConfig);
|
|
59
|
+
// Copy auth files
|
|
60
|
+
const authFiles = await this.collectFiles(authDir);
|
|
61
|
+
filesToCopy.push(...authFiles.map((f) => ({
|
|
62
|
+
source: f,
|
|
63
|
+
dest: path_1.default.join(targetDir, f.replace(authDir + path_1.default.sep, '')),
|
|
64
|
+
})));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// 4. Merge all configurations
|
|
68
|
+
const mergedConfig = this.mergeConfigs(configs);
|
|
69
|
+
// 5. Copy all files
|
|
70
|
+
await this.copyFiles(filesToCopy);
|
|
71
|
+
// 6. Create/update package.json
|
|
72
|
+
await this.writePackageJson(targetDir, mergedConfig);
|
|
73
|
+
// 7. Create/update .env
|
|
74
|
+
await this.writeEnvFile(targetDir, mergedConfig);
|
|
75
|
+
}
|
|
76
|
+
async loadConfig(dir) {
|
|
77
|
+
const configPath = path_1.default.join(dir, 'config.json');
|
|
78
|
+
const templatePath = path_1.default.join(dir, 'template.json');
|
|
79
|
+
if (await fs_extra_1.default.pathExists(configPath)) {
|
|
80
|
+
return await fs_extra_1.default.readJson(configPath);
|
|
81
|
+
}
|
|
82
|
+
else if (await fs_extra_1.default.pathExists(templatePath)) {
|
|
83
|
+
return await fs_extra_1.default.readJson(templatePath);
|
|
84
|
+
}
|
|
85
|
+
throw new Error(`No configuration found in ${dir}`);
|
|
86
|
+
}
|
|
87
|
+
async getBaseFiles(framework) {
|
|
88
|
+
// For now, use existing complete template
|
|
89
|
+
// In future, this will use minimal base templates
|
|
90
|
+
const baseDir = path_1.default.join(this.templatesDir, 'next-prisma-postgres-shadcn');
|
|
91
|
+
const files = await this.collectFiles(baseDir);
|
|
92
|
+
return files.map((source) => ({
|
|
93
|
+
source,
|
|
94
|
+
dest: source.replace(baseDir, ''),
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
async collectFiles(dir, exclude = ['config.json', 'template.json', 'node_modules']) {
|
|
98
|
+
const files = [];
|
|
99
|
+
if (!(await fs_extra_1.default.pathExists(dir))) {
|
|
100
|
+
return files;
|
|
101
|
+
}
|
|
102
|
+
const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true });
|
|
103
|
+
for (const entry of entries) {
|
|
104
|
+
if (exclude.includes(entry.name))
|
|
105
|
+
continue;
|
|
106
|
+
const fullPath = path_1.default.join(dir, entry.name);
|
|
107
|
+
if (entry.isDirectory()) {
|
|
108
|
+
const subFiles = await this.collectFiles(fullPath, exclude);
|
|
109
|
+
files.push(...subFiles);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
files.push(fullPath);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return files;
|
|
116
|
+
}
|
|
117
|
+
async copyFiles(files) {
|
|
118
|
+
for (const { source, dest } of files) {
|
|
119
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(dest));
|
|
120
|
+
await fs_extra_1.default.copy(source, dest, { overwrite: true });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
mergeConfigs(configs) {
|
|
124
|
+
return configs.reduce((merged, config) => {
|
|
125
|
+
return {
|
|
126
|
+
...merged,
|
|
127
|
+
dependencies: {
|
|
128
|
+
...merged.dependencies,
|
|
129
|
+
...config.dependencies,
|
|
130
|
+
},
|
|
131
|
+
devDependencies: {
|
|
132
|
+
...merged.devDependencies,
|
|
133
|
+
...config.devDependencies,
|
|
134
|
+
},
|
|
135
|
+
scripts: {
|
|
136
|
+
...merged.scripts,
|
|
137
|
+
...config.scripts,
|
|
138
|
+
},
|
|
139
|
+
env: {
|
|
140
|
+
...merged.env,
|
|
141
|
+
...config.env,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}, {});
|
|
145
|
+
}
|
|
146
|
+
async writePackageJson(targetDir, config) {
|
|
147
|
+
const pkgPath = path_1.default.join(targetDir, 'package.json');
|
|
148
|
+
let pkg = {};
|
|
149
|
+
if (await fs_extra_1.default.pathExists(pkgPath)) {
|
|
150
|
+
pkg = await fs_extra_1.default.readJson(pkgPath);
|
|
151
|
+
}
|
|
152
|
+
// Merge dependencies and scripts
|
|
153
|
+
if (config.dependencies) {
|
|
154
|
+
pkg.dependencies = { ...pkg.dependencies, ...config.dependencies };
|
|
155
|
+
}
|
|
156
|
+
if (config.devDependencies) {
|
|
157
|
+
pkg.devDependencies = { ...pkg.devDependencies, ...config.devDependencies };
|
|
158
|
+
}
|
|
159
|
+
if (config.scripts) {
|
|
160
|
+
pkg.scripts = { ...pkg.scripts, ...config.scripts };
|
|
161
|
+
}
|
|
162
|
+
await fs_extra_1.default.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
163
|
+
}
|
|
164
|
+
async writeEnvFile(targetDir, config) {
|
|
165
|
+
if (!config.env || Object.keys(config.env).length === 0) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const envPath = path_1.default.join(targetDir, '.env');
|
|
169
|
+
const envExamplePath = path_1.default.join(targetDir, '.env.example');
|
|
170
|
+
const envContent = Object.entries(config.env)
|
|
171
|
+
.map(([key, value]) => `${key}="${value}"`)
|
|
172
|
+
.join('\n') + '\n';
|
|
173
|
+
// Append or create .env.example
|
|
174
|
+
if (await fs_extra_1.default.pathExists(envExamplePath)) {
|
|
175
|
+
const existing = await fs_extra_1.default.readFile(envExamplePath, 'utf-8');
|
|
176
|
+
if (!existing.includes(envContent)) {
|
|
177
|
+
await fs_extra_1.default.appendFile(envExamplePath, '\n' + envContent);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
await fs_extra_1.default.writeFile(envExamplePath, envContent);
|
|
182
|
+
}
|
|
183
|
+
// Don't overwrite existing .env, but create if missing
|
|
184
|
+
if (!(await fs_extra_1.default.pathExists(envPath))) {
|
|
185
|
+
await fs_extra_1.default.writeFile(envPath, envContent);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
getAuthKey(framework, auth) {
|
|
189
|
+
// Map framework + auth to specific implementation
|
|
190
|
+
const mapping = {
|
|
191
|
+
'nextjs-nextauth': 'nextauth',
|
|
192
|
+
'nextjs-better-auth': 'better-auth-nextjs',
|
|
193
|
+
'express-better-auth': 'better-auth-express',
|
|
194
|
+
};
|
|
195
|
+
return mapping[`${framework}-${auth}`] || auth;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
exports.TemplateComposer = TemplateComposer;
|
|
199
|
+
//# sourceMappingURL=template-composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-composer.js","sourceRoot":"","sources":["../../src/lib/template-composer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-stackkit-app",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Create a new StackKit project",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Create a new StackKit project with modular composition",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"create-stackkit": "./bin/create-stackkit.js"
|
|
8
8
|
},
|
|
9
9
|
"type": "commonjs",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"bin",
|
|
13
|
+
"templates"
|
|
14
|
+
],
|
|
10
15
|
"repository": {
|
|
11
16
|
"type": "git",
|
|
12
17
|
"url": "https://github.com/tariqul420/stackkit.git",
|
|
@@ -20,7 +25,8 @@
|
|
|
20
25
|
"dev": "tsc --watch",
|
|
21
26
|
"build": "tsc",
|
|
22
27
|
"clean": "rm -rf dist",
|
|
23
|
-
"typecheck": "tsc --noEmit"
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
29
|
+
"prepublishOnly": "npm run build && cp -r ../../templates ."
|
|
24
30
|
},
|
|
25
31
|
"keywords": [
|
|
26
32
|
"create",
|
|
@@ -32,11 +38,17 @@
|
|
|
32
38
|
"author": "Your Name",
|
|
33
39
|
"license": "MIT",
|
|
34
40
|
"dependencies": {
|
|
35
|
-
"
|
|
36
|
-
"
|
|
41
|
+
"chalk": "^4.1.2",
|
|
42
|
+
"fs-extra": "^11.2.0",
|
|
43
|
+
"inquirer": "^9.3.8",
|
|
44
|
+
"ora": "^5.4.1",
|
|
45
|
+
"validate-npm-package-name": "^5.0.1"
|
|
37
46
|
},
|
|
38
47
|
"devDependencies": {
|
|
48
|
+
"@types/fs-extra": "^11.0.4",
|
|
49
|
+
"@types/inquirer": "^9.0.7",
|
|
39
50
|
"@types/node": "^20.11.0",
|
|
51
|
+
"@types/validate-npm-package-name": "^4.0.2",
|
|
40
52
|
"typescript": "^5.3.3"
|
|
41
53
|
}
|
|
42
54
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "better-auth-express",
|
|
3
|
+
"displayName": "Better Auth (Express)",
|
|
4
|
+
"auth": "better-auth",
|
|
5
|
+
"compatibleWith": {
|
|
6
|
+
"frameworks": ["express"],
|
|
7
|
+
"databases": ["prisma-postgresql", "prisma-mongodb"]
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"better-auth": "^1.1.4",
|
|
11
|
+
"@better-auth/prisma": "^1.1.4"
|
|
12
|
+
},
|
|
13
|
+
"env": {
|
|
14
|
+
"BETTER_AUTH_SECRET": "your-secret-here",
|
|
15
|
+
"BETTER_AUTH_URL": "http://localhost:3000"
|
|
16
|
+
},
|
|
17
|
+
"files": ["src/lib/auth.ts", "src/routes/auth.ts"]
|
|
18
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { prismaAdapter } from '@better-auth/prisma';
|
|
2
|
+
import { betterAuth } from 'better-auth';
|
|
3
|
+
import { prisma } from './db';
|
|
4
|
+
|
|
5
|
+
export const auth = betterAuth({
|
|
6
|
+
database: prismaAdapter(prisma, {
|
|
7
|
+
provider: 'postgresql',
|
|
8
|
+
}),
|
|
9
|
+
emailAndPassword: {
|
|
10
|
+
enabled: true,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "better-auth-nextjs",
|
|
3
|
+
"displayName": "Better Auth (Next.js)",
|
|
4
|
+
"auth": "better-auth",
|
|
5
|
+
"compatibleWith": {
|
|
6
|
+
"frameworks": ["nextjs"],
|
|
7
|
+
"databases": ["prisma-postgresql", "prisma-mongodb"]
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"better-auth": "^1.1.4",
|
|
11
|
+
"@better-auth/prisma": "^1.1.4"
|
|
12
|
+
},
|
|
13
|
+
"env": {
|
|
14
|
+
"BETTER_AUTH_SECRET": "your-secret-here",
|
|
15
|
+
"BETTER_AUTH_URL": "http://localhost:3000"
|
|
16
|
+
},
|
|
17
|
+
"files": ["lib/auth.ts", "app/api/auth/[...all]/route.ts"]
|
|
18
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { prismaAdapter } from '@better-auth/prisma';
|
|
2
|
+
import { betterAuth } from 'better-auth';
|
|
3
|
+
import { prisma } from './db';
|
|
4
|
+
|
|
5
|
+
export const auth = betterAuth({
|
|
6
|
+
database: prismaAdapter(prisma, {
|
|
7
|
+
provider: 'postgresql',
|
|
8
|
+
}),
|
|
9
|
+
emailAndPassword: {
|
|
10
|
+
enabled: true,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export type Session = typeof auth.$Infer.Session;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nextauth",
|
|
3
|
+
"displayName": "Auth.js (NextAuth)",
|
|
4
|
+
"auth": "nextauth",
|
|
5
|
+
"compatibleWith": {
|
|
6
|
+
"frameworks": ["nextjs"],
|
|
7
|
+
"databases": ["prisma-postgresql", "prisma-mongodb"]
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"next-auth": "^5.0.0-beta.25",
|
|
11
|
+
"@auth/prisma-adapter": "^2.7.4"
|
|
12
|
+
},
|
|
13
|
+
"env": {
|
|
14
|
+
"AUTH_SECRET": "your-secret-here",
|
|
15
|
+
"NEXTAUTH_URL": "http://localhost:3000"
|
|
16
|
+
},
|
|
17
|
+
"files": ["app/api/auth/[...nextauth]/route.ts", "lib/auth.ts", "middleware.ts"]
|
|
18
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { prisma } from '@/lib/db';
|
|
2
|
+
import { PrismaAdapter } from '@auth/prisma-adapter';
|
|
3
|
+
import NextAuth from 'next-auth';
|
|
4
|
+
import CredentialsProvider from 'next-auth/providers/credentials';
|
|
5
|
+
|
|
6
|
+
export const { handlers, auth, signIn, signOut } = NextAuth({
|
|
7
|
+
adapter: PrismaAdapter(prisma),
|
|
8
|
+
session: {
|
|
9
|
+
strategy: 'jwt',
|
|
10
|
+
},
|
|
11
|
+
providers: [
|
|
12
|
+
CredentialsProvider({
|
|
13
|
+
name: 'Credentials',
|
|
14
|
+
credentials: {
|
|
15
|
+
email: { label: 'Email', type: 'email' },
|
|
16
|
+
password: { label: 'Password', type: 'password' },
|
|
17
|
+
},
|
|
18
|
+
async authorize(credentials) {
|
|
19
|
+
// Add your authentication logic here
|
|
20
|
+
if (!credentials?.email || !credentials?.password) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
// Replace with your actual user lookup
|
|
24
|
+
return { id: '1', email: credentials.email as string };
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
],
|
|
28
|
+
pages: {
|
|
29
|
+
signIn: '/auth/signin',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "tsx watch src/index.ts",
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"start": "node dist/index.js",
|
|
9
|
+
"lint": "eslint src"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"express": "^4.21.2",
|
|
13
|
+
"dotenv": "^16.4.7",
|
|
14
|
+
"cors": "^2.8.5"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/express": "^5.0.0",
|
|
18
|
+
"@types/node": "^22.10.5",
|
|
19
|
+
"@types/cors": "^2.8.17",
|
|
20
|
+
"tsx": "^4.19.2",
|
|
21
|
+
"typescript": "^5.7.2"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import express, { Request, Response } from 'express';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
import cors from 'cors';
|
|
4
|
+
|
|
5
|
+
dotenv.config();
|
|
6
|
+
|
|
7
|
+
const app = express();
|
|
8
|
+
const PORT = process.env.PORT || 3000;
|
|
9
|
+
|
|
10
|
+
// Middleware
|
|
11
|
+
app.use(cors());
|
|
12
|
+
app.use(express.json());
|
|
13
|
+
app.use(express.urlencoded({ extended: true }));
|
|
14
|
+
|
|
15
|
+
// Routes
|
|
16
|
+
app.get('/health', (req: Request, res: Response) => {
|
|
17
|
+
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
app.get('/', (req: Request, res: Response) => {
|
|
21
|
+
res.json({ message: 'Welcome to StackKit API' });
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Start server
|
|
25
|
+
app.listen(PORT, () => {
|
|
26
|
+
console.log(`🚀 Server running on http://localhost:${PORT}`);
|
|
27
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"moduleResolution": "node"
|
|
14
|
+
},
|
|
15
|
+
"include": ["src/**/*"],
|
|
16
|
+
"exclude": ["node_modules", "dist"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Metadata } from 'next';
|
|
2
|
+
import './globals.css';
|
|
3
|
+
|
|
4
|
+
export const metadata: Metadata = {
|
|
5
|
+
title: 'StackKit App',
|
|
6
|
+
description: 'Generated by create-stackkit-app',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default function RootLayout({
|
|
10
|
+
children,
|
|
11
|
+
}: Readonly<{
|
|
12
|
+
children: React.Node;
|
|
13
|
+
}>) {
|
|
14
|
+
return (
|
|
15
|
+
<html lang="en">
|
|
16
|
+
<body>{children}</body>
|
|
17
|
+
</html>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default function Home() {
|
|
2
|
+
return (
|
|
3
|
+
<main className="flex min-h-screen flex-col items-center justify-center p-24">
|
|
4
|
+
<h1 className="text-4xl font-bold">Welcome to StackKit</h1>
|
|
5
|
+
<p className="mt-4 text-xl">Your project is ready to go!</p>
|
|
6
|
+
</main>
|
|
7
|
+
);
|
|
8
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"next": "^15.1.6",
|
|
13
|
+
"react": "^19.0.0",
|
|
14
|
+
"react-dom": "^19.0.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "^22.10.5",
|
|
18
|
+
"@types/react": "^19.0.6",
|
|
19
|
+
"@types/react-dom": "^19.0.2",
|
|
20
|
+
"eslint": "^9",
|
|
21
|
+
"eslint-config-next": "^15.1.6",
|
|
22
|
+
"typescript": "^5.7.2"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2017",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "preserve",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [
|
|
17
|
+
{
|
|
18
|
+
"name": "next"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"paths": {
|
|
22
|
+
"@/*": ["./*"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
26
|
+
"exclude": ["node_modules"]
|
|
27
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prisma-mongodb",
|
|
3
|
+
"displayName": "Prisma + MongoDB",
|
|
4
|
+
"database": "prisma-mongodb",
|
|
5
|
+
"compatibleWith": ["nextjs", "express"],
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@prisma/client": "^6.2.0"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"prisma": "^6.2.0"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"db:generate": "prisma generate",
|
|
14
|
+
"db:push": "prisma db push",
|
|
15
|
+
"db:studio": "prisma studio"
|
|
16
|
+
},
|
|
17
|
+
"env": {
|
|
18
|
+
"DATABASE_URL": "mongodb://localhost:27017/mydb"
|
|
19
|
+
},
|
|
20
|
+
"files": ["prisma/schema.prisma", "lib/db.ts"]
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
|
|
3
|
+
const globalForPrisma = globalThis as unknown as {
|
|
4
|
+
prisma: PrismaClient | undefined;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const prisma =
|
|
8
|
+
globalForPrisma.prisma ??
|
|
9
|
+
new PrismaClient({
|
|
10
|
+
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
generator client {
|
|
2
|
+
provider = "prisma-client-js"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
datasource db {
|
|
6
|
+
provider = "mongodb"
|
|
7
|
+
url = env("DATABASE_URL")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
model User {
|
|
11
|
+
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
12
|
+
email String @unique
|
|
13
|
+
name String?
|
|
14
|
+
createdAt DateTime @default(now())
|
|
15
|
+
updatedAt DateTime @updatedAt
|
|
16
|
+
}
|