create-stackkit-app 0.1.4 ā 0.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/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 +293 -0
- package/dist/lib/create-project.js.map +1 -0
- package/package.json +15 -4
- package/templates/next-prisma-postgres-shadcn/.env.example +5 -0
- package/templates/next-prisma-postgres-shadcn/.eslintrc.json +7 -0
- package/templates/next-prisma-postgres-shadcn/.prettierrc +8 -0
- package/templates/next-prisma-postgres-shadcn/README.md +85 -0
- package/templates/next-prisma-postgres-shadcn/app/api/health/route.ts +25 -0
- package/templates/next-prisma-postgres-shadcn/app/globals.css +1 -0
- package/templates/next-prisma-postgres-shadcn/app/layout.tsx +22 -0
- package/templates/next-prisma-postgres-shadcn/app/page.tsx +29 -0
- package/templates/next-prisma-postgres-shadcn/lib/db.ts +14 -0
- package/templates/next-prisma-postgres-shadcn/lib/env.ts +15 -0
- package/templates/next-prisma-postgres-shadcn/next.config.ts +7 -0
- package/templates/next-prisma-postgres-shadcn/package.json +32 -0
- package/templates/next-prisma-postgres-shadcn/prisma/schema.prisma +20 -0
- package/templates/next-prisma-postgres-shadcn/public/.gitkeep +1 -0
- package/templates/next-prisma-postgres-shadcn/template.json +18 -0
- package/templates/next-prisma-postgres-shadcn/tsconfig.json +32 -0
- package/src/index.ts +0 -21
- package/tsconfig.json +0 -9
package/dist/index.js
CHANGED
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
-
};
|
|
6
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const
|
|
8
|
-
/**
|
|
9
|
-
* Thin wrapper that calls `stackkit init` with arguments
|
|
10
|
-
* This allows users to run `npx create-stackkit@latest my-app`
|
|
11
|
-
*/
|
|
4
|
+
const create_project_1 = require("./lib/create-project");
|
|
12
5
|
async function main() {
|
|
13
6
|
const args = process.argv.slice(2);
|
|
7
|
+
const projectName = args[0];
|
|
14
8
|
try {
|
|
15
|
-
|
|
16
|
-
await (0, execa_1.default)('npx', ['stackkit-cli@latest', 'init', ...args], {
|
|
17
|
-
stdio: 'inherit',
|
|
18
|
-
});
|
|
9
|
+
await (0, create_project_1.createProject)(projectName);
|
|
19
10
|
}
|
|
20
11
|
catch (error) {
|
|
12
|
+
console.error('Error:', error.message);
|
|
21
13
|
process.exit(1);
|
|
22
14
|
}
|
|
23
15
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yDAAqD;AAErD,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAE5B,IAAI,CAAC;QACH,MAAM,IAAA,8BAAa,EAAC,WAAW,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-project.d.ts","sourceRoot":"","sources":["../../src/lib/create-project.ts"],"names":[],"mappings":"AAiBA,wBAAsB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBvE"}
|
|
@@ -0,0 +1,293 @@
|
|
|
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.createProject = createProject;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
+
const ora_1 = __importDefault(require("ora"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
13
|
+
const child_process_1 = require("child_process");
|
|
14
|
+
async function createProject(projectName) {
|
|
15
|
+
console.log(chalk_1.default.bold.cyan('\nš Create StackKit App\n'));
|
|
16
|
+
// Get project configuration through wizard
|
|
17
|
+
const config = await getProjectConfig(projectName);
|
|
18
|
+
// Validate target directory
|
|
19
|
+
const targetDir = path_1.default.join(process.cwd(), config.projectName);
|
|
20
|
+
if (await fs_extra_1.default.pathExists(targetDir)) {
|
|
21
|
+
console.log(chalk_1.default.red(`\nā Directory "${config.projectName}" already exists`));
|
|
22
|
+
console.log(chalk_1.default.gray('Please choose a different name or remove the existing directory.\n'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
// Create project
|
|
26
|
+
await generateProject(config, targetDir);
|
|
27
|
+
// Show next steps
|
|
28
|
+
showNextSteps(config);
|
|
29
|
+
}
|
|
30
|
+
async function getProjectConfig(projectName) {
|
|
31
|
+
const answers = await inquirer_1.default.prompt([
|
|
32
|
+
{
|
|
33
|
+
type: 'input',
|
|
34
|
+
name: 'projectName',
|
|
35
|
+
message: 'Project name:',
|
|
36
|
+
default: projectName || 'my-app',
|
|
37
|
+
when: !projectName,
|
|
38
|
+
validate: (input) => {
|
|
39
|
+
const validation = (0, validate_npm_package_name_1.default)(input);
|
|
40
|
+
if (!validation.validForNewPackages) {
|
|
41
|
+
return validation.errors?.[0] || 'Invalid package name';
|
|
42
|
+
}
|
|
43
|
+
if (fs_extra_1.default.existsSync(path_1.default.join(process.cwd(), input))) {
|
|
44
|
+
return 'Directory already exists';
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: 'list',
|
|
51
|
+
name: 'framework',
|
|
52
|
+
message: 'Select framework:',
|
|
53
|
+
choices: [
|
|
54
|
+
{ name: 'Next.js', value: 'nextjs' },
|
|
55
|
+
{ name: 'Express.js', value: 'express' },
|
|
56
|
+
{ name: 'React (Vite)', value: 'react-vite' },
|
|
57
|
+
{ name: 'Astro', value: 'astro' },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
type: 'list',
|
|
62
|
+
name: 'database',
|
|
63
|
+
message: 'Select database/ORM:',
|
|
64
|
+
choices: [
|
|
65
|
+
{ name: 'Prisma + PostgreSQL', value: 'prisma-postgresql' },
|
|
66
|
+
{ name: 'Prisma + MongoDB', value: 'prisma-mongodb' },
|
|
67
|
+
{ name: 'Mongoose + MongoDB', value: 'mongoose-mongodb' },
|
|
68
|
+
{ name: 'Drizzle + PostgreSQL', value: 'drizzle-postgresql' },
|
|
69
|
+
{ name: 'None', value: 'none' },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: 'list',
|
|
74
|
+
name: 'auth',
|
|
75
|
+
message: 'Select authentication:',
|
|
76
|
+
choices: (answers) => {
|
|
77
|
+
const baseChoices = [
|
|
78
|
+
{ name: 'Auth.js (NextAuth)', value: 'nextauth' },
|
|
79
|
+
{ name: 'Better Auth', value: 'better-auth' },
|
|
80
|
+
{ name: 'Clerk', value: 'clerk' },
|
|
81
|
+
{ name: 'None', value: 'none' },
|
|
82
|
+
];
|
|
83
|
+
// Filter choices based on framework compatibility
|
|
84
|
+
if (answers.framework === 'nextjs') {
|
|
85
|
+
return baseChoices;
|
|
86
|
+
}
|
|
87
|
+
else if (answers.framework === 'express') {
|
|
88
|
+
return baseChoices.filter(c => ['better-auth', 'none'].includes(c.value));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return [{ name: 'None', value: 'none' }];
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'list',
|
|
97
|
+
name: 'language',
|
|
98
|
+
message: 'Language:',
|
|
99
|
+
choices: [
|
|
100
|
+
{ name: 'TypeScript', value: 'typescript' },
|
|
101
|
+
{ name: 'JavaScript', value: 'javascript' },
|
|
102
|
+
],
|
|
103
|
+
default: 'typescript',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
type: 'list',
|
|
107
|
+
name: 'packageManager',
|
|
108
|
+
message: 'Package manager:',
|
|
109
|
+
choices: ['pnpm', 'npm', 'yarn'],
|
|
110
|
+
default: 'pnpm',
|
|
111
|
+
},
|
|
112
|
+
]);
|
|
113
|
+
return {
|
|
114
|
+
projectName: projectName || answers.projectName,
|
|
115
|
+
framework: answers.framework,
|
|
116
|
+
database: answers.database,
|
|
117
|
+
auth: answers.auth,
|
|
118
|
+
language: answers.language,
|
|
119
|
+
packageManager: answers.packageManager,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async function generateProject(config, targetDir) {
|
|
123
|
+
console.log();
|
|
124
|
+
// Copy base template
|
|
125
|
+
const copySpinner = (0, ora_1.default)('Creating project files...').start();
|
|
126
|
+
try {
|
|
127
|
+
await copyBaseTemplate(config, targetDir);
|
|
128
|
+
copySpinner.succeed('Project files created');
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
copySpinner.fail('Failed to create project files');
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
// Install dependencies
|
|
135
|
+
const installSpinner = (0, ora_1.default)('Installing dependencies...').start();
|
|
136
|
+
try {
|
|
137
|
+
await installDependencies(targetDir, config.packageManager);
|
|
138
|
+
installSpinner.succeed('Dependencies installed');
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
installSpinner.fail('Failed to install dependencies');
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
// Initialize git
|
|
145
|
+
const gitSpinner = (0, ora_1.default)('Initializing git repository...').start();
|
|
146
|
+
try {
|
|
147
|
+
await initGit(targetDir);
|
|
148
|
+
gitSpinner.succeed('Git repository initialized');
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
gitSpinner.warn('Failed to initialize git repository');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function copyBaseTemplate(config, targetDir) {
|
|
155
|
+
const templatesDir = path_1.default.join(__dirname, '..', '..', 'templates');
|
|
156
|
+
// Map configuration to template directory
|
|
157
|
+
let templateDir;
|
|
158
|
+
if (config.framework === 'nextjs' &&
|
|
159
|
+
(config.database === 'prisma-postgresql' || config.database === 'prisma-mongodb')) {
|
|
160
|
+
// Use existing Next.js + Prisma template
|
|
161
|
+
templateDir = path_1.default.join(templatesDir, 'next-prisma-postgres-shadcn');
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// For now, fallback to the same template until more templates are added
|
|
165
|
+
templateDir = path_1.default.join(templatesDir, 'next-prisma-postgres-shadcn');
|
|
166
|
+
}
|
|
167
|
+
// Verify template exists
|
|
168
|
+
if (!(await fs_extra_1.default.pathExists(templateDir))) {
|
|
169
|
+
throw new Error(`Template not found at ${templateDir}`);
|
|
170
|
+
}
|
|
171
|
+
// Copy template to target directory
|
|
172
|
+
await fs_extra_1.default.ensureDir(targetDir);
|
|
173
|
+
await fs_extra_1.default.copy(templateDir, targetDir, {
|
|
174
|
+
filter: (src) => {
|
|
175
|
+
const basename = path_1.default.basename(src);
|
|
176
|
+
return basename !== 'template.json' &&
|
|
177
|
+
basename !== 'node_modules' &&
|
|
178
|
+
basename !== '.git';
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
// Update package.json with project name
|
|
182
|
+
const packageJsonPath = path_1.default.join(targetDir, 'package.json');
|
|
183
|
+
if (await fs_extra_1.default.pathExists(packageJsonPath)) {
|
|
184
|
+
const packageJson = await fs_extra_1.default.readJson(packageJsonPath);
|
|
185
|
+
packageJson.name = config.projectName;
|
|
186
|
+
await fs_extra_1.default.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
187
|
+
}
|
|
188
|
+
// Handle language conversion if JavaScript selected
|
|
189
|
+
if (config.language === 'javascript') {
|
|
190
|
+
await convertToJavaScript(targetDir);
|
|
191
|
+
}
|
|
192
|
+
// Update database configuration if MongoDB selected
|
|
193
|
+
if (config.database === 'prisma-mongodb') {
|
|
194
|
+
await updatePrismaForMongoDB(targetDir);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async function convertToJavaScript(targetDir) {
|
|
198
|
+
// Remove TypeScript config files
|
|
199
|
+
const tsFiles = ['tsconfig.json', 'next-env.d.ts'];
|
|
200
|
+
for (const file of tsFiles) {
|
|
201
|
+
const filePath = path_1.default.join(targetDir, file);
|
|
202
|
+
if (await fs_extra_1.default.pathExists(filePath)) {
|
|
203
|
+
await fs_extra_1.default.remove(filePath);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Rename .ts(x) files to .js(x)
|
|
207
|
+
const renameExtensions = async (dir) => {
|
|
208
|
+
const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true });
|
|
209
|
+
for (const entry of entries) {
|
|
210
|
+
const fullPath = path_1.default.join(dir, entry.name);
|
|
211
|
+
if (entry.isDirectory() && entry.name !== 'node_modules') {
|
|
212
|
+
await renameExtensions(fullPath);
|
|
213
|
+
}
|
|
214
|
+
else if (entry.isFile()) {
|
|
215
|
+
if (entry.name.endsWith('.ts')) {
|
|
216
|
+
await fs_extra_1.default.rename(fullPath, fullPath.replace(/\.ts$/, '.js'));
|
|
217
|
+
}
|
|
218
|
+
else if (entry.name.endsWith('.tsx')) {
|
|
219
|
+
await fs_extra_1.default.rename(fullPath, fullPath.replace(/\.tsx$/, '.jsx'));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
await renameExtensions(targetDir);
|
|
225
|
+
// Update package.json to remove TypeScript dependencies
|
|
226
|
+
const packageJsonPath = path_1.default.join(targetDir, 'package.json');
|
|
227
|
+
if (await fs_extra_1.default.pathExists(packageJsonPath)) {
|
|
228
|
+
const packageJson = await fs_extra_1.default.readJson(packageJsonPath);
|
|
229
|
+
if (packageJson.devDependencies) {
|
|
230
|
+
delete packageJson.devDependencies['typescript'];
|
|
231
|
+
delete packageJson.devDependencies['@types/node'];
|
|
232
|
+
delete packageJson.devDependencies['@types/react'];
|
|
233
|
+
delete packageJson.devDependencies['@types/react-dom'];
|
|
234
|
+
}
|
|
235
|
+
await fs_extra_1.default.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
async function updatePrismaForMongoDB(targetDir) {
|
|
239
|
+
const prismaSchemaPath = path_1.default.join(targetDir, 'prisma', 'schema.prisma');
|
|
240
|
+
if (await fs_extra_1.default.pathExists(prismaSchemaPath)) {
|
|
241
|
+
let schema = await fs_extra_1.default.readFile(prismaSchemaPath, 'utf-8');
|
|
242
|
+
// Update datasource provider
|
|
243
|
+
schema = schema.replace(/provider\s*=\s*"postgresql"/g, 'provider = "mongodb"');
|
|
244
|
+
// Update connection string
|
|
245
|
+
schema = schema.replace(/DATABASE_URL/g, 'MONGODB_URL');
|
|
246
|
+
// Update id fields to use MongoDB ObjectId
|
|
247
|
+
schema = schema.replace(/@id\s+@default\(autoincrement\(\)\)/g, '@id @default(auto()) @map("_id") @db.ObjectId');
|
|
248
|
+
await fs_extra_1.default.writeFile(prismaSchemaPath, schema);
|
|
249
|
+
}
|
|
250
|
+
// Update .env file
|
|
251
|
+
const envPath = path_1.default.join(targetDir, '.env');
|
|
252
|
+
if (await fs_extra_1.default.pathExists(envPath)) {
|
|
253
|
+
let env = await fs_extra_1.default.readFile(envPath, 'utf-8');
|
|
254
|
+
env = env.replace(/DATABASE_URL\s*=.*/g, 'MONGODB_URL="mongodb://localhost:27017/myapp"');
|
|
255
|
+
await fs_extra_1.default.writeFile(envPath, env);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async function installDependencies(cwd, packageManager) {
|
|
259
|
+
const commands = {
|
|
260
|
+
npm: 'npm install',
|
|
261
|
+
yarn: 'yarn install',
|
|
262
|
+
pnpm: 'pnpm install',
|
|
263
|
+
};
|
|
264
|
+
const command = commands[packageManager];
|
|
265
|
+
if (!command) {
|
|
266
|
+
throw new Error(`Unsupported package manager: ${packageManager}`);
|
|
267
|
+
}
|
|
268
|
+
(0, child_process_1.execSync)(command, {
|
|
269
|
+
cwd,
|
|
270
|
+
stdio: 'pipe',
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
async function initGit(cwd) {
|
|
274
|
+
try {
|
|
275
|
+
(0, child_process_1.execSync)('git --version', { stdio: 'pipe' });
|
|
276
|
+
(0, child_process_1.execSync)('git init', { cwd, stdio: 'pipe' });
|
|
277
|
+
(0, child_process_1.execSync)('git add -A', { cwd, stdio: 'pipe' });
|
|
278
|
+
(0, child_process_1.execSync)('git commit -m "Initial commit from create-stackkit-app"', {
|
|
279
|
+
cwd,
|
|
280
|
+
stdio: 'pipe',
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
throw new Error('Git initialization failed');
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function showNextSteps(config) {
|
|
288
|
+
console.log(chalk_1.default.green.bold(`\nā Created ${config.projectName}\n`));
|
|
289
|
+
console.log(chalk_1.default.bold('Next steps:'));
|
|
290
|
+
console.log(chalk_1.default.cyan(` cd ${config.projectName}`));
|
|
291
|
+
console.log(chalk_1.default.cyan(` ${config.packageManager}${config.packageManager === 'npm' ? ' run' : ''} dev\n`));
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=create-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-project.js","sourceRoot":"","sources":["../../src/lib/create-project.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.2.0",
|
|
4
|
+
"description": "Create a new StackKit project with wizard-style setup",
|
|
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",
|
|
@@ -32,11 +37,17 @@
|
|
|
32
37
|
"author": "Your Name",
|
|
33
38
|
"license": "MIT",
|
|
34
39
|
"dependencies": {
|
|
35
|
-
"
|
|
36
|
-
"
|
|
40
|
+
"chalk": "^4.1.2",
|
|
41
|
+
"fs-extra": "^11.2.0",
|
|
42
|
+
"inquirer": "^9.3.8",
|
|
43
|
+
"ora": "^5.4.1",
|
|
44
|
+
"validate-npm-package-name": "^5.0.1"
|
|
37
45
|
},
|
|
38
46
|
"devDependencies": {
|
|
47
|
+
"@types/fs-extra": "^11.0.4",
|
|
48
|
+
"@types/inquirer": "^9.0.7",
|
|
39
49
|
"@types/node": "^20.11.0",
|
|
50
|
+
"@types/validate-npm-package-name": "^4.0.2",
|
|
40
51
|
"typescript": "^5.3.3"
|
|
41
52
|
}
|
|
42
53
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Project
|
|
2
|
+
|
|
3
|
+
Created with [StackKit](https://github.com/tariqul420/stackkit).
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install dependencies
|
|
9
|
+
pnpm install
|
|
10
|
+
|
|
11
|
+
# Configure environment
|
|
12
|
+
cp .env.example .env
|
|
13
|
+
# Update DATABASE_URL in .env
|
|
14
|
+
|
|
15
|
+
# Run migrations
|
|
16
|
+
pnpm prisma migrate dev
|
|
17
|
+
|
|
18
|
+
# Start dev server
|
|
19
|
+
pnpm dev
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Open [http://localhost:3000](http://localhost:3000)
|
|
23
|
+
|
|
24
|
+
## Stack
|
|
25
|
+
|
|
26
|
+
- Next.js 15 (App Router)
|
|
27
|
+
- TypeScript
|
|
28
|
+
- Prisma + PostgreSQL
|
|
29
|
+
- Tailwind CSS
|
|
30
|
+
- shadcn/ui
|
|
31
|
+
- Zod validation
|
|
32
|
+
|
|
33
|
+
## Structure
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
āāā app/ # Next.js routes
|
|
37
|
+
āāā lib/ # Utilities
|
|
38
|
+
āāā prisma/ # Database schema
|
|
39
|
+
āāā public/ # Static files
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Scripts
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pnpm dev # Development server
|
|
46
|
+
pnpm build # Production build
|
|
47
|
+
pnpm start # Start production
|
|
48
|
+
pnpm lint # Run linter
|
|
49
|
+
pnpm prisma studio # Open Prisma Studio
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Add Features
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx stackkit-cli add auth
|
|
56
|
+
```
|
|
57
|
+
āāā lib/ # Shared utilities
|
|
58
|
+
ā āāā db.ts # Prisma client
|
|
59
|
+
ā āāā env.ts # Environment validation
|
|
60
|
+
āāā prisma/ # Database schema
|
|
61
|
+
ā āāā schema.prisma
|
|
62
|
+
āāā public/ # Static assets
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Available Commands
|
|
66
|
+
|
|
67
|
+
- `pnpm dev` - Start development server
|
|
68
|
+
- `pnpm build` - Build for production
|
|
69
|
+
- `pnpm start` - Start production server
|
|
70
|
+
- `pnpm lint` - Run ESLint
|
|
71
|
+
- `pnpm format` - Format code with Prettier
|
|
72
|
+
|
|
73
|
+
## Adding Features
|
|
74
|
+
|
|
75
|
+
Use StackKit to add more features to your project:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx stackkit add auth
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Learn More
|
|
82
|
+
|
|
83
|
+
- [Next.js Documentation](https://nextjs.org/docs)
|
|
84
|
+
- [Prisma Documentation](https://www.prisma.io/docs)
|
|
85
|
+
- [StackKit Documentation](https://github.com/yourusername/stackkit)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { prisma } from '@/lib/db';
|
|
3
|
+
|
|
4
|
+
export async function GET() {
|
|
5
|
+
try {
|
|
6
|
+
// Test database connection
|
|
7
|
+
await prisma.$queryRaw`SELECT 1`;
|
|
8
|
+
|
|
9
|
+
return NextResponse.json({
|
|
10
|
+
status: 'ok',
|
|
11
|
+
timestamp: new Date().toISOString(),
|
|
12
|
+
database: 'connected',
|
|
13
|
+
});
|
|
14
|
+
} catch (error) {
|
|
15
|
+
return NextResponse.json(
|
|
16
|
+
{
|
|
17
|
+
status: 'error',
|
|
18
|
+
timestamp: new Date().toISOString(),
|
|
19
|
+
database: 'disconnected',
|
|
20
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
21
|
+
},
|
|
22
|
+
{ status: 500 }
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Metadata } from 'next';
|
|
2
|
+
import { Inter } from 'next/font/google';
|
|
3
|
+
import './globals.css';
|
|
4
|
+
|
|
5
|
+
const inter = Inter({ subsets: ['latin'] });
|
|
6
|
+
|
|
7
|
+
export const metadata: Metadata = {
|
|
8
|
+
title: 'StackKit App',
|
|
9
|
+
description: 'Created with StackKit',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default function RootLayout({
|
|
13
|
+
children,
|
|
14
|
+
}: Readonly<{
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
}>) {
|
|
17
|
+
return (
|
|
18
|
+
<html lang="en">
|
|
19
|
+
<body className={inter.className}>{children}</body>
|
|
20
|
+
</html>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export default function HomePage() {
|
|
2
|
+
return (
|
|
3
|
+
<main className="flex min-h-screen flex-col items-center justify-center p-24">
|
|
4
|
+
<div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm">
|
|
5
|
+
<h1 className="text-4xl font-bold mb-4">Welcome to StackKit</h1>
|
|
6
|
+
<p className="text-lg text-gray-600 dark:text-gray-400">
|
|
7
|
+
Your production-ready Next.js starter
|
|
8
|
+
</p>
|
|
9
|
+
<div className="mt-8 space-y-2">
|
|
10
|
+
<p>ā
Next.js 15 App Router</p>
|
|
11
|
+
<p>ā
TypeScript</p>
|
|
12
|
+
<p>ā
Prisma + PostgreSQL</p>
|
|
13
|
+
<p>ā
Tailwind CSS</p>
|
|
14
|
+
<p>ā
Environment validation</p>
|
|
15
|
+
</div>
|
|
16
|
+
<div className="mt-8">
|
|
17
|
+
<a
|
|
18
|
+
href="/api/health"
|
|
19
|
+
className="text-blue-600 hover:underline"
|
|
20
|
+
target="_blank"
|
|
21
|
+
rel="noopener noreferrer"
|
|
22
|
+
>
|
|
23
|
+
Check API Health ā
|
|
24
|
+
</a>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</main>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import { env } from './env';
|
|
3
|
+
|
|
4
|
+
const globalForPrisma = globalThis as unknown as {
|
|
5
|
+
prisma: PrismaClient | undefined;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const prisma =
|
|
9
|
+
globalForPrisma.prisma ??
|
|
10
|
+
new PrismaClient({
|
|
11
|
+
log: env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
if (env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
const envSchema = z.object({
|
|
4
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
5
|
+
DATABASE_URL: z.string().url(),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const parsedEnv = envSchema.safeParse(process.env);
|
|
9
|
+
|
|
10
|
+
if (!parsedEnv.success) {
|
|
11
|
+
console.error('ā Invalid environment variables:', parsedEnv.error.format());
|
|
12
|
+
throw new Error('Invalid environment variables');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const env = parsedEnv.data;
|
|
@@ -0,0 +1,32 @@
|
|
|
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": "eslint . --ext .ts,.tsx",
|
|
10
|
+
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
11
|
+
"postinstall": "prisma generate"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@prisma/client": "^5.8.0",
|
|
15
|
+
"next": "16.1.1",
|
|
16
|
+
"react": "19.2.3",
|
|
17
|
+
"react-dom": "19.2.3",
|
|
18
|
+
"zod": "^3.22.4"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@tailwindcss/postcss": "^4",
|
|
22
|
+
"@types/node": "^20",
|
|
23
|
+
"@types/react": "^19",
|
|
24
|
+
"@types/react-dom": "^19",
|
|
25
|
+
"eslint": "^9",
|
|
26
|
+
"eslint-config-next": "16.1.1",
|
|
27
|
+
"prettier": "^3.2.4",
|
|
28
|
+
"prisma": "^5.8.0",
|
|
29
|
+
"tailwindcss": "^4",
|
|
30
|
+
"typescript": "^5"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// This is your Prisma schema file
|
|
2
|
+
// Learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
3
|
+
|
|
4
|
+
generator client {
|
|
5
|
+
provider = "prisma-client-js"
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
datasource db {
|
|
9
|
+
provider = "postgresql"
|
|
10
|
+
url = env("DATABASE_URL")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Example model - replace with your own
|
|
14
|
+
model User {
|
|
15
|
+
id String @id @default(cuid())
|
|
16
|
+
email String @unique
|
|
17
|
+
name String?
|
|
18
|
+
createdAt DateTime @default(now())
|
|
19
|
+
updatedAt DateTime @updatedAt
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# This file is used to keep the public directory in git
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "next-prisma-postgres-shadcn",
|
|
3
|
+
"displayName": "Next.js + Prisma + PostgreSQL + shadcn/ui",
|
|
4
|
+
"description": "Next.js 15 App Router, Prisma, PostgreSQL, shadcn/ui, TypeScript",
|
|
5
|
+
"tags": ["nextjs", "prisma", "postgresql", "shadcn", "typescript"],
|
|
6
|
+
"defaultPackageManager": "pnpm",
|
|
7
|
+
"features": [
|
|
8
|
+
"Next.js 15 App Router",
|
|
9
|
+
"TypeScript",
|
|
10
|
+
"Prisma ORM",
|
|
11
|
+
"PostgreSQL",
|
|
12
|
+
"shadcn/ui components",
|
|
13
|
+
"Tailwind CSS",
|
|
14
|
+
"Environment validation (Zod)",
|
|
15
|
+
"ESLint + Prettier",
|
|
16
|
+
"Health check API route"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
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": [
|
|
26
|
+
"next-env.d.ts",
|
|
27
|
+
"**/*.ts",
|
|
28
|
+
"**/*.tsx",
|
|
29
|
+
".next/types/**/*.ts"
|
|
30
|
+
],
|
|
31
|
+
"exclude": ["node_modules"]
|
|
32
|
+
}
|
package/src/index.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import execa from 'execa';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Thin wrapper that calls `stackkit init` with arguments
|
|
6
|
-
* This allows users to run `npx create-stackkit@latest my-app`
|
|
7
|
-
*/
|
|
8
|
-
async function main() {
|
|
9
|
-
const args = process.argv.slice(2);
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
// Call stackkit init with forwarded arguments
|
|
13
|
-
await execa('npx', ['stackkit-cli@latest', 'init', ...args], {
|
|
14
|
-
stdio: 'inherit',
|
|
15
|
-
});
|
|
16
|
-
} catch (error) {
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
main();
|