stackkit 0.2.6 → 0.2.7
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/cli/create.js +1 -2
- package/dist/cli/list.js +73 -83
- package/dist/index.js +25 -44
- package/dist/lib/constants.d.ts +110 -0
- package/dist/lib/constants.js +112 -0
- package/dist/lib/env/env-editor.js +41 -47
- package/dist/lib/fs/files.d.ts +0 -1
- package/dist/lib/fs/files.js +12 -40
- package/dist/lib/generation/code-generator.d.ts +4 -1
- package/dist/lib/generation/code-generator.js +36 -10
- package/dist/lib/pm/package-manager.d.ts +1 -1
- package/dist/lib/pm/package-manager.js +130 -14
- package/dist/lib/ui/logger.d.ts +8 -1
- package/dist/lib/ui/logger.js +60 -3
- package/dist/lib/utils/fs-helpers.d.ts +12 -0
- package/dist/lib/utils/fs-helpers.js +61 -0
- package/dist/lib/utils/json-loader.d.ts +6 -0
- package/dist/lib/utils/json-loader.js +34 -0
- package/dist/lib/utils/module-loader.d.ts +9 -0
- package/dist/lib/utils/module-loader.js +98 -0
- package/dist/lib/utils/package-root.d.ts +1 -0
- package/dist/lib/utils/package-root.js +75 -2
- package/dist/lib/utils/path-resolver.d.ts +9 -0
- package/dist/lib/utils/path-resolver.js +44 -0
- package/modules/auth/authjs/files/nextjs/api/auth/[...nextauth]/route.ts +3 -0
- package/modules/auth/authjs/files/nextjs/proxy.ts +1 -0
- package/modules/auth/authjs/files/shared/lib/auth.ts +119 -0
- package/modules/auth/authjs/files/{prisma → shared/prisma}/schema.prisma +11 -1
- package/modules/auth/authjs/generator.json +18 -8
- package/modules/auth/better-auth/files/express/middlewares/authorize.ts +54 -0
- package/modules/auth/better-auth/files/express/types/express.d.ts +16 -0
- package/modules/auth/better-auth/files/nextjs/lib/auth/auth-guards.ts +31 -0
- package/modules/auth/better-auth/files/nextjs/proxy.ts +34 -0
- package/modules/auth/better-auth/files/{lib → shared/lib}/auth-client.ts +1 -1
- package/modules/auth/better-auth/files/{lib → shared/lib}/auth.ts +46 -20
- package/modules/auth/better-auth/files/{prisma → shared/prisma}/schema.prisma +11 -2
- package/modules/auth/better-auth/generator.json +74 -19
- package/modules/database/mongoose/generator.json +16 -2
- package/modules/database/prisma/files/lib/prisma.ts +1 -1
- package/modules/database/prisma/files/prisma/schema.prisma +1 -2
- package/modules/database/prisma/generator.json +8 -1
- package/package.json +2 -2
- package/templates/express/env.example +2 -1
- package/templates/express/package.json +3 -4
- package/templates/express/src/app.ts +18 -25
- package/templates/express/src/config/cors.ts +12 -0
- package/templates/express/src/config/helmet.ts +5 -0
- package/templates/express/src/config/logger.ts +6 -0
- package/templates/express/src/config/rate-limit.ts +11 -0
- package/templates/express/src/{features → modules}/health/health.route.ts +1 -1
- package/templates/express/src/routes/index.ts +12 -0
- package/templates/express/src/shared/errors/api-error.ts +14 -0
- package/templates/express/src/shared/errors/error-codes.ts +9 -0
- package/templates/express/src/shared/logger/logger.ts +20 -0
- package/templates/express/src/{middlewares → shared/middlewares}/error.middleware.ts +1 -1
- package/templates/express/src/shared/middlewares/not-found.middleware.ts +9 -0
- package/templates/express/src/shared/utils/async-handler.ts +9 -0
- package/templates/express/src/shared/utils/pagination.ts +6 -0
- package/templates/express/src/shared/utils/response.ts +9 -0
- package/templates/express/tsconfig.json +9 -3
- package/templates/react/src/app/layouts/dashboard-layout.tsx +8 -0
- package/templates/react/src/app/layouts/public-layout.tsx +5 -0
- package/templates/react/src/app/providers.tsx +20 -0
- package/templates/react/src/app/router.tsx +21 -0
- package/templates/react/src/{pages/About.tsx → features/about/pages/about.tsx} +1 -1
- package/templates/react/src/{pages/Home.tsx → features/home/pages/home.tsx} +1 -1
- package/templates/react/src/main.tsx +2 -2
- package/templates/react/src/{api/client.ts → shared/api/http.ts} +1 -1
- package/templates/react/src/{pages/NotFound.tsx → shared/pages/not-found.tsx} +1 -1
- package/dist/lib/git-utils.d.ts +0 -1
- package/dist/lib/git-utils.js +0 -29
- package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +0 -2
- package/modules/auth/authjs/files/lib/auth.ts +0 -22
- /package/modules/auth/better-auth/files/{api → nextjs/api}/auth/[...all]/route.ts +0 -0
- /package/modules/auth/better-auth/files/{lib → shared/lib/email}/email-service.ts +0 -0
- /package/modules/auth/better-auth/files/{lib → shared/lib/email}/email-templates.ts +0 -0
- /package/templates/express/src/{features → modules}/health/health.controller.ts +0 -0
- /package/templates/express/src/{features → modules}/health/health.service.ts +0 -0
- /package/templates/react/src/{components/ErrorBoundary.tsx → shared/components/error-boundary.tsx} +0 -0
- /package/templates/react/src/{components/Layout.tsx → shared/components/layout.tsx} +0 -0
- /package/templates/react/src/{components/Loading.tsx → shared/components/loading.tsx} +0 -0
- /package/templates/react/src/{components/SEO.tsx → shared/components/seo.tsx} +0 -0
- /package/templates/react/src/{lib/queryClient.ts → shared/lib/query-client.ts} +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import rateLimit from "express-rate-limit";
|
|
2
|
+
import { env } from "./env";
|
|
3
|
+
|
|
4
|
+
const limiter = rateLimit({
|
|
5
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
6
|
+
max: env.isProduction ? 100 : 1000, // limit each IP
|
|
7
|
+
standardHeaders: true,
|
|
8
|
+
legacyHeaders: false,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export { limiter };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { healthRoutes } from "../modules/health/health.route";
|
|
3
|
+
const router = Router();
|
|
4
|
+
|
|
5
|
+
// versioned API
|
|
6
|
+
const v1 = Router();
|
|
7
|
+
|
|
8
|
+
v1.use("/health", healthRoutes);
|
|
9
|
+
|
|
10
|
+
router.use("/v1", v1);
|
|
11
|
+
|
|
12
|
+
export const apiRoutes = router;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default class ApiError extends Error {
|
|
2
|
+
statusCode: number;
|
|
3
|
+
isOperational: boolean;
|
|
4
|
+
|
|
5
|
+
constructor(statusCode: number, message: string, isOperational = true) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
this.isOperational = isOperational;
|
|
9
|
+
Object.setPrototypeOf(this, ApiError.prototype);
|
|
10
|
+
if (Error.captureStackTrace) {
|
|
11
|
+
Error.captureStackTrace(this, this.constructor);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
function ts() {
|
|
2
|
+
return new Date().toISOString();
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export const info = (msg: string, meta?: any) => {
|
|
6
|
+
console.log(`${ts()} INFO: ${msg}` + (meta ? ` ${JSON.stringify(meta)}` : ""));
|
|
7
|
+
};
|
|
8
|
+
export const warn = (msg: string, meta?: any) => {
|
|
9
|
+
console.warn(`${ts()} WARN: ${msg}` + (meta ? ` ${JSON.stringify(meta)}` : ""));
|
|
10
|
+
};
|
|
11
|
+
export const error = (msg: string, meta?: any) => {
|
|
12
|
+
console.error(`${ts()} ERROR: ${msg}` + (meta ? ` ${JSON.stringify(meta)}` : ""));
|
|
13
|
+
};
|
|
14
|
+
export const debug = (msg: string, meta?: any) => {
|
|
15
|
+
if (process.env.NODE_ENV !== "production") {
|
|
16
|
+
console.debug(`${ts()} DEBUG: ${msg}` + (meta ? ` ${JSON.stringify(meta)}` : ""));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default { info, warn, error, debug };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextFunction, Request, Response } from "express";
|
|
2
|
-
import { env } from "
|
|
2
|
+
import { env } from "../../config/env";
|
|
3
3
|
|
|
4
4
|
export const errorHandler = (err: any, _req: Request, res: Response, _: NextFunction) => {
|
|
5
5
|
const statusCode = err.status || 500;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NextFunction, Request, Response } from "express";
|
|
2
|
+
|
|
3
|
+
export default function asyncHandler(
|
|
4
|
+
fn: (req: Request, res: Response, next: NextFunction) => Promise<any>,
|
|
5
|
+
) {
|
|
6
|
+
return (req: Request, res: Response, next: NextFunction) => {
|
|
7
|
+
fn(req, res, next).catch(next);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export function getPagination(query: any) {
|
|
2
|
+
const page = Math.max(1, parseInt(String(query.page || "1"), 10) || 1);
|
|
3
|
+
const limit = Math.min(100, parseInt(String(query.limit || "10"), 10) || 10);
|
|
4
|
+
const skip = (page - 1) * limit;
|
|
5
|
+
return { page, limit, skip, take: limit };
|
|
6
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Response } from "express";
|
|
2
|
+
|
|
3
|
+
export function success(res: Response, data: any, message = "Success", meta?: any) {
|
|
4
|
+
return res.json({ success: true, message, data, meta });
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function fail(res: Response, status = 500, message = "Error", details?: any) {
|
|
8
|
+
return res.status(status).json({ success: false, message, details });
|
|
9
|
+
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
+
"sourceMap": true,
|
|
4
|
+
"outDir": "dist",
|
|
5
|
+
"strict": true,
|
|
6
|
+
"target": "ES2020",
|
|
7
|
+
"lib": ["ES2020", "DOM"],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"types": ["node"],
|
|
10
|
+
"esModuleInterop": true,
|
|
3
11
|
"module": "ESNext",
|
|
4
12
|
"moduleResolution": "node",
|
|
5
|
-
"
|
|
6
|
-
"strict": true,
|
|
7
|
-
"esModuleInterop": true
|
|
13
|
+
"resolveJsonModule": true
|
|
8
14
|
}
|
|
9
15
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { QueryClientProvider } from "@tanstack/react-query";
|
|
2
|
+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
3
|
+
import { Toaster } from "react-hot-toast";
|
|
4
|
+
import { SEOProvider } from "../shared/components/seo";
|
|
5
|
+
import { queryClient } from "../shared/lib/query-client";
|
|
6
|
+
import type { ReactNode } from "react";
|
|
7
|
+
|
|
8
|
+
export function Providers({ children }: { children: ReactNode }) {
|
|
9
|
+
return (
|
|
10
|
+
<SEOProvider>
|
|
11
|
+
<QueryClientProvider client={queryClient}>
|
|
12
|
+
{children}
|
|
13
|
+
<Toaster position="top-right" />
|
|
14
|
+
<ReactQueryDevtools initialIsOpen={false} />
|
|
15
|
+
</QueryClientProvider>
|
|
16
|
+
</SEOProvider>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default Providers;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createBrowserRouter } from "react-router";
|
|
2
|
+
import { ErrorBoundary } from "../shared/components/error-boundary";
|
|
3
|
+
import PublicLayout from "./layouts/public-layout";
|
|
4
|
+
import Home from "../features/home/pages/home";
|
|
5
|
+
import About from "../features/about/pages/about";
|
|
6
|
+
import NotFound from "../shared/pages/not-found";
|
|
7
|
+
|
|
8
|
+
export const router = createBrowserRouter([
|
|
9
|
+
{
|
|
10
|
+
path: "/",
|
|
11
|
+
Component: PublicLayout,
|
|
12
|
+
errorElement: <ErrorBoundary />,
|
|
13
|
+
children: [
|
|
14
|
+
{ index: true, Component: Home },
|
|
15
|
+
{ path: "about", Component: About },
|
|
16
|
+
{ path: "*", Component: NotFound },
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
export default router;
|
|
@@ -4,10 +4,10 @@ import { StrictMode } from "react";
|
|
|
4
4
|
import { createRoot } from "react-dom/client";
|
|
5
5
|
import { Toaster } from "react-hot-toast";
|
|
6
6
|
import { RouterProvider } from "react-router";
|
|
7
|
-
import { SEOProvider } from "./components/SEO";
|
|
8
7
|
import "./index.css";
|
|
9
|
-
import { queryClient } from "./lib/queryClient";
|
|
10
8
|
import { router } from "./router";
|
|
9
|
+
import { queryClient } from "./shared/lib/query-client";
|
|
10
|
+
import { SEOProvider } from "./shared/components/seo";
|
|
11
11
|
|
|
12
12
|
createRoot(document.getElementById("root")!).render(
|
|
13
13
|
<StrictMode>
|
|
@@ -14,7 +14,7 @@ api.interceptors.request.use(
|
|
|
14
14
|
(config) => {
|
|
15
15
|
const token = localStorage.getItem("auth_token");
|
|
16
16
|
if (token) {
|
|
17
|
-
config.headers.Authorization = `Bearer ${token}`;
|
|
17
|
+
(config.headers as Record<string, string>).Authorization = `Bearer ${token}`;
|
|
18
18
|
}
|
|
19
19
|
return config;
|
|
20
20
|
},
|
package/dist/lib/git-utils.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function initGit(cwd: string): Promise<void>;
|
package/dist/lib/git-utils.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.initGit = initGit;
|
|
4
|
-
const child_process_1 = require("child_process");
|
|
5
|
-
async function initGit(cwd) {
|
|
6
|
-
try {
|
|
7
|
-
(0, child_process_1.execSync)("git --version", { stdio: "pipe" });
|
|
8
|
-
}
|
|
9
|
-
catch {
|
|
10
|
-
throw new Error("Git is not installed or not available in PATH");
|
|
11
|
-
}
|
|
12
|
-
try {
|
|
13
|
-
(0, child_process_1.execSync)("git status", { cwd, stdio: "pipe" });
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
// Not a git repo, proceed with initialization
|
|
18
|
-
}
|
|
19
|
-
(0, child_process_1.execSync)("git init", { cwd, stdio: "pipe" });
|
|
20
|
-
(0, child_process_1.execSync)("git add .", { cwd, stdio: "pipe" });
|
|
21
|
-
try {
|
|
22
|
-
(0, child_process_1.execSync)("git diff --cached --quiet", { cwd, stdio: "pipe" });
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
// Files are staged, proceed with commit
|
|
27
|
-
}
|
|
28
|
-
(0, child_process_1.execSync)('git commit -m "Initial commit"', { cwd, stdio: "pipe" });
|
|
29
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import NextAuth from "next-auth"
|
|
2
|
-
import { PrismaAdapter } from "@auth/prisma-adapter"
|
|
3
|
-
import { prisma } from "./prisma";
|
|
4
|
-
import Google from "next-auth/providers/google"
|
|
5
|
-
import { encode, decode } from 'next-auth/jwt';
|
|
6
|
-
|
|
7
|
-
export const { handlers, signIn, signOut, auth } = NextAuth({
|
|
8
|
-
adapter: PrismaAdapter(prisma),
|
|
9
|
-
providers: [
|
|
10
|
-
Google({
|
|
11
|
-
clientId: process.env.AUTH_GOOGLE_ID,
|
|
12
|
-
clientSecret: process.env.AUTH_GOOGLE_SECRET,
|
|
13
|
-
}),
|
|
14
|
-
],
|
|
15
|
-
session: { strategy: "jwt" },
|
|
16
|
-
secret: process.env.AUTH_SECRET,
|
|
17
|
-
jwt: { encode, decode },
|
|
18
|
-
pages: {
|
|
19
|
-
signIn: '/sign-in',
|
|
20
|
-
error: '/error',
|
|
21
|
-
},
|
|
22
|
-
})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/templates/react/src/{components/ErrorBoundary.tsx → shared/components/error-boundary.tsx}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|