create-zhx-monorepo 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 +34 -0
- package/bin/index.js +65 -0
- package/package.json +18 -0
- package/templates/monorepo-starter/.vscode/settings.json +3 -0
- package/templates/monorepo-starter/README.md +42 -0
- package/templates/monorepo-starter/apps/web/components.json +20 -0
- package/templates/monorepo-starter/apps/web/eslint.config.mjs +4 -0
- package/templates/monorepo-starter/apps/web/next-env.d.ts +6 -0
- package/templates/monorepo-starter/apps/web/next.config.mjs +6 -0
- package/templates/monorepo-starter/apps/web/package.json +31 -0
- package/templates/monorepo-starter/apps/web/postcss.config.mjs +1 -0
- package/templates/monorepo-starter/apps/web/public/.gitkeep +0 -0
- package/templates/monorepo-starter/apps/web/sitemap.config.cjs +6 -0
- package/templates/monorepo-starter/apps/web/src/app/(auth)/layout.tsx +7 -0
- package/templates/monorepo-starter/apps/web/src/app/(root)/layout.tsx +15 -0
- package/templates/monorepo-starter/apps/web/src/app/(root)/page.tsx +14 -0
- package/templates/monorepo-starter/apps/web/src/app/globals.css +1 -0
- package/templates/monorepo-starter/apps/web/src/app/layout.tsx +24 -0
- package/templates/monorepo-starter/apps/web/src/components/Footer.tsx +9 -0
- package/templates/monorepo-starter/apps/web/src/components/Header.tsx +11 -0
- package/templates/monorepo-starter/apps/web/src/components/ThemeSwitch.tsx +34 -0
- package/templates/monorepo-starter/apps/web/src/hooks/.gitkeep +0 -0
- package/templates/monorepo-starter/apps/web/src/lib/.gitkeep +0 -0
- package/templates/monorepo-starter/apps/web/src/providers/index.tsx +10 -0
- package/templates/monorepo-starter/apps/web/src/providers/theme.tsx +19 -0
- package/templates/monorepo-starter/apps/web/src/types/index.d.ts +16 -0
- package/templates/monorepo-starter/apps/web/tsconfig.json +20 -0
- package/templates/monorepo-starter/eslint.config.mjs +12 -0
- package/templates/monorepo-starter/package.json +23 -0
- package/templates/monorepo-starter/packages/config/eslint/base.js +31 -0
- package/templates/monorepo-starter/packages/config/eslint/nest.js +26 -0
- package/templates/monorepo-starter/packages/config/eslint/next.js +39 -0
- package/templates/monorepo-starter/packages/config/eslint/react.js +30 -0
- package/templates/monorepo-starter/packages/config/package.json +32 -0
- package/templates/monorepo-starter/packages/config/typescript/base.json +31 -0
- package/templates/monorepo-starter/packages/config/typescript/nest.json +14 -0
- package/templates/monorepo-starter/packages/config/typescript/next.json +10 -0
- package/templates/monorepo-starter/packages/config/typescript/react.json +9 -0
- package/templates/monorepo-starter/packages/ui/components.json +20 -0
- package/templates/monorepo-starter/packages/ui/eslint.config.mjs +4 -0
- package/templates/monorepo-starter/packages/ui/package.json +38 -0
- package/templates/monorepo-starter/packages/ui/postcss.config.mjs +6 -0
- package/templates/monorepo-starter/packages/ui/src/components/button.tsx +71 -0
- package/templates/monorepo-starter/packages/ui/src/hooks/.gitkeep +0 -0
- package/templates/monorepo-starter/packages/ui/src/lib/utils.ts +6 -0
- package/templates/monorepo-starter/packages/ui/src/styles/globals.css +182 -0
- package/templates/monorepo-starter/packages/ui/tsconfig.json +13 -0
- package/templates/monorepo-starter/packages/ui/tsconfig.lint.json +8 -0
- package/templates/monorepo-starter/pnpm-lock.yaml +12441 -0
- package/templates/monorepo-starter/pnpm-workspace.yaml +17 -0
- package/templates/monorepo-starter/server/.env.example +64 -0
- package/templates/monorepo-starter/server/README.md +63 -0
- package/templates/monorepo-starter/server/eslint.config.mjs +4 -0
- package/templates/monorepo-starter/server/nest-cli.json +12 -0
- package/templates/monorepo-starter/server/package.json +97 -0
- package/templates/monorepo-starter/server/prisma/generated/browser.ts +54 -0
- package/templates/monorepo-starter/server/prisma/generated/client.ts +76 -0
- package/templates/monorepo-starter/server/prisma/generated/commonInputTypes.ts +577 -0
- package/templates/monorepo-starter/server/prisma/generated/enums.ts +68 -0
- package/templates/monorepo-starter/server/prisma/generated/internal/class.ts +250 -0
- package/templates/monorepo-starter/server/prisma/generated/internal/prismaNamespace.ts +1436 -0
- package/templates/monorepo-starter/server/prisma/generated/internal/prismaNamespaceBrowser.ts +227 -0
- package/templates/monorepo-starter/server/prisma/generated/models/BackupCode.ts +1375 -0
- package/templates/monorepo-starter/server/prisma/generated/models/Notification.ts +1587 -0
- package/templates/monorepo-starter/server/prisma/generated/models/Otp.ts +1488 -0
- package/templates/monorepo-starter/server/prisma/generated/models/RefreshToken.ts +1515 -0
- package/templates/monorepo-starter/server/prisma/generated/models/RoleAssignment.ts +1385 -0
- package/templates/monorepo-starter/server/prisma/generated/models/SecuritySetting.ts +1422 -0
- package/templates/monorepo-starter/server/prisma/generated/models/User.ts +2498 -0
- package/templates/monorepo-starter/server/prisma/generated/models.ts +18 -0
- package/templates/monorepo-starter/server/prisma/migrations/20251218164821_init/migration.sql +210 -0
- package/templates/monorepo-starter/server/prisma/migrations/migration_lock.toml +3 -0
- package/templates/monorepo-starter/server/prisma/schema.prisma +193 -0
- package/templates/monorepo-starter/server/prisma.config.ts +13 -0
- package/templates/monorepo-starter/server/scripts/generate.sh +14 -0
- package/templates/monorepo-starter/server/src/app.module.ts +49 -0
- package/templates/monorepo-starter/server/src/lib/decorators/logger.decorator.ts +20 -0
- package/templates/monorepo-starter/server/src/lib/decorators/public.decorator.ts +4 -0
- package/templates/monorepo-starter/server/src/lib/decorators/roles.decorator.ts +5 -0
- package/templates/monorepo-starter/server/src/lib/dto/auth.dto.ts +64 -0
- package/templates/monorepo-starter/server/src/lib/dto/security-setting.dto.ts +21 -0
- package/templates/monorepo-starter/server/src/lib/filters/exceptions.filter.ts +62 -0
- package/templates/monorepo-starter/server/src/lib/guards/auth.guard.ts +104 -0
- package/templates/monorepo-starter/server/src/lib/interceptors/response.interceptor.ts +33 -0
- package/templates/monorepo-starter/server/src/lib/pipes/validation.pipe.ts +7 -0
- package/templates/monorepo-starter/server/src/lib/schemas/env.schema.ts +99 -0
- package/templates/monorepo-starter/server/src/lib/utils/cookie.util.ts +23 -0
- package/templates/monorepo-starter/server/src/lib/utils/general.util.ts +24 -0
- package/templates/monorepo-starter/server/src/main.ts +41 -0
- package/templates/monorepo-starter/server/src/modules/auth/auth.controller.ts +74 -0
- package/templates/monorepo-starter/server/src/modules/auth/auth.module.ts +16 -0
- package/templates/monorepo-starter/server/src/modules/auth/auth.service.ts +525 -0
- package/templates/monorepo-starter/server/src/modules/auth/oauth.controller.ts +58 -0
- package/templates/monorepo-starter/server/src/modules/auth/oauth.service.ts +165 -0
- package/templates/monorepo-starter/server/src/modules/auth/otp.service.ts +133 -0
- package/templates/monorepo-starter/server/src/modules/auth/role.service.ts +99 -0
- package/templates/monorepo-starter/server/src/modules/auth/security-setting.service.ts +102 -0
- package/templates/monorepo-starter/server/src/modules/env/env.module.ts +9 -0
- package/templates/monorepo-starter/server/src/modules/env/env.service.ts +22 -0
- package/templates/monorepo-starter/server/src/modules/logger/logger.module.ts +12 -0
- package/templates/monorepo-starter/server/src/modules/logger/logger.service.ts +37 -0
- package/templates/monorepo-starter/server/src/modules/logger/winston.config.ts +32 -0
- package/templates/monorepo-starter/server/src/modules/notification/notification.module.ts +11 -0
- package/templates/monorepo-starter/server/src/modules/notification/notification.service.ts +118 -0
- package/templates/monorepo-starter/server/src/modules/prisma/prisma.extension.ts +72 -0
- package/templates/monorepo-starter/server/src/modules/prisma/prisma.module.ts +9 -0
- package/templates/monorepo-starter/server/src/modules/prisma/prisma.service.ts +49 -0
- package/templates/monorepo-starter/server/src/modules/public/public.controller.ts +21 -0
- package/templates/monorepo-starter/server/src/modules/public/public.module.ts +9 -0
- package/templates/monorepo-starter/server/src/modules/public/public.service.ts +30 -0
- package/templates/monorepo-starter/server/src/modules/scheduler/cleanup.service.ts +33 -0
- package/templates/monorepo-starter/server/src/modules/scheduler/scheduler.module.ts +7 -0
- package/templates/monorepo-starter/server/src/modules/template/template.module.ts +8 -0
- package/templates/monorepo-starter/server/src/modules/template/template.service.ts +33 -0
- package/templates/monorepo-starter/server/src/modules/token/token.module.ts +11 -0
- package/templates/monorepo-starter/server/src/modules/token/token.service.ts +131 -0
- package/templates/monorepo-starter/server/src/types/express.d.ts +10 -0
- package/templates/monorepo-starter/server/src/types/index.d.ts +13 -0
- package/templates/monorepo-starter/server/templates/notification.templates.ts +243 -0
- package/templates/monorepo-starter/server/test/app.e2e-spec.ts +25 -0
- package/templates/monorepo-starter/server/test/jest-e2e.json +9 -0
- package/templates/monorepo-starter/server/tsconfig.json +23 -0
- package/templates/monorepo-starter/server/tsup.config.ts +14 -0
- package/templates/monorepo-starter/tsconfig.json +3 -0
- package/templates/monorepo-starter/turbo.json +21 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# create-zhx-monorepo
|
|
2
|
+
|
|
3
|
+
A CLI package to quickly generate a **Monorepo Starter** monorepo for full-stack development with Next.js, NestJS, and shadcn/ui.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install globally (optional)
|
|
11
|
+
pnpm add -g create-zhx-monorepo
|
|
12
|
+
|
|
13
|
+
# Create a new project
|
|
14
|
+
pnpm create-zhx-monorepo my-new-project
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This will generate a ready-to-use monorepo under `my-new-project` with:
|
|
18
|
+
|
|
19
|
+
- `apps/web` – Next.js frontend
|
|
20
|
+
- `server` – NestJS backend
|
|
21
|
+
- `packages/ui` – Shared UI components
|
|
22
|
+
- `packages/config` – ESLint & TypeScript configs
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Requirements
|
|
27
|
+
|
|
28
|
+
- Node.js 24+
|
|
29
|
+
- PNPM
|
|
30
|
+
- Git
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
Made with ❤️ by **JZ Digital Labs**
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import prompts from "prompts";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { green, cyan, red } from "kolorist";
|
|
7
|
+
import { execSync } from "child_process";
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
|
|
12
|
+
async function main() {
|
|
13
|
+
const targetDir = process.argv[2];
|
|
14
|
+
|
|
15
|
+
if (!targetDir) {
|
|
16
|
+
console.log(red("❌ Please provide a project name"));
|
|
17
|
+
console.log("Example:");
|
|
18
|
+
console.log(" pnpm create zhx-monorepo my-app");
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const projectPath = path.resolve(process.cwd(), targetDir);
|
|
23
|
+
|
|
24
|
+
if (fs.existsSync(projectPath)) {
|
|
25
|
+
console.log(red("❌ Directory already exists"));
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { gitRemote } = await prompts({
|
|
30
|
+
type: "text",
|
|
31
|
+
name: "gitRemote",
|
|
32
|
+
message: "Git remote URL (optional):",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log(cyan("📦 Creating project..."));
|
|
36
|
+
|
|
37
|
+
// Copy template
|
|
38
|
+
const templateDir = path.join(__dirname, "../templates/monorepo-starter");
|
|
39
|
+
await fs.copy(templateDir, projectPath);
|
|
40
|
+
|
|
41
|
+
// Update package.json
|
|
42
|
+
const pkgPath = path.join(projectPath, "package.json");
|
|
43
|
+
const pkg = await fs.readJson(pkgPath);
|
|
44
|
+
pkg.name = targetDir;
|
|
45
|
+
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
46
|
+
|
|
47
|
+
// Init git
|
|
48
|
+
process.chdir(projectPath);
|
|
49
|
+
execSync("git init", { stdio: "ignore" });
|
|
50
|
+
execSync("git add .", { stdio: "ignore" });
|
|
51
|
+
execSync('git commit -m "Initial commit"', { stdio: "ignore" });
|
|
52
|
+
|
|
53
|
+
if (gitRemote) {
|
|
54
|
+
execSync(`git remote add origin ${gitRemote}`, { stdio: "ignore" });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log(green("✅ Project ready!"));
|
|
58
|
+
console.log();
|
|
59
|
+
console.log("Next steps:");
|
|
60
|
+
console.log(` cd ${targetDir}`);
|
|
61
|
+
console.log(" pnpm install");
|
|
62
|
+
console.log(" pnpm dev");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-zhx-monorepo",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Create a ZHX monorepo with one command",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-zhx-monorepo": "bin/index.js"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"fs-extra": "^11.3.3",
|
|
15
|
+
"prompts": "^2.4.2",
|
|
16
|
+
"kolorist": "^1.8.0"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Monorepo Starter Template
|
|
2
|
+
|
|
3
|
+
This is a minimal, modern monorepo template based on shadcn/ui, customized for fast development and scalability.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Modular structure for web, server, and shared packages
|
|
8
|
+
- Customizable UI components (`packages/ui`)
|
|
9
|
+
- Tailwind CSS and PostCSS preconfigured
|
|
10
|
+
- TypeScript everywhere
|
|
11
|
+
- Ready for Next.js and NestJS
|
|
12
|
+
- ESLint, TurboRepo, and PNPM workspace setup
|
|
13
|
+
|
|
14
|
+
## Structure
|
|
15
|
+
|
|
16
|
+
- `apps/web` – Next.js frontend
|
|
17
|
+
- `server` – NestJS backend
|
|
18
|
+
- `packages/ui` – Shared UI components
|
|
19
|
+
- `packages/config` – Shared configs (ESLint, TypeScript)
|
|
20
|
+
|
|
21
|
+
## Getting Started
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pnpm install
|
|
25
|
+
pnpm dev # Start all apps
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
Import UI components in your app:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { Button } from "@workspace/ui/components/button";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Customization
|
|
37
|
+
|
|
38
|
+
Feel free to modify, extend, and organize the template to fit your workflow.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
Made with ❤️ using shadcn/ui & Monorepo
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "new-york",
|
|
4
|
+
"rsc": true,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "../../packages/ui/src/styles/globals.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true
|
|
11
|
+
},
|
|
12
|
+
"iconLibrary": "lucide",
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@/components",
|
|
15
|
+
"hooks": "@/hooks",
|
|
16
|
+
"lib": "@/lib",
|
|
17
|
+
"utils": "@workspace/ui/lib/utils",
|
|
18
|
+
"ui": "@workspace/ui/components"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="next" />
|
|
2
|
+
/// <reference types="next/image-types/global" />
|
|
3
|
+
/// <reference path="./.next/types/routes.d.ts" />
|
|
4
|
+
|
|
5
|
+
// NOTE: This file should not be edited
|
|
6
|
+
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "web",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "next dev --turbopack",
|
|
8
|
+
"build": "next build",
|
|
9
|
+
"postbuild": "next-sitemap --config sitemap.config.cjs",
|
|
10
|
+
"start": "next start",
|
|
11
|
+
"lint": "next lint",
|
|
12
|
+
"lint:fix": "next lint --fix",
|
|
13
|
+
"typecheck": "tsc --noEmit"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@workspace/ui": "workspace:*",
|
|
17
|
+
"lucide-react": "^0.562.0",
|
|
18
|
+
"next": "^16.0.10",
|
|
19
|
+
"next-sitemap": "^4.2.3",
|
|
20
|
+
"next-themes": "^0.4.6",
|
|
21
|
+
"react": "^19.2.3",
|
|
22
|
+
"react-dom": "^19.2.3"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^25.0.3",
|
|
26
|
+
"@types/react": "^19.2.7",
|
|
27
|
+
"@types/react-dom": "^19.2.3",
|
|
28
|
+
"@workspace/config": "workspace:*",
|
|
29
|
+
"tailwindcss": "^4.1.18"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "@workspace/ui/postcss.config";
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Header from "@/components/Header";
|
|
3
|
+
import Footer from "@/components/Footer";
|
|
4
|
+
|
|
5
|
+
const Layout = ({ children }: LayoutProps) => {
|
|
6
|
+
return (
|
|
7
|
+
<>
|
|
8
|
+
<Header />
|
|
9
|
+
<main>{children}</main>
|
|
10
|
+
<Footer />
|
|
11
|
+
</>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default Layout;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Button } from "@workspace/ui/components/button"
|
|
2
|
+
|
|
3
|
+
const HomePage = () => {
|
|
4
|
+
return (
|
|
5
|
+
<div className="flex items-center justify-center min-h-svh">
|
|
6
|
+
<div className="flex flex-col items-center justify-center gap-4">
|
|
7
|
+
<h1 className="text-2xl font-bold">Hello World</h1>
|
|
8
|
+
<Button size="sm">Button</Button>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default HomePage
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Inter } from "next/font/google";
|
|
2
|
+
|
|
3
|
+
import "@workspace/ui/globals.css";
|
|
4
|
+
import "./globals.css";
|
|
5
|
+
import Provider from "@/providers";
|
|
6
|
+
|
|
7
|
+
const primaryFont = Inter({
|
|
8
|
+
variable: "--font-primary",
|
|
9
|
+
subsets: ["latin"],
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const RootLayout = ({ children }: LayoutProps) => {
|
|
13
|
+
return (
|
|
14
|
+
<html lang="en" suppressHydrationWarning>
|
|
15
|
+
<body
|
|
16
|
+
className={`${primaryFont.variable} font-sans antialiased `}
|
|
17
|
+
>
|
|
18
|
+
<Provider>{children}</Provider>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default RootLayout;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Moon, Sun } from "lucide-react";
|
|
5
|
+
import { useTheme } from "next-themes";
|
|
6
|
+
import { Button, type ButtonProps } from "@workspace/ui/components/button";
|
|
7
|
+
|
|
8
|
+
function ThemeSwitch(props: ButtonProps) {
|
|
9
|
+
const { setTheme, theme, systemTheme } = useTheme();
|
|
10
|
+
|
|
11
|
+
const currentTheme = theme === "system" ? systemTheme : theme;
|
|
12
|
+
|
|
13
|
+
const toggleTheme = () =>
|
|
14
|
+
setTheme(currentTheme === "dark" ? "light" : "dark");
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Button
|
|
18
|
+
variant="outline"
|
|
19
|
+
size="icon"
|
|
20
|
+
className="rounded-full"
|
|
21
|
+
{...props}
|
|
22
|
+
onClick={toggleTheme}
|
|
23
|
+
>
|
|
24
|
+
{currentTheme === "dark" ? (
|
|
25
|
+
<Moon className="text-white" />
|
|
26
|
+
) : (
|
|
27
|
+
<Sun className="text-black" />
|
|
28
|
+
)}
|
|
29
|
+
<span className="sr-only">Toggle theme</span>
|
|
30
|
+
</Button>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default ThemeSwitch;
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
import React from "react"
|
|
3
|
+
import { ThemeProvider as NextThemesProvider } from "next-themes"
|
|
4
|
+
|
|
5
|
+
function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|
6
|
+
return (
|
|
7
|
+
<NextThemesProvider
|
|
8
|
+
attribute="class"
|
|
9
|
+
defaultTheme="system"
|
|
10
|
+
enableSystem
|
|
11
|
+
disableTransitionOnChange
|
|
12
|
+
enableColorScheme
|
|
13
|
+
>
|
|
14
|
+
{children}
|
|
15
|
+
</NextThemesProvider>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default ThemeProvider;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
interface SegmentParams {
|
|
4
|
+
[key: string]: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type TSearchParams = Record<string, string | string[] | undefined>;
|
|
8
|
+
|
|
9
|
+
interface PageProps {
|
|
10
|
+
params: Promise<SegmentParams>;
|
|
11
|
+
searchParams: Promise<TSearchParams>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface LayoutProps extends PageProps {
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@workspace/config/typescript/next",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"baseUrl": ".",
|
|
5
|
+
"outDir": "dist",
|
|
6
|
+
"paths": {
|
|
7
|
+
"@/*": ["src/*"],
|
|
8
|
+
"@workspace/ui/*": ["../../packages/ui/src/*"]
|
|
9
|
+
},
|
|
10
|
+
"plugins": [{ "name": "next" }]
|
|
11
|
+
},
|
|
12
|
+
"include": [
|
|
13
|
+
"next-env.d.ts",
|
|
14
|
+
"next.config.ts",
|
|
15
|
+
"**/*.ts",
|
|
16
|
+
"**/*.tsx",
|
|
17
|
+
".next/types/**/*.ts"
|
|
18
|
+
],
|
|
19
|
+
"exclude": ["node_modules"]
|
|
20
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// This configuration only applies to the package manager root.
|
|
2
|
+
/** @type {import("eslint").Linter.Config} */
|
|
3
|
+
const config = {
|
|
4
|
+
ignorePatterns: ["apps/**", "packages/**", "server/**"],
|
|
5
|
+
extends: ["@workspace/config/eslint/base"],
|
|
6
|
+
parser: "@typescript-eslint/parser",
|
|
7
|
+
parserOptions: {
|
|
8
|
+
project: true,
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default config;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zhx-monorepo",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "turbo build",
|
|
8
|
+
"dev": "turbo dev",
|
|
9
|
+
"lint": "turbo lint",
|
|
10
|
+
"format": "turbo format",
|
|
11
|
+
"update:deps": "pnpm update -r --latest"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@workspace/config": "workspace:*",
|
|
15
|
+
"prettier": "^3.7.4",
|
|
16
|
+
"turbo": "^2.6.3",
|
|
17
|
+
"typescript": "5.9.3"
|
|
18
|
+
},
|
|
19
|
+
"packageManager": "pnpm@10.26.0",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=24"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
3
|
+
import turboPlugin from "eslint-plugin-turbo";
|
|
4
|
+
import tseslint from "typescript-eslint";
|
|
5
|
+
|
|
6
|
+
/** @type {import("eslint").Linter.Config} */
|
|
7
|
+
export const config = [
|
|
8
|
+
js.configs.recommended,
|
|
9
|
+
eslintConfigPrettier,
|
|
10
|
+
...tseslint.configs.recommended,
|
|
11
|
+
{
|
|
12
|
+
plugins: { turbo: turboPlugin },
|
|
13
|
+
rules: {
|
|
14
|
+
"turbo/no-undeclared-env-vars": "error",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
ignores: [
|
|
19
|
+
"dist/**",
|
|
20
|
+
"build/**",
|
|
21
|
+
"coverage/**",
|
|
22
|
+
"node_modules/**",
|
|
23
|
+
".next/**",
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
languageOptions: {
|
|
28
|
+
sourceType: "module",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import tseslint from "typescript-eslint";
|
|
2
|
+
import globals from "globals";
|
|
3
|
+
import { config as baseConfig } from "./base.js";
|
|
4
|
+
|
|
5
|
+
/** @type {import("eslint").Linter.Config} */
|
|
6
|
+
export const config = [
|
|
7
|
+
...baseConfig,
|
|
8
|
+
{
|
|
9
|
+
languageOptions: {
|
|
10
|
+
globals: {
|
|
11
|
+
...globals.node,
|
|
12
|
+
},
|
|
13
|
+
sourceType: "module",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
rules: {
|
|
18
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
19
|
+
"@typescript-eslint/no-floating-promises": "error",
|
|
20
|
+
"@typescript-eslint/no-unsafe-argument": "error",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
ignores: ["test/**"],
|
|
25
|
+
},
|
|
26
|
+
];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import pluginReact from "eslint-plugin-react";
|
|
2
|
+
import pluginReactHooks from "eslint-plugin-react-hooks";
|
|
3
|
+
import pluginNext from "@next/eslint-plugin-next";
|
|
4
|
+
import globals from "globals";
|
|
5
|
+
import { config as baseConfig } from "./base.js";
|
|
6
|
+
|
|
7
|
+
/** @type {import("eslint").Linter.Config} */
|
|
8
|
+
export const config = [
|
|
9
|
+
...baseConfig,
|
|
10
|
+
pluginReact.configs.flat.recommended,
|
|
11
|
+
{
|
|
12
|
+
languageOptions: {
|
|
13
|
+
...pluginReact.configs.flat.recommended.languageOptions,
|
|
14
|
+
globals: {
|
|
15
|
+
...globals.browser,
|
|
16
|
+
...globals.serviceworker,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
settings: {
|
|
20
|
+
react: { version: "detect" },
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
plugins: {
|
|
25
|
+
"@next/next": pluginNext,
|
|
26
|
+
"react-hooks": pluginReactHooks,
|
|
27
|
+
},
|
|
28
|
+
rules: {
|
|
29
|
+
...pluginNext.configs.recommended.rules,
|
|
30
|
+
...pluginNext.configs["core-web-vitals"].rules,
|
|
31
|
+
...pluginReactHooks.configs.recommended.rules,
|
|
32
|
+
"react/react-in-jsx-scope": "off",
|
|
33
|
+
"react/prop-types": "off",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
ignores: [".next/**"],
|
|
38
|
+
},
|
|
39
|
+
];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import pluginReact from "eslint-plugin-react";
|
|
2
|
+
import pluginReactHooks from "eslint-plugin-react-hooks";
|
|
3
|
+
import globals from "globals";
|
|
4
|
+
import { config as baseConfig } from "./base.js";
|
|
5
|
+
|
|
6
|
+
/** @type {import("eslint").Linter.Config} */
|
|
7
|
+
export const config = [
|
|
8
|
+
...baseConfig,
|
|
9
|
+
pluginReact.configs.flat.recommended,
|
|
10
|
+
{
|
|
11
|
+
languageOptions: {
|
|
12
|
+
...pluginReact.configs.flat.recommended.languageOptions,
|
|
13
|
+
globals: {
|
|
14
|
+
...globals.serviceworker,
|
|
15
|
+
...globals.browser,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
settings: {
|
|
19
|
+
react: { version: "detect" },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
plugins: { "react-hooks": pluginReactHooks },
|
|
24
|
+
rules: {
|
|
25
|
+
...pluginReactHooks.configs.recommended.rules,
|
|
26
|
+
"react/react-in-jsx-scope": "off",
|
|
27
|
+
"react/prop-types": "off",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@workspace/config",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./eslint/*": "./eslint/*.js",
|
|
9
|
+
"./typescript/*": "./typescript/*.json"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"lint": "eslint . --max-warnings 0"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@eslint/js": "^9.39.2",
|
|
16
|
+
"@next/eslint-plugin-next": "^16.0.10",
|
|
17
|
+
"@types/jest": "^30.0.0",
|
|
18
|
+
"eslint": "^9.39.2",
|
|
19
|
+
"eslint-config-prettier": "^10.1.8",
|
|
20
|
+
"eslint-plugin-only-warn": "^1.1.0",
|
|
21
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
22
|
+
"eslint-plugin-react": "^7.37.5",
|
|
23
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
24
|
+
"eslint-plugin-turbo": "^2.6.3",
|
|
25
|
+
"globals": "^16.5.0",
|
|
26
|
+
"jest": "^30.2.0",
|
|
27
|
+
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
28
|
+
"ts-jest": "^29.4.6",
|
|
29
|
+
"turbo": "^2.6.3",
|
|
30
|
+
"typescript-eslint": "^8.50.0"
|
|
31
|
+
}
|
|
32
|
+
}
|