stackkit 0.1.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 +41 -0
- package/bin/stackkit.js +4 -0
- package/dist/cli/add.d.ts +8 -0
- package/dist/cli/add.js +313 -0
- package/dist/cli/create.d.ts +22 -0
- package/dist/cli/create.js +336 -0
- package/dist/cli/doctor.d.ts +7 -0
- package/dist/cli/doctor.js +569 -0
- package/dist/cli/list.d.ts +6 -0
- package/dist/cli/list.js +123 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +91 -0
- package/dist/lib/conversion/js-conversion.d.ts +1 -0
- package/dist/lib/conversion/js-conversion.js +244 -0
- package/dist/lib/database/database-config.d.ts +6 -0
- package/dist/lib/database/database-config.js +9 -0
- package/dist/lib/discovery/module-discovery.d.ts +62 -0
- package/dist/lib/discovery/module-discovery.js +188 -0
- package/dist/lib/env/env-editor.d.ts +9 -0
- package/dist/lib/env/env-editor.js +116 -0
- package/dist/lib/framework/framework-utils.d.ts +22 -0
- package/dist/lib/framework/framework-utils.js +74 -0
- package/dist/lib/fs/files.d.ts +14 -0
- package/dist/lib/fs/files.js +101 -0
- package/dist/lib/generation/code-generator.d.ts +83 -0
- package/dist/lib/generation/code-generator.js +681 -0
- package/dist/lib/git-utils.d.ts +1 -0
- package/dist/lib/git-utils.js +9 -0
- package/dist/lib/pm/package-manager.d.ts +5 -0
- package/dist/lib/pm/package-manager.js +69 -0
- package/dist/lib/project/detect.d.ts +4 -0
- package/dist/lib/project/detect.js +121 -0
- package/dist/lib/ui/logger.d.ts +16 -0
- package/dist/lib/ui/logger.js +59 -0
- package/dist/types/index.d.ts +92 -0
- package/dist/types/index.js +2 -0
- 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/api/auth/[...all]/route.ts +4 -0
- package/modules/auth/better-auth/files/lib/auth-client.ts +7 -0
- package/modules/auth/better-auth/files/lib/auth.ts +83 -0
- 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/prisma/schema.prisma +63 -0
- package/modules/auth/better-auth/generator.json +78 -0
- package/modules/auth/better-auth/module.json +37 -0
- package/modules/database/mongoose/files/lib/db.ts +63 -0
- package/modules/database/mongoose/files/models/User.ts +34 -0
- package/modules/database/mongoose/generator.json +24 -0
- package/modules/database/mongoose/module.json +15 -0
- package/modules/database/prisma/files/lib/prisma.ts +45 -0
- package/modules/database/prisma/files/prisma/schema.prisma +8 -0
- package/modules/database/prisma/files/prisma.config.ts +12 -0
- package/modules/database/prisma/generator.json +43 -0
- package/modules/database/prisma/module.json +17 -0
- package/package.json +83 -0
- package/templates/express/.env.example +2 -0
- package/templates/express/eslint.config.cjs +42 -0
- package/templates/express/package.json +33 -0
- package/templates/express/src/app.ts +51 -0
- package/templates/express/src/config/env.ts +12 -0
- 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/src/middlewares/error.middleware.ts +18 -0
- package/templates/express/src/server.ts +8 -0
- package/templates/express/template.json +27 -0
- package/templates/express/tsconfig.json +30 -0
- package/templates/nextjs/README.md +52 -0
- package/templates/nextjs/app/favicon.ico +0 -0
- package/templates/nextjs/app/globals.css +26 -0
- package/templates/nextjs/app/layout.tsx +30 -0
- package/templates/nextjs/app/page.tsx +57 -0
- package/templates/nextjs/eslint.config.mjs +18 -0
- package/templates/nextjs/lib/env.ts +8 -0
- package/templates/nextjs/next.config.ts +7 -0
- package/templates/nextjs/package.json +27 -0
- package/templates/nextjs/postcss.config.mjs +7 -0
- package/templates/nextjs/public/file.svg +1 -0
- package/templates/nextjs/public/globe.svg +1 -0
- package/templates/nextjs/public/next.svg +1 -0
- package/templates/nextjs/public/vercel.svg +1 -0
- package/templates/nextjs/public/window.svg +1 -0
- package/templates/nextjs/template.json +34 -0
- package/templates/nextjs/tsconfig.json +34 -0
- package/templates/react/.env.example +1 -0
- package/templates/react/.prettierignore +4 -0
- package/templates/react/.prettierrc +9 -0
- package/templates/react/README.md +56 -0
- package/templates/react/eslint.config.js +23 -0
- package/templates/react/index.html +14 -0
- package/templates/react/package.json +44 -0
- package/templates/react/public/vite.svg +1 -0
- package/templates/react/src/api/client.ts +47 -0
- package/templates/react/src/assets/react.svg +1 -0
- package/templates/react/src/components/ErrorBoundary.tsx +51 -0
- package/templates/react/src/components/Layout.tsx +13 -0
- package/templates/react/src/components/Loading.tsx +8 -0
- package/templates/react/src/components/SEO.tsx +49 -0
- package/templates/react/src/config/constants.ts +5 -0
- package/templates/react/src/hooks/index.ts +64 -0
- package/templates/react/src/index.css +1 -0
- package/templates/react/src/lib/queryClient.ts +12 -0
- package/templates/react/src/main.tsx +22 -0
- package/templates/react/src/pages/About.tsx +78 -0
- package/templates/react/src/pages/Home.tsx +49 -0
- package/templates/react/src/pages/NotFound.tsx +24 -0
- package/templates/react/src/router.tsx +21 -0
- package/templates/react/src/types/api.d.ts +20 -0
- package/templates/react/src/utils/helpers.ts +51 -0
- package/templates/react/src/utils/storage.ts +35 -0
- package/templates/react/src/vite-env.d.ts +11 -0
- package/templates/react/template.json +38 -0
- package/templates/react/tsconfig.app.json +28 -0
- package/templates/react/tsconfig.json +4 -0
- package/templates/react/tsconfig.node.json +26 -0
- package/templates/react/vite.config.ts +7 -0
- package/templates/react-vite/README.md +56 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export const getVerificationEmailTemplate = (user: { name?: string; email: string }, url: string) => {
|
|
2
|
+
const html = `
|
|
3
|
+
<!DOCTYPE html>
|
|
4
|
+
<html lang="en">
|
|
5
|
+
<head>
|
|
6
|
+
<meta charset="UTF-8">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
8
|
+
<title>Verify Your Email</title>
|
|
9
|
+
<style>
|
|
10
|
+
body { font-family: Arial, sans-serif; line-height: 1.6; color: #000; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #fff; }
|
|
11
|
+
.header { padding: 20px; text-align: center; border-bottom: 1px solid #000; }
|
|
12
|
+
.content { padding: 20px; }
|
|
13
|
+
.button { display: inline-block; background-color: #fff; color: #000; padding: 10px 20px; text-decoration: none; border: 1px solid #000; border-radius: 5px; margin: 20px 0; }
|
|
14
|
+
.footer { font-size: 12px; color: #000; text-align: center; margin-top: 20px; border-top: 1px solid #000; padding-top: 20px; }
|
|
15
|
+
</style>
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<div class="header">
|
|
19
|
+
<h1>Verify Your Email Address</h1>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="content">
|
|
22
|
+
<p>Hi ${user.name || user.email},</p>
|
|
23
|
+
<p>Thank you for signing up. Please verify your email address to complete your registration.</p>
|
|
24
|
+
<a href="${url}" class="button">Verify Email</a>
|
|
25
|
+
<p>If the button doesn't work, copy and paste this link: <a href="${url}">${url}</a></p>
|
|
26
|
+
<p>This link expires in 24 hours.</p>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="footer">
|
|
29
|
+
<p>If you didn't create an account, ignore this email.</p>
|
|
30
|
+
</div>
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const text = `Hi ${user.name || user.email},
|
|
36
|
+
|
|
37
|
+
Thank you for signing up. Please verify your email address by clicking this link: ${url}
|
|
38
|
+
|
|
39
|
+
This link expires in 24 hours.
|
|
40
|
+
|
|
41
|
+
If you didn't create an account, ignore this email.`;
|
|
42
|
+
|
|
43
|
+
return { html, text };
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const getPasswordResetEmailTemplate = (user: { name?: string; email: string }, url: string) => {
|
|
47
|
+
const html = `
|
|
48
|
+
<!DOCTYPE html>
|
|
49
|
+
<html lang="en">
|
|
50
|
+
<head>
|
|
51
|
+
<meta charset="UTF-8">
|
|
52
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
53
|
+
<title>Reset Your Password</title>
|
|
54
|
+
<style>
|
|
55
|
+
body { font-family: Arial, sans-serif; line-height: 1.6; color: #000; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #fff; }
|
|
56
|
+
.header { padding: 20px; text-align: center; border-bottom: 1px solid #000; }
|
|
57
|
+
.content { padding: 20px; }
|
|
58
|
+
.button { display: inline-block; background-color: #fff; color: #000; padding: 10px 20px; text-decoration: none; border: 1px solid #000; border-radius: 5px; margin: 20px 0; }
|
|
59
|
+
.footer { font-size: 12px; color: #000; text-align: center; margin-top: 20px; border-top: 1px solid #000; padding-top: 20px; }
|
|
60
|
+
</style>
|
|
61
|
+
</head>
|
|
62
|
+
<body>
|
|
63
|
+
<div class="header">
|
|
64
|
+
<h1>Reset Your Password</h1>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="content">
|
|
67
|
+
<p>Hi ${user.name || user.email},</p>
|
|
68
|
+
<p>You requested a password reset. Click the link below to reset your password.</p>
|
|
69
|
+
<a href="${url}" class="button">Reset Password</a>
|
|
70
|
+
<p>If the button doesn't work, copy and paste this link: <a href="${url}">${url}</a></p>
|
|
71
|
+
<p>This link expires in 1 hour.</p>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="footer">
|
|
74
|
+
<p>If you didn't request this, ignore this email.</p>
|
|
75
|
+
</div>
|
|
76
|
+
</body>
|
|
77
|
+
</html>
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
const text = `Hi ${user.name || user.email},
|
|
81
|
+
|
|
82
|
+
You requested a password reset. Click this link to reset your password: ${url}
|
|
83
|
+
|
|
84
|
+
This link expires in 1 hour.
|
|
85
|
+
|
|
86
|
+
If you didn't request this, ignore this email.`;
|
|
87
|
+
|
|
88
|
+
return { html, text };
|
|
89
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{{#var defaultId = {{#if prismaProvider == postgresql}}@default(cuid()){{/if}}{{#if prismaProvider == mysql}}@default(uuid()){{/if}}{{#if prismaProvider == sqlite}}@default(uuid()){{/if}}}}
|
|
2
|
+
model User {
|
|
3
|
+
id String @id {{defaultId}}
|
|
4
|
+
name String
|
|
5
|
+
email String
|
|
6
|
+
emailVerified Boolean @default(false)
|
|
7
|
+
image String?
|
|
8
|
+
createdAt DateTime @default(now())
|
|
9
|
+
updatedAt DateTime @updatedAt
|
|
10
|
+
sessions Session[]
|
|
11
|
+
accounts Account[]
|
|
12
|
+
role String @default("USER")
|
|
13
|
+
|
|
14
|
+
@@unique([email])
|
|
15
|
+
@@map("user")
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
model Session {
|
|
19
|
+
id String @id {{defaultId}}
|
|
20
|
+
expiresAt DateTime
|
|
21
|
+
token String @unique
|
|
22
|
+
createdAt DateTime @default(now())
|
|
23
|
+
updatedAt DateTime @updatedAt
|
|
24
|
+
ipAddress String?
|
|
25
|
+
userAgent String?
|
|
26
|
+
userId String
|
|
27
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
28
|
+
|
|
29
|
+
@@index([userId])
|
|
30
|
+
@@map("session")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
model Account {
|
|
34
|
+
id String @id {{defaultId}}
|
|
35
|
+
accountId String
|
|
36
|
+
providerId String
|
|
37
|
+
userId String
|
|
38
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
39
|
+
accessToken String?
|
|
40
|
+
refreshToken String?
|
|
41
|
+
idToken String?
|
|
42
|
+
accessTokenExpiresAt DateTime?
|
|
43
|
+
refreshTokenExpiresAt DateTime?
|
|
44
|
+
scope String?
|
|
45
|
+
password String?
|
|
46
|
+
createdAt DateTime @default(now())
|
|
47
|
+
updatedAt DateTime @updatedAt
|
|
48
|
+
|
|
49
|
+
@@index([userId])
|
|
50
|
+
@@map("account")
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
model Verification {
|
|
54
|
+
id String @id {{defaultId}}
|
|
55
|
+
identifier String
|
|
56
|
+
value String
|
|
57
|
+
expiresAt DateTime
|
|
58
|
+
createdAt DateTime @default(now())
|
|
59
|
+
updatedAt DateTime @updatedAt
|
|
60
|
+
|
|
61
|
+
@@index([identifier])
|
|
62
|
+
@@map("verification")
|
|
63
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "better-auth",
|
|
3
|
+
"type": "auth",
|
|
4
|
+
"priority": 10,
|
|
5
|
+
"operations": [
|
|
6
|
+
{
|
|
7
|
+
"type": "create-file",
|
|
8
|
+
"description": "Create Better Auth configuration file",
|
|
9
|
+
"source": "lib/auth.ts",
|
|
10
|
+
"destination": "lib/auth.ts",
|
|
11
|
+
"condition": { "framework": ["nextjs", "express"] }
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"type": "create-file",
|
|
15
|
+
"description": "Create email service for sending emails",
|
|
16
|
+
"source": "lib/email-service.ts",
|
|
17
|
+
"destination": "lib/email/email-service.ts",
|
|
18
|
+
"condition": { "framework": ["nextjs", "express"] }
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"type": "create-file",
|
|
22
|
+
"description": "Create email templates",
|
|
23
|
+
"source": "lib/email-templates.ts",
|
|
24
|
+
"destination": "lib/email/email-templates.ts",
|
|
25
|
+
"condition": { "framework": ["nextjs", "express"] }
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"type": "create-file",
|
|
29
|
+
"description": "Create Better Auth API routes for Next.js",
|
|
30
|
+
"source": "api/auth/[...all]/route.ts",
|
|
31
|
+
"destination": "app/api/auth/[...all]/route.ts",
|
|
32
|
+
"condition": { "framework": "nextjs" }
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"type": "create-file",
|
|
36
|
+
"description": "Create Better Auth client for React",
|
|
37
|
+
"source": "lib/auth-client.ts",
|
|
38
|
+
"destination": "lib/auth-client.ts",
|
|
39
|
+
"condition": { "framework": ["nextjs", "react"] }
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"type": "create-file",
|
|
43
|
+
"description": "Create Better Auth middleware for Next.js",
|
|
44
|
+
"destination": "proxy.ts",
|
|
45
|
+
"condition": { "framework": "nextjs" },
|
|
46
|
+
"content": "import { auth } from \"@/lib/auth\";\n\nexport default auth((req) => {\n console.log('middleware', req.auth)\n})\n\nexport const config = {\n matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],\n}"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"type": "patch-file",
|
|
50
|
+
"description": "Add Better Auth schema to Prisma schema",
|
|
51
|
+
"destination": "prisma/schema.prisma",
|
|
52
|
+
"condition": { "database": "prisma" },
|
|
53
|
+
"operations": [
|
|
54
|
+
{
|
|
55
|
+
"type": "add-to-bottom",
|
|
56
|
+
"source": "prisma/schema.prisma"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"better-auth": "^1.4.12",
|
|
63
|
+
"nodemailer": "^7.0.12"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@types/nodemailer": "^7.0.5"
|
|
67
|
+
},
|
|
68
|
+
"scripts": {},
|
|
69
|
+
"envVars": {
|
|
70
|
+
"BETTER_AUTH_SECRET": "",
|
|
71
|
+
"BETTER_AUTH_URL": "http://localhost:3000",
|
|
72
|
+
"EMAIL_HOST": "smtp.gmail.com",
|
|
73
|
+
"EMAIL_PORT": "587",
|
|
74
|
+
"EMAIL_USER": "",
|
|
75
|
+
"EMAIL_PASS": "",
|
|
76
|
+
"EMAIL_FROM": "noreply@yourapp.com"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "better-auth",
|
|
3
|
+
"displayName": "Better Auth",
|
|
4
|
+
"description": "Modern authentication with Better Auth",
|
|
5
|
+
"category": "auth",
|
|
6
|
+
"provider": "better-auth",
|
|
7
|
+
"supportedFrameworks": ["nextjs", "express", "react"],
|
|
8
|
+
"compatibility": {
|
|
9
|
+
"frameworks": ["nextjs", "express", "react"],
|
|
10
|
+
"databases": ["prisma", "mongoose"],
|
|
11
|
+
"languages": ["typescript", "javascript"],
|
|
12
|
+
"packageManagers": ["npm", "yarn", "pnpm", "bun"]
|
|
13
|
+
},
|
|
14
|
+
"databaseAdapters": {
|
|
15
|
+
"prisma-postgresql": {
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@prisma/adapter-pg": "^5.0.0",
|
|
18
|
+
"pg": "^8.0.0"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"prisma-mongodb": {
|
|
22
|
+
"dependencies": {}
|
|
23
|
+
},
|
|
24
|
+
"prisma-mysql": {
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@prisma/adapter-mariadb": "^5.0.0",
|
|
27
|
+
"mysql2": "^3.0.0"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"prisma-sqlite": {
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@prisma/adapter-better-sqlite3": "^5.0.0",
|
|
33
|
+
"better-sqlite3": "^9.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
|
|
3
|
+
type MongooseCache = {
|
|
4
|
+
conn: typeof mongoose | null;
|
|
5
|
+
promise: Promise<typeof mongoose> | null;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const globalWithMongoose = globalThis as unknown as {
|
|
9
|
+
mongoose: MongooseCache;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// Initialize the cache if not already present
|
|
13
|
+
const cached = globalWithMongoose.mongoose || {
|
|
14
|
+
conn: null,
|
|
15
|
+
promise: null,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
if (!globalWithMongoose.mongoose) {
|
|
19
|
+
globalWithMongoose.mongoose = cached;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function dbConnect(): Promise<typeof mongoose> {
|
|
23
|
+
if (cached.conn) {
|
|
24
|
+
return cached.conn;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const uri = process.env.DATABASE_URL as string;
|
|
28
|
+
|
|
29
|
+
if (!cached.promise) {
|
|
30
|
+
const opts = {
|
|
31
|
+
bufferCommands: false,
|
|
32
|
+
connectTimeoutMS: 10000,
|
|
33
|
+
serverSelectionTimeoutMS: 10000,
|
|
34
|
+
// serverApi removed: not needed for mongoose-only connection
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
cached.promise = mongoose
|
|
38
|
+
.connect(uri, opts)
|
|
39
|
+
.then(async (mongooseInstance: typeof mongoose) => {
|
|
40
|
+
console.info("MongoDB connected successfully");
|
|
41
|
+
if (mongoose.connection.db) {
|
|
42
|
+
await mongoose.connection.db.admin().command({ ping: 1 });
|
|
43
|
+
console.info("Pinged your deployment. You successfully connected to MongoDB!");
|
|
44
|
+
}
|
|
45
|
+
return mongooseInstance;
|
|
46
|
+
})
|
|
47
|
+
.catch((error: Error) => {
|
|
48
|
+
console.error("MongoDB connection failed", { error });
|
|
49
|
+
throw error;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
cached.conn = await cached.promise;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
cached.promise = null;
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return cached.conn;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { dbConnect as mongoose, dbConnect as connectMongoose };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import mongoose, { Document, Schema } from "mongoose";
|
|
2
|
+
|
|
3
|
+
export interface IUser extends Document {
|
|
4
|
+
name: string;
|
|
5
|
+
email: string;
|
|
6
|
+
createdAt: Date;
|
|
7
|
+
updatedAt: Date;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const UserSchema: Schema = new Schema(
|
|
11
|
+
{
|
|
12
|
+
name: {
|
|
13
|
+
type: String,
|
|
14
|
+
required: true,
|
|
15
|
+
trim: true,
|
|
16
|
+
},
|
|
17
|
+
email: {
|
|
18
|
+
type: String,
|
|
19
|
+
required: true,
|
|
20
|
+
unique: true,
|
|
21
|
+
lowercase: true,
|
|
22
|
+
trim: true,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
timestamps: true,
|
|
27
|
+
},
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// Add indexes for better performance
|
|
31
|
+
UserSchema.index({ email: 1 });
|
|
32
|
+
UserSchema.index({ createdAt: -1 });
|
|
33
|
+
|
|
34
|
+
export default mongoose.models.User || mongoose.model<IUser>("User", UserSchema);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mongoose",
|
|
3
|
+
"type": "database",
|
|
4
|
+
"priority": 5,
|
|
5
|
+
"operations": [
|
|
6
|
+
{
|
|
7
|
+
"type": "create-file",
|
|
8
|
+
"source": "lib/db.ts",
|
|
9
|
+
"destination": "src/lib/db.ts"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"type": "create-file",
|
|
13
|
+
"source": "models/User.ts",
|
|
14
|
+
"destination": "src/lib/models.ts"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"mongoose": "^8.8.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {},
|
|
21
|
+
"envVars": {
|
|
22
|
+
"MONGODB_URI": "mongodb://localhost:27017/database_name"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mongoose",
|
|
3
|
+
"displayName": "Mongoose (MongoDB)",
|
|
4
|
+
"description": "Mongoose ODM for MongoDB database",
|
|
5
|
+
"category": "database",
|
|
6
|
+
"provider": "mongoose",
|
|
7
|
+
"database": "mongodb",
|
|
8
|
+
"supportedFrameworks": ["nextjs", "express"],
|
|
9
|
+
"compatibility": {
|
|
10
|
+
"frameworks": ["nextjs", "express"],
|
|
11
|
+
"databases": ["mongoose"],
|
|
12
|
+
"languages": ["typescript", "javascript"],
|
|
13
|
+
"packageManagers": ["npm", "yarn", "pnpm", "bun"]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client'
|
|
2
|
+
|
|
3
|
+
const globalForPrisma = globalThis as unknown as {
|
|
4
|
+
prisma: PrismaClient | undefined
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
{{#if prismaProvider == "postgresql"}}
|
|
8
|
+
import { PrismaPg } from "@prisma/adapter-pg";
|
|
9
|
+
|
|
10
|
+
const adapter = new PrismaPg({
|
|
11
|
+
connectionString: process.env.DATABASE_URL!,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const prisma = globalForPrisma.prisma ?? new PrismaClient({
|
|
15
|
+
adapter,
|
|
16
|
+
});
|
|
17
|
+
{{/if}}
|
|
18
|
+
|
|
19
|
+
{{#if prismaProvider == "mongodb"}}
|
|
20
|
+
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
|
|
21
|
+
{{/if}}
|
|
22
|
+
|
|
23
|
+
{{#if prismaProvider == "mysql"}}
|
|
24
|
+
import { PrismaMariaDb } from '@prisma/adapter-mariadb';
|
|
25
|
+
|
|
26
|
+
const adapter = new PrismaMariaDb({
|
|
27
|
+
host: process.env.DATABASE_HOST,
|
|
28
|
+
user: process.env.DATABASE_USER,
|
|
29
|
+
password: process.env.DATABASE_PASSWORD,
|
|
30
|
+
database: process.env.DATABASE_NAME,
|
|
31
|
+
connectionLimit: 5
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter });
|
|
35
|
+
{{/if}}
|
|
36
|
+
|
|
37
|
+
{{#if prismaProvider == "sqlite"}}
|
|
38
|
+
import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
|
|
39
|
+
|
|
40
|
+
const adapter = new PrismaBetterSqlite3({ url: process.env.DATABASE_URL });
|
|
41
|
+
|
|
42
|
+
export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter });
|
|
43
|
+
{{/if}}
|
|
44
|
+
|
|
45
|
+
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prisma",
|
|
3
|
+
"type": "database",
|
|
4
|
+
"priority": 5,
|
|
5
|
+
"operations": [
|
|
6
|
+
{
|
|
7
|
+
"type": "create-file",
|
|
8
|
+
"source": "prisma/schema.prisma",
|
|
9
|
+
"destination": "prisma/schema.prisma"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"type": "create-file",
|
|
13
|
+
"source": "prisma.config.ts",
|
|
14
|
+
"destination": "prisma.config.ts"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"type": "create-file",
|
|
18
|
+
"source": "lib/prisma.ts",
|
|
19
|
+
"destination": "lib/prisma.ts",
|
|
20
|
+
"condition": {
|
|
21
|
+
"framework": ["nextjs", "express"]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"prisma": "^7.2.0",
|
|
27
|
+
"@prisma/client": "^7.2.0",
|
|
28
|
+
"dotenv": "^17.2.3"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"prisma": "^7.2.0"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"db:generate": "prisma generate",
|
|
35
|
+
"db:push": "prisma db push",
|
|
36
|
+
"db:seed": "tsx prisma/seed.ts",
|
|
37
|
+
"db:migrate": "prisma migrate dev",
|
|
38
|
+
"db:studio": "prisma studio"
|
|
39
|
+
},
|
|
40
|
+
"envVars": {
|
|
41
|
+
"DATABASE_URL": "postgresql://username:password@localhost:5432/database_name"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prisma",
|
|
3
|
+
"displayName": "Prisma",
|
|
4
|
+
"description": "Prisma ORM",
|
|
5
|
+
"category": "database",
|
|
6
|
+
"provider": "prisma",
|
|
7
|
+
"supportedFrameworks": ["nextjs", "express"],
|
|
8
|
+
"compatibility": {
|
|
9
|
+
"frameworks": ["nextjs", "express"],
|
|
10
|
+
"databases": ["prisma"],
|
|
11
|
+
"languages": ["typescript", "javascript"],
|
|
12
|
+
"packageManagers": ["npm", "yarn", "pnpm", "bun"]
|
|
13
|
+
},
|
|
14
|
+
"postInstall": [
|
|
15
|
+
"npx prisma generate"
|
|
16
|
+
]
|
|
17
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stackkit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Production-ready CLI to create and extend JavaScript or TypeScript apps with modular stacks.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"stackkit": "./bin/stackkit.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "commonjs",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"bin",
|
|
13
|
+
"templates",
|
|
14
|
+
"modules"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/tariqul420/stackkit.git",
|
|
19
|
+
"directory": "apps/create-stackkit"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://stackkit.tariqul.dev",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/tariqul420/stackkit/issues"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "tsc --watch",
|
|
27
|
+
"build": "npm run clean && tsc && npm run copy-assets",
|
|
28
|
+
"copy-assets": "cp -r ../../templates . && cp -r ../../modules .",
|
|
29
|
+
"clean": "rm -rf dist templates modules",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"prepublishOnly": "npm run build"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"stackkit",
|
|
35
|
+
"cli",
|
|
36
|
+
"project-generator",
|
|
37
|
+
"scaffold",
|
|
38
|
+
"boilerplate",
|
|
39
|
+
|
|
40
|
+
"javascript",
|
|
41
|
+
"typescript",
|
|
42
|
+
|
|
43
|
+
"nextjs",
|
|
44
|
+
"react",
|
|
45
|
+
"vite",
|
|
46
|
+
"express",
|
|
47
|
+
|
|
48
|
+
"prisma",
|
|
49
|
+
"mongoose",
|
|
50
|
+
"mongodb",
|
|
51
|
+
"postgresql",
|
|
52
|
+
|
|
53
|
+
"authentication"
|
|
54
|
+
],
|
|
55
|
+
"author": "Tariqul Islam",
|
|
56
|
+
"license": "MIT",
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"chalk": "^4.1.2",
|
|
59
|
+
"commander": "^12.0.0",
|
|
60
|
+
"detect-package-manager": "^3.0.1",
|
|
61
|
+
"execa": "^5.1.1",
|
|
62
|
+
"fs-extra": "^11.2.0",
|
|
63
|
+
"inquirer": "^9.3.8",
|
|
64
|
+
"ora": "^5.4.1",
|
|
65
|
+
"validate-npm-package-name": "^5.0.1",
|
|
66
|
+
"@babel/core": "^7.28.5",
|
|
67
|
+
"@babel/preset-env": "^7.28.5",
|
|
68
|
+
"@babel/preset-typescript": "^7.28.5",
|
|
69
|
+
"@babel/preset-react": "^7.28.5"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@types/fs-extra": "^11.0.4",
|
|
73
|
+
"@types/inquirer": "^9.0.7",
|
|
74
|
+
"@types/node": "^25.0.8",
|
|
75
|
+
"@types/validate-npm-package-name": "^4.0.2",
|
|
76
|
+
"typescript": "^5.3.3",
|
|
77
|
+
"recast": "^0.20.5",
|
|
78
|
+
"@babel/core": "^7.28.5",
|
|
79
|
+
"@babel/plugin-transform-typescript": "^7.28.5",
|
|
80
|
+
"@babel/parser": "^7.28.5",
|
|
81
|
+
"@babel/plugin-transform-react-jsx": "^7.27.1"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module.exports = [
|
|
2
|
+
// Global ignores
|
|
3
|
+
{
|
|
4
|
+
ignores: ['**/node_modules/**', '**/dist/**', '.env'],
|
|
5
|
+
},
|
|
6
|
+
|
|
7
|
+
// TypeScript files
|
|
8
|
+
{
|
|
9
|
+
files: ['**/*.ts', '**/*.tsx'],
|
|
10
|
+
languageOptions: {
|
|
11
|
+
parser: require('@typescript-eslint/parser'),
|
|
12
|
+
parserOptions: {
|
|
13
|
+
project: './tsconfig.json',
|
|
14
|
+
ecmaVersion: 'latest',
|
|
15
|
+
sourceType: 'module',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
plugins: {
|
|
19
|
+
'@typescript-eslint': require('@typescript-eslint/eslint-plugin'),
|
|
20
|
+
},
|
|
21
|
+
rules: {
|
|
22
|
+
'prefer-const': 'error',
|
|
23
|
+
'no-console': 'off',
|
|
24
|
+
eqeqeq: ['error', 'always'],
|
|
25
|
+
curly: ['error', 'multi-line'],
|
|
26
|
+
'no-implicit-coercion': ['warn', { allow: ['!!'] }],
|
|
27
|
+
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^(?:_|next)$' }],
|
|
28
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
29
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// JavaScript files
|
|
34
|
+
{
|
|
35
|
+
files: ['**/*.js'],
|
|
36
|
+
languageOptions: {
|
|
37
|
+
ecmaVersion: 'latest',
|
|
38
|
+
sourceType: 'module',
|
|
39
|
+
},
|
|
40
|
+
rules: {},
|
|
41
|
+
},
|
|
42
|
+
];
|