create-template-project 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/config/dependencies.json +15 -15
- package/dist/index.js +677 -483
- package/dist/templates/base/files/.release-it.json +1 -1
- package/dist/templates/base/files/_oxc.config.ts +212 -87
- package/dist/templates/cli/files/src/index.ts +1 -2
- package/dist/templates/cli/files/src/lib.ts +1 -3
- package/dist/templates/web-app/files/playwright.config.ts +7 -4
- package/dist/templates/web-app/files/src/App.tsx +11 -12
- package/dist/templates/web-app/files/src/index.tsx +1 -1
- package/dist/templates/web-app/files/tests/e2e/basic.e2e-test.ts +2 -2
- package/dist/templates/web-fullstack/files/client/src/App.tsx +8 -5
- package/dist/templates/web-fullstack/files/client/src/components/ProtectedRoute.tsx +5 -3
- package/dist/templates/web-fullstack/files/client/src/contexts/AuthContext.tsx +22 -18
- package/dist/templates/web-fullstack/files/client/src/main.tsx +8 -5
- package/dist/templates/web-fullstack/files/client/src/pages/Dashboard.tsx +12 -7
- package/dist/templates/web-fullstack/files/client/src/pages/Login.tsx +11 -7
- package/dist/templates/web-fullstack/files/client/src/trpc.ts +2 -1
- package/dist/templates/web-fullstack/files/playwright.config.ts +8 -5
- package/dist/templates/web-fullstack/files/server/src/context.ts +7 -5
- package/dist/templates/web-fullstack/files/server/src/index.ts +2 -3
- package/dist/templates/web-fullstack/files/server/src/routers/_app.ts +1 -0
- package/dist/templates/web-fullstack/files/server/src/routers/auth.ts +4 -4
- package/dist/templates/web-fullstack/files/server/src/trpc.ts +3 -4
- package/dist/templates/web-vanilla/files/playwright.config.ts +7 -4
- package/dist/templates/web-vanilla/files/src/index.test.ts +1 -1
- package/dist/templates/web-vanilla/files/src/index.ts +1 -1
- package/dist/templates/web-vanilla/files/src/lib.ts +1 -3
- package/package.json +13 -7
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable react/jsx-max-depth */
|
|
2
|
+
/* eslint-disable import/no-relative-parent-imports */
|
|
3
|
+
/* eslint-disable eslint/no-void */
|
|
4
|
+
/* eslint-disable typescript/no-deprecated */
|
|
5
|
+
import {useState, type ReactNode, type FormEvent} from 'react';
|
|
2
6
|
import {Button, TextField, Dialog, DialogActions, DialogContent, DialogTitle, Typography, Alert, Box} from '@mui/material';
|
|
3
7
|
import {useAuth} from '../contexts/AuthContext.js';
|
|
4
8
|
import {trpc} from '../trpc.js';
|
|
5
9
|
import {useNavigate} from 'react-router-dom';
|
|
6
10
|
|
|
7
|
-
export const Login = () => {
|
|
11
|
+
export const Login = (): ReactNode => {
|
|
8
12
|
const [email, setEmail] = useState('demo@example.com');
|
|
9
13
|
const [password, setPassword] = useState('password');
|
|
10
14
|
const [error, setError] = useState<string | null>(null);
|
|
@@ -21,7 +25,7 @@ export const Login = () => {
|
|
|
21
25
|
},
|
|
22
26
|
});
|
|
23
27
|
|
|
24
|
-
const handleSubmit = (e: FormEvent) => {
|
|
28
|
+
const handleSubmit = (e: FormEvent<HTMLFormElement>): void => {
|
|
25
29
|
e.preventDefault();
|
|
26
30
|
setError(null);
|
|
27
31
|
loginMutation.mutate({email, password});
|
|
@@ -32,13 +36,13 @@ export const Login = () => {
|
|
|
32
36
|
<form onSubmit={handleSubmit}>
|
|
33
37
|
<DialogTitle>Login</DialogTitle>
|
|
34
38
|
<DialogContent>
|
|
35
|
-
<Box display
|
|
36
|
-
{error && <Alert severity="error">{error}</Alert>}
|
|
39
|
+
<Box sx={{display: 'flex', flexDirection: 'column', gap: 2, pt: 1}}>
|
|
40
|
+
{error !== null && <Alert severity="error">{error}</Alert>}
|
|
37
41
|
<Typography variant="body2" color="textSecondary">
|
|
38
42
|
Use <b>demo@example.com</b> / <b>password</b> to login.
|
|
39
43
|
</Typography>
|
|
40
|
-
<TextField label="Email" type="email" fullWidth required value={email} onChange={(e) => setEmail(e.currentTarget.value)} />
|
|
41
|
-
<TextField label="Password" type="password" fullWidth required value={password} onChange={(e) => setPassword(e.currentTarget.value)} />
|
|
44
|
+
<TextField label="Email" type="email" fullWidth required value={email} onChange={(e) => { setEmail(e.currentTarget.value); }} />
|
|
45
|
+
<TextField label="Password" type="password" fullWidth required value={password} onChange={(e) => { setPassword(e.currentTarget.value); }} />
|
|
42
46
|
</Box>
|
|
43
47
|
</DialogContent>
|
|
44
48
|
<DialogActions>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
/* eslint-disable import/no-relative-parent-imports */
|
|
1
2
|
import {createTRPCReact} from '@trpc/react-query';
|
|
2
|
-
import type
|
|
3
|
+
import {type AppRouter} from '../../server/src/routers/_app.js';
|
|
3
4
|
|
|
4
5
|
export const trpc = createTRPCReact<AppRouter>();
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {defineConfig, devices} from '@playwright/test';
|
|
2
|
+
import {env} from 'node:process';
|
|
3
|
+
|
|
4
|
+
const isCi = env.CI !== undefined;
|
|
2
5
|
|
|
3
6
|
export default defineConfig({
|
|
4
7
|
testDir: './tests/e2e',
|
|
5
8
|
testMatch: '**/*.e2e-test.ts',
|
|
6
9
|
fullyParallel: true,
|
|
7
|
-
forbidOnly:
|
|
8
|
-
retries:
|
|
9
|
-
workers:
|
|
10
|
+
forbidOnly: isCi,
|
|
11
|
+
retries: isCi ? 2 : 0,
|
|
12
|
+
workers: isCi ? 1 : undefined,
|
|
10
13
|
reporter: 'html',
|
|
11
14
|
use: {
|
|
12
15
|
baseURL: 'http://localhost:5173',
|
|
@@ -22,12 +25,12 @@ export default defineConfig({
|
|
|
22
25
|
{
|
|
23
26
|
command: 'npm run dev --workspace=server',
|
|
24
27
|
port: 3000,
|
|
25
|
-
reuseExistingServer: !
|
|
28
|
+
reuseExistingServer: !isCi,
|
|
26
29
|
},
|
|
27
30
|
{
|
|
28
31
|
command: 'npm run dev --workspace=client',
|
|
29
32
|
port: 5173,
|
|
30
|
-
reuseExistingServer: !
|
|
33
|
+
reuseExistingServer: !isCi,
|
|
31
34
|
},
|
|
32
35
|
],
|
|
33
36
|
});
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable oxc/no-optional-chaining */
|
|
2
|
+
/* eslint-disable typescript/strict-boolean-expressions */
|
|
3
|
+
import {type CreateExpressContextOptions} from '@trpc/server/adapters/express';
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
type User = {
|
|
4
6
|
id: string;
|
|
5
7
|
name: string;
|
|
6
8
|
email: string;
|
|
7
|
-
}
|
|
9
|
+
};
|
|
8
10
|
|
|
9
|
-
export const createContext = ({req}: CreateExpressContextOptions) => {
|
|
11
|
+
export const createContext = ({req}: CreateExpressContextOptions): {user: User | null} => {
|
|
10
12
|
const authHeader = req.headers.authorization;
|
|
11
13
|
let user: User | null = null;
|
|
12
14
|
|
|
13
15
|
if (authHeader?.startsWith('Bearer ')) {
|
|
14
|
-
const token = authHeader.split(' ')
|
|
16
|
+
const [, token] = authHeader.split(' ');
|
|
15
17
|
// Mock token verification
|
|
16
18
|
if (token === 'mock-token') {
|
|
17
19
|
user = {id: '1', name: 'Demo User', email: 'demo@example.com'};
|
|
@@ -4,11 +4,10 @@ import * as trpcExpress from '@trpc/server/adapters/express';
|
|
|
4
4
|
import {appRouter} from './routers/_app.js';
|
|
5
5
|
import {createContext} from './context.js';
|
|
6
6
|
import path from 'node:path';
|
|
7
|
-
import {fileURLToPath} from 'node:url';
|
|
8
7
|
|
|
9
|
-
const __dirname =
|
|
8
|
+
const __dirname = import.meta.dirname;
|
|
10
9
|
const app = express();
|
|
11
|
-
const port = process.env['PORT']
|
|
10
|
+
const port = Number(process.env['PORT'] ?? 3001);
|
|
12
11
|
|
|
13
12
|
app.use(cors());
|
|
14
13
|
app.use(express.json());
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* eslint-disable import/no-relative-parent-imports */
|
|
2
|
+
/* eslint-disable typescript/no-deprecated */
|
|
1
3
|
import {z} from 'zod';
|
|
2
4
|
import {publicProcedure, protectedProcedure, router} from '../trpc.js';
|
|
3
5
|
import {TRPCError} from '@trpc/server';
|
|
@@ -10,7 +12,7 @@ export const authRouter = router({
|
|
|
10
12
|
password: z.string().min(6),
|
|
11
13
|
}),
|
|
12
14
|
)
|
|
13
|
-
.mutation(
|
|
15
|
+
.mutation(({input}) => {
|
|
14
16
|
// Mock authentication logic
|
|
15
17
|
if (input.email === 'demo@example.com' && input.password === 'password') {
|
|
16
18
|
return {
|
|
@@ -23,7 +25,5 @@ export const authRouter = router({
|
|
|
23
25
|
message: 'Invalid email or password',
|
|
24
26
|
});
|
|
25
27
|
}),
|
|
26
|
-
me: protectedProcedure.query(({ctx}) =>
|
|
27
|
-
return ctx.user;
|
|
28
|
-
}),
|
|
28
|
+
me: protectedProcedure.query(({ctx}) => ctx.user),
|
|
29
29
|
});
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
/* eslint-disable typescript/promise-function-async */
|
|
1
2
|
import {initTRPC, TRPCError} from '@trpc/server';
|
|
2
|
-
import {Context} from './context.js';
|
|
3
|
+
import {type Context} from './context.js';
|
|
3
4
|
|
|
4
5
|
const t = initTRPC.context<Context>().create();
|
|
5
6
|
|
|
6
|
-
export const router = t
|
|
7
|
-
export const createCallerFactory = t.createCallerFactory;
|
|
8
|
-
export const publicProcedure = t.procedure;
|
|
7
|
+
export const {router, createCallerFactory, procedure: publicProcedure} = t;
|
|
9
8
|
export const protectedProcedure = t.procedure.use(({ctx, next}) => {
|
|
10
9
|
if (!ctx.user) {
|
|
11
10
|
throw new TRPCError({code: 'UNAUTHORIZED'});
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {defineConfig, devices} from '@playwright/test';
|
|
2
|
+
import {env} from 'node:process';
|
|
3
|
+
|
|
4
|
+
const isCi = env.CI !== undefined;
|
|
2
5
|
|
|
3
6
|
export default defineConfig({
|
|
4
7
|
testDir: './tests/e2e',
|
|
5
8
|
testMatch: '**/*.e2e-test.ts',
|
|
6
9
|
fullyParallel: true,
|
|
7
|
-
forbidOnly:
|
|
8
|
-
retries:
|
|
9
|
-
workers:
|
|
10
|
+
forbidOnly: isCi,
|
|
11
|
+
retries: isCi ? 2 : 0,
|
|
12
|
+
workers: isCi ? 1 : undefined,
|
|
10
13
|
reporter: 'html',
|
|
11
14
|
use: {
|
|
12
15
|
baseURL: 'http://localhost:5173',
|
|
@@ -21,6 +24,6 @@ export default defineConfig({
|
|
|
21
24
|
webServer: {
|
|
22
25
|
command: 'npm run dev',
|
|
23
26
|
url: 'http://localhost:5173',
|
|
24
|
-
reuseExistingServer: !
|
|
27
|
+
reuseExistingServer: !isCi,
|
|
25
28
|
},
|
|
26
29
|
});
|
|
@@ -7,6 +7,6 @@ test('formatMessage returns correct string', () => {
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
test('createHeading renders in the browser', async () => {
|
|
10
|
-
document.body.
|
|
10
|
+
document.body.append(createHeading('Browser Test'));
|
|
11
11
|
await expect.element(page.getByRole('heading', {name: 'Browser Test'})).toBeVisible();
|
|
12
12
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-template-project",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "An ultra-modular, type-safe Node.js CLI tool used to scaffold new project templates (CLI, Webpage, Webapp, Fullstack) with best-practice configurations pre-installed.",
|
|
6
6
|
"keywords": [
|
|
@@ -46,6 +46,11 @@
|
|
|
46
46
|
".": "./dist/index.js",
|
|
47
47
|
"./package.json": "./package.json"
|
|
48
48
|
},
|
|
49
|
+
"imports": {
|
|
50
|
+
"#shared/*.js": "./src/shared/*.ts",
|
|
51
|
+
"#templates/*.js": "./src/templates/*.ts",
|
|
52
|
+
"#templating/*.js": "./src/utils/templating/*.ts"
|
|
53
|
+
},
|
|
49
54
|
"scripts": {
|
|
50
55
|
"run-interactive": "node ./dist/index.js interactive",
|
|
51
56
|
"build": "vite build && node scripts/copy-templates.ts",
|
|
@@ -77,20 +82,21 @@
|
|
|
77
82
|
"@commitlint/config-conventional": "20.5.0",
|
|
78
83
|
"@types/cli-progress": "3.11.6",
|
|
79
84
|
"@types/debug": "4.1.13",
|
|
80
|
-
"@
|
|
85
|
+
"@types/node": "25.6.0",
|
|
86
|
+
"@vitest/coverage-v8": "4.1.4",
|
|
81
87
|
"conventional-changelog": "7.2.0",
|
|
82
88
|
"conventional-changelog-angular": "8.3.1",
|
|
83
89
|
"eslint-plugin-regexp": "3.1.0",
|
|
84
90
|
"husky": "9.1.7",
|
|
85
|
-
"oxfmt": "0.
|
|
86
|
-
"oxlint": "1.
|
|
87
|
-
"oxlint-tsgolint": "0.
|
|
91
|
+
"oxfmt": "0.45.0",
|
|
92
|
+
"oxlint": "1.60.0",
|
|
93
|
+
"oxlint-tsgolint": "0.20.0",
|
|
88
94
|
"pnpm": "10.33.0",
|
|
89
95
|
"release-it": "19.2.4",
|
|
90
96
|
"rimraf": "6.1.3",
|
|
91
97
|
"typescript": "6.0.2",
|
|
92
|
-
"vite": "8.0.
|
|
93
|
-
"vitest": "4.1.
|
|
98
|
+
"vite": "8.0.8",
|
|
99
|
+
"vitest": "4.1.4"
|
|
94
100
|
},
|
|
95
101
|
"engines": {
|
|
96
102
|
"node": ">=22"
|