stackkit-cli 0.4.2 → 0.4.3
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 +17 -10
- package/bin/stackkit.js +1 -1
- package/dist/commands/add.js +26 -24
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +34 -29
- package/dist/commands/list.js +12 -12
- package/dist/index.js +25 -23
- package/dist/types/index.d.ts +14 -14
- package/dist/utils/code-inject.d.ts +1 -1
- package/dist/utils/code-inject.js +6 -6
- package/dist/utils/detect.d.ts +1 -1
- package/dist/utils/detect.js +48 -44
- package/dist/utils/env-editor.js +20 -20
- package/dist/utils/files.js +4 -4
- package/dist/utils/json-editor.d.ts +3 -3
- package/dist/utils/json-editor.js +10 -14
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.js +8 -8
- package/dist/utils/package-manager.d.ts +2 -2
- package/dist/utils/package-manager.js +33 -26
- package/modules/auth/better-auth-express/adapters/mongoose-mongodb.ts +13 -0
- package/modules/auth/better-auth-express/adapters/prisma-mongodb.ts +15 -0
- package/modules/auth/better-auth-express/adapters/prisma-postgresql.ts +15 -0
- package/modules/auth/better-auth-express/files/lib/auth.ts +1 -1
- package/modules/auth/better-auth-express/files/routes/auth.ts +3 -3
- package/modules/auth/better-auth-express/files/schemas/prisma-mongodb-schema.prisma +72 -0
- package/modules/auth/better-auth-express/files/schemas/prisma-postgresql-schema.prisma +72 -0
- package/modules/auth/better-auth-express/module.json +26 -3
- package/modules/auth/better-auth-nextjs/adapters/mongoose-mongodb.ts +24 -0
- package/modules/auth/better-auth-nextjs/adapters/prisma-mongodb.ts +26 -0
- package/modules/auth/better-auth-nextjs/adapters/prisma-postgresql.ts +26 -0
- package/modules/auth/better-auth-nextjs/files/api/auth/[...all]/route.ts +2 -3
- package/modules/auth/better-auth-nextjs/files/lib/auth.ts +4 -4
- package/modules/auth/better-auth-nextjs/files/schemas/prisma-mongodb-schema.prisma +72 -0
- package/modules/auth/better-auth-nextjs/files/schemas/prisma-postgresql-schema.prisma +72 -0
- package/modules/auth/better-auth-nextjs/module.json +26 -5
- package/modules/auth/better-auth-react/files/lib/auth-client.ts +2 -2
- package/modules/auth/better-auth-react/module.json +7 -5
- package/modules/auth/clerk-express/files/lib/auth.ts +1 -1
- package/modules/auth/clerk-express/module.json +22 -8
- package/modules/auth/clerk-nextjs/files/lib/auth-provider.tsx +1 -1
- package/modules/auth/clerk-nextjs/files/middleware.ts +3 -3
- package/modules/auth/clerk-nextjs/module.json +50 -14
- package/modules/auth/clerk-react/files/lib/auth-provider.tsx +2 -2
- package/modules/auth/clerk-react/module.json +16 -7
- package/modules/database/mongoose-mongodb/files/lib/db.ts +3 -3
- package/modules/database/mongoose-mongodb/module.json +43 -6
- package/modules/database/prisma-mongodb/files/lib/db.ts +2 -2
- package/modules/database/prisma-mongodb/files/prisma/schema.prisma +1 -1
- package/modules/database/prisma-mongodb/module.json +28 -4
- package/modules/database/prisma-postgresql/files/lib/db.ts +2 -2
- package/modules/database/prisma-postgresql/files/prisma/schema.prisma +1 -1
- package/modules/database/prisma-postgresql/module.json +28 -4
- package/package.json +1 -1
- package/templates/express/.env.example +11 -0
- package/templates/express/eslint.config.cjs +42 -0
- package/templates/express/package.json +39 -0
- package/templates/express/src/app.ts +71 -0
- package/templates/express/src/config/env.ts +23 -0
- package/templates/express/src/middlewares/error.middleware.ts +18 -0
- package/templates/{bases/express-base → express}/src/server.ts +2 -2
- package/templates/express/template.json +44 -0
- package/templates/express/tsconfig.json +31 -0
- package/templates/{bases/nextjs-base → nextjs}/app/layout.tsx +1 -5
- package/templates/nextjs/app/page.tsx +57 -0
- package/templates/{bases/nextjs-base → nextjs}/package.json +2 -1
- package/templates/{bases/nextjs-base → nextjs}/template.json +13 -1
- package/templates/react-vite/.env.example +2 -0
- package/templates/react-vite/README.md +85 -0
- package/templates/react-vite/eslint.config.js +23 -0
- package/templates/{bases/react-vite-base → react-vite}/index.html +1 -0
- package/templates/{bases/react-vite-base → react-vite}/package.json +16 -2
- package/templates/react-vite/src/api/client.ts +47 -0
- package/templates/react-vite/src/api/services/user.service.ts +18 -0
- package/templates/react-vite/src/components/ErrorBoundary.tsx +51 -0
- package/templates/react-vite/src/components/Layout.tsx +13 -0
- package/templates/react-vite/src/components/Loading.tsx +8 -0
- package/templates/react-vite/src/components/SEO.tsx +49 -0
- package/templates/react-vite/src/config/constants.ts +5 -0
- package/templates/react-vite/src/hooks/index.ts +64 -0
- package/templates/react-vite/src/index.css +1 -0
- package/templates/react-vite/src/lib/queryClient.ts +12 -0
- package/templates/react-vite/src/main.tsx +22 -0
- package/templates/react-vite/src/pages/About.tsx +78 -0
- package/templates/react-vite/src/pages/Home.tsx +49 -0
- package/templates/react-vite/src/pages/NotFound.tsx +24 -0
- package/templates/react-vite/src/pages/UserProfile.tsx +40 -0
- package/templates/react-vite/src/router.tsx +33 -0
- package/templates/react-vite/src/types/api.d.ts +20 -0
- package/templates/react-vite/src/types/user.d.ts +6 -0
- package/templates/react-vite/src/utils/helpers.ts +51 -0
- package/templates/react-vite/src/utils/storage.ts +35 -0
- package/templates/react-vite/src/vite-env.d.ts +11 -0
- package/templates/react-vite/template.json +46 -0
- package/templates/react-vite/tsconfig.json +4 -0
- package/templates/react-vite/vite.config.ts +13 -0
- package/modules/database/drizzle-postgresql/files/drizzle.config.ts +0 -10
- package/modules/database/drizzle-postgresql/files/lib/db.ts +0 -7
- package/modules/database/drizzle-postgresql/files/lib/schema.ts +0 -8
- package/modules/database/drizzle-postgresql/module.json +0 -35
- package/templates/bases/express-base/.env.example +0 -2
- package/templates/bases/express-base/package.json +0 -23
- package/templates/bases/express-base/src/app.ts +0 -34
- package/templates/bases/express-base/src/config/env.ts +0 -14
- package/templates/bases/express-base/src/middlewares/error.middleware.ts +0 -12
- package/templates/bases/express-base/template.json +0 -7
- package/templates/bases/express-base/tsconfig.json +0 -14
- package/templates/bases/nextjs-base/app/page.tsx +0 -65
- package/templates/bases/react-vite-base/README.md +0 -73
- package/templates/bases/react-vite-base/eslint.config.js +0 -23
- package/templates/bases/react-vite-base/src/App.css +0 -42
- package/templates/bases/react-vite-base/src/App.tsx +0 -35
- package/templates/bases/react-vite-base/src/index.css +0 -68
- package/templates/bases/react-vite-base/src/main.tsx +0 -10
- package/templates/bases/react-vite-base/template.json +0 -19
- package/templates/bases/react-vite-base/tsconfig.json +0 -7
- package/templates/bases/react-vite-base/vite.config.ts +0 -7
- /package/templates/{bases/nextjs-base → nextjs}/README.md +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/app/favicon.ico +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/app/globals.css +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/eslint.config.mjs +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/next.config.ts +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/postcss.config.mjs +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/public/file.svg +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/public/globe.svg +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/public/next.svg +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/public/vercel.svg +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/public/window.svg +0 -0
- /package/templates/{bases/nextjs-base → nextjs}/tsconfig.json +0 -0
- /package/templates/{bases/react-vite-base → react-vite}/public/vite.svg +0 -0
- /package/templates/{bases/react-vite-base → react-vite}/src/assets/react.svg +0 -0
- /package/templates/{bases/react-vite-base → react-vite}/tsconfig.app.json +0 -0
- /package/templates/{bases/react-vite-base → react-vite}/tsconfig.node.json +0 -0
|
@@ -1,18 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongoose-mongodb",
|
|
3
3
|
"displayName": "Mongoose + MongoDB",
|
|
4
|
-
"description": "Mongoose ODM for MongoDB",
|
|
4
|
+
"description": "Mongoose ODM for MongoDB database",
|
|
5
5
|
"category": "database",
|
|
6
|
+
"provider": "mongoose",
|
|
7
|
+
"database": "mongodb",
|
|
8
|
+
"supportedFrameworks": ["nextjs", "express"],
|
|
6
9
|
"dependencies": {
|
|
7
10
|
"mongoose": "^8.8.4"
|
|
8
11
|
},
|
|
9
|
-
"
|
|
10
|
-
|
|
12
|
+
"devDependencies": {},
|
|
13
|
+
"envVars": [
|
|
14
|
+
{
|
|
15
|
+
"key": "MONGODB_URI",
|
|
16
|
+
"value": "mongodb://localhost:27017/myapp",
|
|
17
|
+
"description": "MongoDB connection string",
|
|
18
|
+
"required": true
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"frameworkPatches": {
|
|
22
|
+
"express": {
|
|
23
|
+
"tsconfig.json": {
|
|
24
|
+
"merge": {
|
|
25
|
+
"compilerOptions": {
|
|
26
|
+
"paths": {
|
|
27
|
+
"@/*": ["./src/*"],
|
|
28
|
+
"@/models/*": ["./src/models/*"]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"include": ["src/**/*", "src/models/**/*"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"nextjs": {
|
|
36
|
+
"tsconfig.json": {
|
|
37
|
+
"merge": {
|
|
38
|
+
"compilerOptions": {
|
|
39
|
+
"paths": {
|
|
40
|
+
"@/models/*": ["./models/*"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
11
46
|
},
|
|
12
|
-
"
|
|
47
|
+
"patches": [
|
|
13
48
|
{
|
|
14
|
-
"
|
|
15
|
-
"
|
|
49
|
+
"type": "create-file",
|
|
50
|
+
"description": "Create MongoDB connection with Mongoose",
|
|
51
|
+
"source": "lib/db.ts",
|
|
52
|
+
"destination": "{{lib}}/db.ts"
|
|
16
53
|
}
|
|
17
54
|
]
|
|
18
55
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PrismaClient } from
|
|
1
|
+
import { PrismaClient } from "@prisma/client";
|
|
2
2
|
|
|
3
3
|
const globalForPrisma = globalThis as unknown as {
|
|
4
4
|
prisma: PrismaClient | undefined;
|
|
@@ -6,4 +6,4 @@ const globalForPrisma = globalThis as unknown as {
|
|
|
6
6
|
|
|
7
7
|
export const db = globalForPrisma.prisma ?? new PrismaClient();
|
|
8
8
|
|
|
9
|
-
if (process.env.NODE_ENV !==
|
|
9
|
+
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = db;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "prisma-mongodb",
|
|
3
3
|
"displayName": "Prisma + MongoDB",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Prisma ORM with MongoDB database",
|
|
5
5
|
"category": "database",
|
|
6
|
+
"provider": "prisma",
|
|
7
|
+
"database": "mongodb",
|
|
6
8
|
"supportedFrameworks": ["nextjs", "express"],
|
|
7
9
|
"dependencies": {
|
|
8
10
|
"@prisma/client": "^6.1.0"
|
|
@@ -18,17 +20,39 @@
|
|
|
18
20
|
"required": true
|
|
19
21
|
}
|
|
20
22
|
],
|
|
23
|
+
"frameworkPatches": {
|
|
24
|
+
"express": {
|
|
25
|
+
"tsconfig.json": {
|
|
26
|
+
"merge": {
|
|
27
|
+
"compilerOptions": {
|
|
28
|
+
"paths": {
|
|
29
|
+
"@/*": ["./src/*"]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"include": ["src/**/*"],
|
|
33
|
+
"exclude": ["node_modules", "dist", "prisma/migrations"]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"nextjs": {
|
|
38
|
+
"tsconfig.json": {
|
|
39
|
+
"merge": {
|
|
40
|
+
"exclude": ["node_modules", ".next", "out", "prisma/migrations"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
21
45
|
"patches": [
|
|
22
46
|
{
|
|
23
47
|
"type": "create-file",
|
|
24
48
|
"description": "Create Prisma schema for MongoDB",
|
|
25
|
-
"source": "prisma/schema.prisma",
|
|
49
|
+
"source": "files/prisma/schema.prisma",
|
|
26
50
|
"destination": "prisma/schema.prisma"
|
|
27
51
|
},
|
|
28
52
|
{
|
|
29
53
|
"type": "create-file",
|
|
30
54
|
"description": "Create Prisma client singleton",
|
|
31
|
-
"source": "lib/db.ts",
|
|
55
|
+
"source": "files/lib/db.ts",
|
|
32
56
|
"destination": "{{lib}}/db.ts"
|
|
33
57
|
}
|
|
34
58
|
],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PrismaClient } from
|
|
1
|
+
import { PrismaClient } from "@prisma/client";
|
|
2
2
|
|
|
3
3
|
const globalForPrisma = globalThis as unknown as {
|
|
4
4
|
prisma: PrismaClient | undefined;
|
|
@@ -6,4 +6,4 @@ const globalForPrisma = globalThis as unknown as {
|
|
|
6
6
|
|
|
7
7
|
export const db = globalForPrisma.prisma ?? new PrismaClient();
|
|
8
8
|
|
|
9
|
-
if (process.env.NODE_ENV !==
|
|
9
|
+
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = db;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "prisma-postgresql",
|
|
3
3
|
"displayName": "Prisma + PostgreSQL",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Prisma ORM with PostgreSQL database",
|
|
5
5
|
"category": "database",
|
|
6
|
+
"provider": "prisma",
|
|
7
|
+
"database": "postgresql",
|
|
6
8
|
"supportedFrameworks": ["nextjs", "express"],
|
|
7
9
|
"dependencies": {
|
|
8
10
|
"@prisma/client": "^6.1.0"
|
|
@@ -18,17 +20,39 @@
|
|
|
18
20
|
"required": true
|
|
19
21
|
}
|
|
20
22
|
],
|
|
23
|
+
"frameworkPatches": {
|
|
24
|
+
"express": {
|
|
25
|
+
"tsconfig.json": {
|
|
26
|
+
"merge": {
|
|
27
|
+
"compilerOptions": {
|
|
28
|
+
"paths": {
|
|
29
|
+
"@/*": ["./src/*"]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"include": ["src/**/*"],
|
|
33
|
+
"exclude": ["node_modules", "dist", "prisma/migrations"]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"nextjs": {
|
|
38
|
+
"tsconfig.json": {
|
|
39
|
+
"merge": {
|
|
40
|
+
"exclude": ["node_modules", ".next", "out", "prisma/migrations"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
21
45
|
"patches": [
|
|
22
46
|
{
|
|
23
47
|
"type": "create-file",
|
|
24
48
|
"description": "Create Prisma schema",
|
|
25
|
-
"source": "prisma/schema.prisma",
|
|
49
|
+
"source": "files/prisma/schema.prisma",
|
|
26
50
|
"destination": "prisma/schema.prisma"
|
|
27
51
|
},
|
|
28
52
|
{
|
|
29
53
|
"type": "create-file",
|
|
30
54
|
"description": "Create Prisma client singleton",
|
|
31
|
-
"source": "lib/db.ts",
|
|
55
|
+
"source": "files/lib/db.ts",
|
|
32
56
|
"destination": "{{lib}}/db.ts"
|
|
33
57
|
}
|
|
34
58
|
],
|
package/package.json
CHANGED
|
@@ -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
|
+
];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "tsx watch src/server.ts",
|
|
8
|
+
"clean": "rimraf dist",
|
|
9
|
+
"prebuild": "npm run clean",
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"lint": "eslint src --ext .ts",
|
|
12
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
13
|
+
"start": "node dist/server.js",
|
|
14
|
+
"start:prod": "cross-env NODE_ENV=production node dist/server.js"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"compression": "^1.7.4",
|
|
18
|
+
"cors": "^2.8.5",
|
|
19
|
+
"dotenv": "^16.4.7",
|
|
20
|
+
"express": "^4.21.2",
|
|
21
|
+
"express-rate-limit": "^6.7.0",
|
|
22
|
+
"helmet": "^7.0.0",
|
|
23
|
+
"morgan": "^1.10.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/compression": "^1.8.1",
|
|
27
|
+
"@types/cors": "^2.8.17",
|
|
28
|
+
"@types/express": "^4.17.21",
|
|
29
|
+
"@types/morgan": "^1.9.4",
|
|
30
|
+
"@types/node": "^22.10.5",
|
|
31
|
+
"@typescript-eslint/eslint-plugin": "^8.52.0",
|
|
32
|
+
"@typescript-eslint/parser": "^8.52.0",
|
|
33
|
+
"cross-env": "^7.0.3",
|
|
34
|
+
"eslint": "^9.39.2",
|
|
35
|
+
"rimraf": "^5.0.0",
|
|
36
|
+
"tsx": "^4.19.2",
|
|
37
|
+
"typescript": "^5.7.2"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import compression from "compression";
|
|
2
|
+
import cors from "cors";
|
|
3
|
+
import express, { Application, NextFunction, Request, Response } from "express";
|
|
4
|
+
import rateLimit from "express-rate-limit";
|
|
5
|
+
import helmet from "helmet";
|
|
6
|
+
import morgan from "morgan";
|
|
7
|
+
import { env } from "./config/env";
|
|
8
|
+
import { errorHandler } from "./middlewares/error.middleware";
|
|
9
|
+
|
|
10
|
+
// app initialization
|
|
11
|
+
const app: Application = express();
|
|
12
|
+
app.use(express.json());
|
|
13
|
+
|
|
14
|
+
// trust proxy when behind reverse proxy (like Heroku, Vercel, Load Balancers)
|
|
15
|
+
if (env.app.trust_proxy) {
|
|
16
|
+
app.set("trust proxy", 1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// security headers
|
|
20
|
+
app.use(helmet());
|
|
21
|
+
|
|
22
|
+
// response compression
|
|
23
|
+
app.use(compression());
|
|
24
|
+
|
|
25
|
+
// rate limiting
|
|
26
|
+
const limiter = rateLimit({
|
|
27
|
+
windowMs: env.app.rateLimit.windowMs,
|
|
28
|
+
max: env.app.rateLimit.max,
|
|
29
|
+
standardHeaders: true,
|
|
30
|
+
legacyHeaders: false,
|
|
31
|
+
});
|
|
32
|
+
app.use(limiter);
|
|
33
|
+
|
|
34
|
+
// logging
|
|
35
|
+
if (env.node.isProduction) {
|
|
36
|
+
app.use(morgan("combined"));
|
|
37
|
+
} else {
|
|
38
|
+
app.use(morgan("dev"));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// cors configuration
|
|
42
|
+
app.use(
|
|
43
|
+
cors({
|
|
44
|
+
origin: [env.app.site_url],
|
|
45
|
+
credentials: true,
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// Home page route
|
|
50
|
+
app.get("/", (req: Request, res: Response) => {
|
|
51
|
+
res.json({
|
|
52
|
+
title: "Welcome to your Express app",
|
|
53
|
+
description:
|
|
54
|
+
"Built with StackKit - A production-ready Express template with TypeScript, security, and best practices.",
|
|
55
|
+
version: "1.0.0",
|
|
56
|
+
docs: "https://github.com/tariqul420/stackkit",
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// unhandled routes
|
|
61
|
+
app.use((req: Request, res: Response, next: NextFunction) => {
|
|
62
|
+
const error: any = new Error(`Can't find ${req.originalUrl} on this server!`);
|
|
63
|
+
error.status = 404;
|
|
64
|
+
|
|
65
|
+
next(error);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Global error handler
|
|
69
|
+
app.use(errorHandler);
|
|
70
|
+
|
|
71
|
+
export default app;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import dotenv from "dotenv";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
dotenv.config({ path: path.join(process.cwd(), ".env") });
|
|
5
|
+
|
|
6
|
+
const env = {
|
|
7
|
+
app: {
|
|
8
|
+
port: Number(process.env.PORT) || 3000,
|
|
9
|
+
url: process.env.APP_URL || "http://localhost:3000",
|
|
10
|
+
site_url: process.env.SITE_URL || "http://localhost:5173",
|
|
11
|
+
trust_proxy: (process.env.TRUST_PROXY || "false") === "true",
|
|
12
|
+
rateLimit: {
|
|
13
|
+
max: Number(process.env.RATE_LIMIT_MAX) || 100,
|
|
14
|
+
windowMs: Number(process.env.RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
node: {
|
|
18
|
+
env: process.env.NODE_ENV || "development",
|
|
19
|
+
isProduction: (process.env.NODE_ENV || "development") === "production",
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { env };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NextFunction, Request, Response } from "express";
|
|
2
|
+
import { env } from "../config/env";
|
|
3
|
+
|
|
4
|
+
export const errorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {
|
|
5
|
+
const statusCode = err.status || 500;
|
|
6
|
+
const errorMessage = err?.message || "Internal server error!";
|
|
7
|
+
|
|
8
|
+
const payload: any = {
|
|
9
|
+
success: false,
|
|
10
|
+
message: errorMessage,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
if (!env.node.isProduction) {
|
|
14
|
+
payload.errors = err?.stack || err;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
res.status(statusCode).json(payload);
|
|
18
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "express-base",
|
|
3
|
+
"displayName": "Express.js",
|
|
4
|
+
"framework": "express",
|
|
5
|
+
"description": "Express.js REST API with TypeScript",
|
|
6
|
+
"files": ["src/", ".env.example", ".gitignore", "package.json", "tsconfig.json"],
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "tsx watch src/server.ts",
|
|
9
|
+
"clean": "rimraf dist",
|
|
10
|
+
"prebuild": "npm run clean",
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"lint": "eslint src --ext .ts",
|
|
13
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
14
|
+
"start": "node dist/server.js",
|
|
15
|
+
"start:prod": "cross-env NODE_ENV=production node dist/server.js"
|
|
16
|
+
},
|
|
17
|
+
"jsScripts": {
|
|
18
|
+
"dev": "tsx --watch src/server.js",
|
|
19
|
+
"clean": "rimraf dist",
|
|
20
|
+
"prebuild": "npm run clean",
|
|
21
|
+
"build": "echo 'No build step for JavaScript'",
|
|
22
|
+
"lint": "eslint src --ext .js",
|
|
23
|
+
"lint:fix": "eslint src --ext .js --fix",
|
|
24
|
+
"start": "node src/server.js",
|
|
25
|
+
"start:prod": "cross-env NODE_ENV=production node src/server.js"
|
|
26
|
+
},
|
|
27
|
+
"fileReplacements": [
|
|
28
|
+
{
|
|
29
|
+
"file": "src/server.js",
|
|
30
|
+
"from": "import app from './app'",
|
|
31
|
+
"to": "import app from './app.js'"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"file": "src/app.js",
|
|
35
|
+
"from": "import { env } from './config/env'",
|
|
36
|
+
"to": "import { env } from './config/env.js'"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"file": "src/app.js",
|
|
40
|
+
"from": "import { errorHandler } from './middlewares/error.middleware'",
|
|
41
|
+
"to": "import { errorHandler } from './middlewares/error.middleware.js'"
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"rootDir": "./src",
|
|
4
|
+
"outDir": "./dist",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"target": "ES2023",
|
|
8
|
+
"lib": ["ES2023"],
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"allowSyntheticDefaultImports": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
"sourceMap": true,
|
|
16
|
+
"declaration": false,
|
|
17
|
+
"declarationMap": false,
|
|
18
|
+
"removeComments": false,
|
|
19
|
+
"noImplicitAny": true,
|
|
20
|
+
"noImplicitReturns": true,
|
|
21
|
+
"noImplicitThis": true,
|
|
22
|
+
"noUnusedLocals": true,
|
|
23
|
+
"noUnusedParameters": true,
|
|
24
|
+
"exactOptionalPropertyTypes": true,
|
|
25
|
+
"noEmitOnError": true,
|
|
26
|
+
"incremental": false,
|
|
27
|
+
"ignoreDeprecations": "5.0"
|
|
28
|
+
},
|
|
29
|
+
"include": ["src/**/*"],
|
|
30
|
+
"exclude": ["node_modules", "dist"]
|
|
31
|
+
}
|
|
@@ -24,11 +24,7 @@ export default function RootLayout({
|
|
|
24
24
|
}>) {
|
|
25
25
|
return (
|
|
26
26
|
<html lang="en">
|
|
27
|
-
<body
|
|
28
|
-
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
29
|
-
>
|
|
30
|
-
{children}
|
|
31
|
-
</body>
|
|
27
|
+
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>{children}</body>
|
|
32
28
|
</html>
|
|
33
29
|
);
|
|
34
30
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import Image from "next/image";
|
|
2
|
+
|
|
3
|
+
export default function Home() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
|
|
6
|
+
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
|
|
7
|
+
<div className="flex items-center gap-4 mb-8">
|
|
8
|
+
<div className="text-2xl font-bold text-black dark:text-white">Stackkit</div>
|
|
9
|
+
<span className="text-xl text-zinc-400">+</span>
|
|
10
|
+
<Image
|
|
11
|
+
className="dark:invert"
|
|
12
|
+
src="/next.svg"
|
|
13
|
+
alt="Next.js logo"
|
|
14
|
+
width={100}
|
|
15
|
+
height={20}
|
|
16
|
+
priority
|
|
17
|
+
/>
|
|
18
|
+
</div>
|
|
19
|
+
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
|
|
20
|
+
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
|
|
21
|
+
To get started, edit the page.tsx file.
|
|
22
|
+
</h1>
|
|
23
|
+
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
|
|
24
|
+
This template includes Next.js, Tailwind CSS, and Stackkit best practices. Check out the{" "}
|
|
25
|
+
<a
|
|
26
|
+
href="https://github.com/tariqul420/stackkit"
|
|
27
|
+
className="font-medium text-zinc-950 dark:text-zinc-50 hover:underline"
|
|
28
|
+
target="_blank"
|
|
29
|
+
rel="noopener noreferrer"
|
|
30
|
+
>
|
|
31
|
+
Stackkit repository
|
|
32
|
+
</a>{" "}
|
|
33
|
+
for more info.
|
|
34
|
+
</p>
|
|
35
|
+
</div>
|
|
36
|
+
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
|
|
37
|
+
<a
|
|
38
|
+
className="flex h-12 w-full items-center justify-center rounded-full bg-white text-black px-5 transition-colors hover:bg-zinc-200 md:w-40"
|
|
39
|
+
href="https://nextjs.org/docs"
|
|
40
|
+
target="_blank"
|
|
41
|
+
rel="noopener noreferrer"
|
|
42
|
+
>
|
|
43
|
+
Documentation
|
|
44
|
+
</a>
|
|
45
|
+
<a
|
|
46
|
+
className="flex h-12 w-full items-center justify-center rounded-full bg-black text-white px-5 transition-colors hover:bg-zinc-900 md:w-40"
|
|
47
|
+
href="https://github.com/tariqul420/stackkit"
|
|
48
|
+
target="_blank"
|
|
49
|
+
rel="noopener noreferrer"
|
|
50
|
+
>
|
|
51
|
+
Stackkit GitHub
|
|
52
|
+
</a>
|
|
53
|
+
</div>
|
|
54
|
+
</main>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -14,5 +14,17 @@
|
|
|
14
14
|
"postcss.config.mjs",
|
|
15
15
|
"README.md",
|
|
16
16
|
"tsconfig.json"
|
|
17
|
-
]
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"dev": "next dev",
|
|
20
|
+
"build": "next build",
|
|
21
|
+
"start": "next start",
|
|
22
|
+
"lint": "eslint"
|
|
23
|
+
},
|
|
24
|
+
"jsScripts": {
|
|
25
|
+
"dev": "next dev",
|
|
26
|
+
"build": "next build",
|
|
27
|
+
"start": "next start",
|
|
28
|
+
"lint": "eslint"
|
|
29
|
+
}
|
|
18
30
|
}
|