create-template-project 0.1.0 → 0.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 +8 -8
- package/dist/cli.mjs +54 -18
- package/dist/config/dependencies.json +59 -39
- package/dist/generators/info.mjs +58 -0
- package/dist/generators/project.mjs +60 -27
- package/dist/index.mjs +4 -1
- package/dist/templates/base/files/.github/workflows/node.js.yml +5 -3
- package/dist/templates/base/files/.prettierignore +50 -0
- package/dist/templates/base/files/.prettierrc.json +4 -2
- package/dist/templates/base/files/AGENTS.md +5 -2
- package/dist/templates/base/files/README.md +36 -13
- package/dist/templates/base/files/_oxlint.config.ts +17 -33
- package/dist/templates/base/files/tsconfig.json +32 -32
- package/dist/templates/base/files/vitest.config.ts +2 -2
- package/dist/templates/base/index.mjs +40 -1
- package/dist/templates/cli/index.mjs +14 -1
- package/dist/templates/web-app/files/index.html +11 -0
- package/dist/templates/web-app/files/playwright.config.ts +26 -0
- package/dist/templates/web-app/files/src/index.tsx +21 -0
- package/dist/templates/web-app/files/tests/e2e/basic.e2e-test.ts +13 -0
- package/dist/templates/web-app/files/vite.config.ts +30 -0
- package/dist/templates/web-app/index.mjs +69 -0
- package/dist/templates/web-fullstack/files/client/index.html +10 -0
- package/dist/templates/{fullstack → web-fullstack}/files/client/package.json +2 -2
- package/dist/templates/{fullstack → web-fullstack}/files/client/src/contexts/AuthContext.tsx +1 -5
- package/dist/templates/{fullstack → web-fullstack}/files/client/src/pages/Login.tsx +4 -33
- package/dist/templates/web-fullstack/files/client/vite.config.ts +26 -0
- package/dist/templates/web-fullstack/files/playwright.config.ts +33 -0
- package/dist/templates/{fullstack → web-fullstack}/files/server/package.json +2 -2
- package/dist/templates/web-fullstack/files/server/vite.config.ts +21 -0
- package/dist/templates/web-fullstack/files/tests/e2e/basic.e2e-test.ts +14 -0
- package/dist/templates/web-fullstack/index.mjs +78 -0
- package/dist/templates/web-vanilla/files/index.html +11 -0
- package/dist/templates/web-vanilla/files/package.json +17 -0
- package/dist/templates/web-vanilla/files/playwright.config.ts +26 -0
- package/dist/templates/web-vanilla/files/tests/e2e/basic.e2e-test.ts +11 -0
- package/dist/templates/web-vanilla/files/vite.config.ts +24 -0
- package/dist/templates/web-vanilla/index.mjs +45 -0
- package/dist/types.mjs +4 -4
- package/dist/utils/file.mjs +31 -13
- package/package.json +24 -21
- package/dist/templates/fullstack/files/client/index.html +0 -8
- package/dist/templates/fullstack/files/client/tsdown.config.ts +0 -3
- package/dist/templates/fullstack/files/server/tsdown.config.ts +0 -3
- package/dist/templates/fullstack/index.mjs +0 -42
- package/dist/templates/webapp/files/backend/src/index.ts +0 -17
- package/dist/templates/webapp/files/frontend/index.html +0 -9
- package/dist/templates/webapp/files/frontend/src/index.ts +0 -4
- package/dist/templates/webapp/files/package.json +0 -13
- package/dist/templates/webapp/files/tsdown.config.ts +0 -10
- package/dist/templates/webapp/index.mjs +0 -16
- package/dist/templates/webpage/files/index.html +0 -8
- package/dist/templates/webpage/files/package.json +0 -8
- package/dist/templates/webpage/index.mjs +0 -16
- /package/dist/templates/{webapp → web-app}/files/src/index.test.ts +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/client/src/App.test.tsx +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/client/src/App.tsx +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/client/src/components/ProtectedRoute.tsx +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/client/src/main.tsx +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/client/src/pages/Dashboard.tsx +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/client/src/trpc.ts +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/package.json +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/server/src/context.ts +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/server/src/index.test.ts +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/server/src/index.ts +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/server/src/routers/_app.ts +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/server/src/routers/auth.ts +0 -0
- /package/dist/templates/{fullstack → web-fullstack}/files/server/src/trpc.ts +0 -0
- /package/dist/templates/{webpage → web-vanilla}/files/src/index.test.ts +0 -0
- /package/dist/templates/{webpage → web-vanilla}/files/src/index.ts +0 -0
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/doberkofler/create-template-project/actions/workflows/node.js.yml)
|
|
6
6
|
[](https://coveralls.io/github/doberkofler/create-template-project?branch=master)
|
|
7
7
|
|
|
8
|
-
An ultra-modular, type-safe Node.js CLI tool used to scaffold new project templates (CLI,
|
|
8
|
+
An ultra-modular, type-safe Node.js CLI tool used to scaffold new project templates (CLI, Web-Vanilla, Web-App, Web-Fullstack) with best-practice configurations pre-installed.
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
@@ -63,12 +63,12 @@ create-template-project update --template cli --name existing-project
|
|
|
63
63
|
|
|
64
64
|
#### Command Options (create/update):
|
|
65
65
|
|
|
66
|
-
- `-t, --template <type>`: Template type (`cli`, `
|
|
66
|
+
- `-t, --template <type>`: Template type (`cli`, `web-vanilla`, `web-app`, `web-fullstack`)
|
|
67
67
|
- `-n, --name <name>`: Project name
|
|
68
68
|
- `--github`: Create GitHub project (requires `gh` CLI authenticated)
|
|
69
69
|
- `-d, --directory <path>`: Output directory (defaults to `.`)
|
|
70
70
|
- `--overwrite`: Overwrite existing directory by removing it first (create & update)
|
|
71
|
-
- `--no-build`: Create a project without a build step (not allowed for `
|
|
71
|
+
- `--no-build`: Create a project without a build step (not allowed for `web-app`)
|
|
72
72
|
- `--silent`: Reduce console output (useful for CI and scripts)
|
|
73
73
|
|
|
74
74
|
## Project Templates
|
|
@@ -76,16 +76,16 @@ create-template-project update --template cli --name existing-project
|
|
|
76
76
|
### 🟢 CLI
|
|
77
77
|
A clean Node.js CLI environment featuring `commander` and `cli-progress`. Supports optional `tsdown` bundling.
|
|
78
78
|
|
|
79
|
-
### 🔵
|
|
79
|
+
### 🔵 Web-Vanilla
|
|
80
80
|
Standalone web page setup for modern browsers. Can be used with or without a build step.
|
|
81
81
|
|
|
82
|
-
### 🟡
|
|
83
|
-
|
|
82
|
+
### 🟡 Web-App
|
|
83
|
+
Modern React application featuring MUI components and TanStack Query for state management.
|
|
84
84
|
|
|
85
|
-
### ⚛️ Fullstack
|
|
85
|
+
### ⚛️ Web-Fullstack
|
|
86
86
|
A full-stack monorepo featuring:
|
|
87
87
|
- **Client**: React with MUI (including Icons) and TypeScript.
|
|
88
|
-
- **Server**: Express.js backend.
|
|
88
|
+
- **Server**: Express.js backend with tRPC for end-to-end type safety.
|
|
89
89
|
- **E2E**: Playwright for end-to-end testing.
|
|
90
90
|
|
|
91
91
|
## Contributing
|
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ProjectOptionsSchema } from "./types.mjs";
|
|
1
|
+
import { ProjectOptionsSchema, TemplateTypeSchema } from "./types.mjs";
|
|
2
|
+
import { getAllTemplatesInfo, getTemplateInfo } from "./generators/info.mjs";
|
|
2
3
|
import { Command } from "commander";
|
|
3
4
|
import * as p from "@clack/prompts";
|
|
4
5
|
import path from "node:path";
|
|
@@ -15,19 +16,54 @@ const parseArgs = async () => {
|
|
|
15
16
|
writeErr: () => {}
|
|
16
17
|
});
|
|
17
18
|
program.name("create-template-project").exitOverride().description("Scaffold a new project template").version("0.1.0").option("--debug", "Enable debug output").on("option:debug", () => {
|
|
19
|
+
process.env["DEBUG"] = "create-template-project:*";
|
|
18
20
|
debugLib.enable("create-template-project:*");
|
|
19
21
|
}).addHelpText("after", `
|
|
22
|
+
Commands:
|
|
23
|
+
create - Create a new project from a template.
|
|
24
|
+
update - Update an existing project from its template.
|
|
25
|
+
interactive - Start interactive project configuration.
|
|
26
|
+
info - Show detailed information about available templates and components.
|
|
27
|
+
|
|
20
28
|
Templates:
|
|
21
|
-
cli
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
fullstack
|
|
29
|
+
cli - Node.js CLI application with commander and cli-progress.
|
|
30
|
+
web-vanilla - Standalone web page (modern HTML/JS).
|
|
31
|
+
web-app - React application with MUI and TanStack Query.
|
|
32
|
+
web-fullstack - Full-stack monorepo with Express server and React/MUI client.
|
|
25
33
|
`);
|
|
26
34
|
let commandResult;
|
|
27
|
-
program.command("
|
|
35
|
+
program.command("info").description("Show detailed information about available templates and their components").option("-t, --template <type>", "Template type (cli, web-vanilla, web-app, web-fullstack)").action((opts) => {
|
|
36
|
+
debug("Executing \"info\" command with options: %O", opts);
|
|
37
|
+
p.intro("Template Information");
|
|
38
|
+
if (opts.template) {
|
|
39
|
+
const typeResult = TemplateTypeSchema.safeParse(opts.template);
|
|
40
|
+
if (!typeResult.success) {
|
|
41
|
+
p.log.error(`Invalid template type: ${opts.template}. Must be one of: cli, web-vanilla, web-app, web-fullstack`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const info = getTemplateInfo(typeResult.data);
|
|
45
|
+
p.note([
|
|
46
|
+
`Description: ${info.description}`,
|
|
47
|
+
"",
|
|
48
|
+
"Components:",
|
|
49
|
+
...info.components.map((c) => ` ● ${c.name}: ${c.description}`)
|
|
50
|
+
].join("\n"), `Template: ${info.name}`);
|
|
51
|
+
} else {
|
|
52
|
+
const allInfo = getAllTemplatesInfo();
|
|
53
|
+
for (const info of allInfo) p.note([
|
|
54
|
+
`Description: ${info.description}`,
|
|
55
|
+
"",
|
|
56
|
+
"Components:",
|
|
57
|
+
...info.components.map((c) => ` ● ${c.name}: ${c.description}`)
|
|
58
|
+
].join("\n"), `Template: ${info.name}`);
|
|
59
|
+
}
|
|
60
|
+
p.outro("Use \"create\" to scaffold a new project.");
|
|
61
|
+
process.exit(0);
|
|
62
|
+
});
|
|
63
|
+
program.command("create").description("Create a new project from a template").option("-t, --template <type>", "Template type (cli, web-vanilla, web-app, web-fullstack)").option("-n, --name <name>", "Project name").option("-p, --package-manager <pm>", "Package manager (npm, pnpm, yarn)", "npm").option("--create-github-repository", "Create GitHub project").option("-d, --directory <path>", "Output directory", ".").option("--overwrite", "Overwrite existing directory by removing it first", false).option("--skip-build", "Skip build tooling (disables bundling and uses raw source files)", false).option("--install-dependencies", "Install dependencies after scaffolding", false).option("--build", "Run the CI script (lint, build, test) after scaffolding", false).option("--dev", "Run the dev server after scaffolding", false).option("--open", "Open the browser after scaffolding", false).option("--silent", "Reduce console output", false).action((opts) => {
|
|
28
64
|
debug("Executing \"create\" command with options: %O", opts);
|
|
29
|
-
if (opts.template === "
|
|
30
|
-
p.log.error("The --skip-build option is not allowed for the \"
|
|
65
|
+
if (opts.template === "web-app" && opts.skipBuild) {
|
|
66
|
+
p.log.error("The --skip-build option is not allowed for the \"web-app\" template.");
|
|
31
67
|
process.exit(1);
|
|
32
68
|
}
|
|
33
69
|
commandResult = {
|
|
@@ -43,10 +79,10 @@ Templates:
|
|
|
43
79
|
};
|
|
44
80
|
debug("Processed \"create\" options: %O", commandResult);
|
|
45
81
|
});
|
|
46
|
-
program.command("update").description("Update an existing project from its template").option("-t, --template <type>", "Template type (cli,
|
|
82
|
+
program.command("update").description("Update an existing project from its template").option("-t, --template <type>", "Template type (cli, web-vanilla, web-app, web-fullstack)").option("-n, --name <name>", "Project name").option("-p, --package-manager <pm>", "Package manager (npm, pnpm, yarn)", "npm").option("--create-github-repository", "Create GitHub project").option("-d, --directory <path>", "Output directory", ".").option("--overwrite", "Overwrite existing directory by removing it first", false).option("--skip-build", "Skip build tooling (disables bundling and uses raw source files)", false).option("--install-dependencies", "Install dependencies after scaffolding", false).option("--build", "Run the CI script (lint, build, test) after updating", false).option("--dev", "Run the dev server after scaffolding", false).option("--open", "Open the browser after scaffolding", false).option("--silent", "Reduce console output", false).action((opts) => {
|
|
47
83
|
debug("Executing \"update\" command with options: %O", opts);
|
|
48
|
-
if (opts.template === "
|
|
49
|
-
p.log.error("The --skip-build option is not allowed for the \"
|
|
84
|
+
if (opts.template === "web-app" && opts.skipBuild) {
|
|
85
|
+
p.log.error("The --skip-build option is not allowed for the \"web-app\" template.");
|
|
50
86
|
process.exit(1);
|
|
51
87
|
}
|
|
52
88
|
commandResult = {
|
|
@@ -131,16 +167,16 @@ Templates:
|
|
|
131
167
|
value: "cli"
|
|
132
168
|
},
|
|
133
169
|
{
|
|
134
|
-
label: "
|
|
135
|
-
value: "
|
|
170
|
+
label: "Web-Vanilla (Standalone)",
|
|
171
|
+
value: "web-vanilla"
|
|
136
172
|
},
|
|
137
173
|
{
|
|
138
|
-
label: "
|
|
139
|
-
value: "
|
|
174
|
+
label: "Web-App (React + MUI)",
|
|
175
|
+
value: "web-app"
|
|
140
176
|
},
|
|
141
177
|
{
|
|
142
|
-
label: "
|
|
143
|
-
value: "fullstack"
|
|
178
|
+
label: "Web-Fullstack (Express + React Monorepo)",
|
|
179
|
+
value: "web-fullstack"
|
|
144
180
|
}
|
|
145
181
|
]
|
|
146
182
|
});
|
|
@@ -175,7 +211,7 @@ Templates:
|
|
|
175
211
|
}
|
|
176
212
|
}
|
|
177
213
|
let skipBuild = false;
|
|
178
|
-
if (template !== "
|
|
214
|
+
if (template !== "web-app") {
|
|
179
215
|
const res = await p.confirm({
|
|
180
216
|
message: "Should we use build tooling? (Enables bundling using tsdown, and uses raw dist/ instead of src/)",
|
|
181
217
|
initialValue: true
|
|
@@ -1,155 +1,175 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
|
+
"vite": {
|
|
4
|
+
"version": "8.0.1",
|
|
5
|
+
"description": "Native-ESM powered web dev build tool"
|
|
6
|
+
},
|
|
7
|
+
"@vitejs/plugin-react": {
|
|
8
|
+
"version": "6.0.1",
|
|
9
|
+
"description": "The default Vite plugin for React projects."
|
|
10
|
+
},
|
|
11
|
+
"@vitest/browser": {
|
|
12
|
+
"version": "4.1.0",
|
|
13
|
+
"description": "Run Vitest in the browser."
|
|
14
|
+
},
|
|
15
|
+
"@vitest/browser-playwright": {
|
|
16
|
+
"version": "4.1.0",
|
|
17
|
+
"description": "Playwright provider for Vitest browser mode."
|
|
18
|
+
},
|
|
19
|
+
"playwright": {
|
|
20
|
+
"version": "1.58.2",
|
|
21
|
+
"description": "Framework for Web-browser automation."
|
|
22
|
+
},
|
|
3
23
|
"debug": {
|
|
4
|
-
"version": "
|
|
24
|
+
"version": "4.4.3",
|
|
5
25
|
"description": "A tiny JavaScript debugging utility modelled after Node.js core debugging technique."
|
|
6
26
|
},
|
|
7
27
|
"@commitlint/cli": {
|
|
8
|
-
"version": "
|
|
28
|
+
"version": "20.5.0",
|
|
9
29
|
"description": "Lint commit messages to ensure they follow conventional commits."
|
|
10
30
|
},
|
|
11
31
|
"@commitlint/config-conventional": {
|
|
12
|
-
"version": "
|
|
32
|
+
"version": "20.5.0",
|
|
13
33
|
"description": "Shareable commitlint config enforcing conventional commits."
|
|
14
34
|
},
|
|
15
35
|
"@types/debug": {
|
|
16
|
-
"version": "^4.1.
|
|
36
|
+
"version": "^4.1.13",
|
|
17
37
|
"description": "TypeScript definitions for debug."
|
|
18
38
|
},
|
|
19
39
|
"@types/node": {
|
|
20
|
-
"version": "
|
|
40
|
+
"version": "25.5.0",
|
|
21
41
|
"description": "TypeScript definitions for Node.js."
|
|
22
42
|
},
|
|
23
43
|
"@vitest/coverage-v8": {
|
|
24
|
-
"version": "
|
|
44
|
+
"version": "4.1.0",
|
|
25
45
|
"description": "V8 coverage provider for Vitest."
|
|
26
46
|
},
|
|
27
47
|
"conventional-changelog": {
|
|
28
|
-
"version": "
|
|
48
|
+
"version": "7.2.0",
|
|
29
49
|
"description": "Generate a changelog from git metadata."
|
|
30
50
|
},
|
|
31
51
|
"husky": {
|
|
32
|
-
"version": "
|
|
52
|
+
"version": "9.1.7",
|
|
33
53
|
"description": "Modern native git hooks made easy."
|
|
34
54
|
},
|
|
35
55
|
"oxlint": {
|
|
36
|
-
"version": "
|
|
56
|
+
"version": "1.56.0",
|
|
37
57
|
"description": "A JavaScript linter written in Rust."
|
|
38
58
|
},
|
|
39
59
|
"oxlint-tsgolint": {
|
|
40
|
-
"version": "
|
|
60
|
+
"version": "0.17.0",
|
|
41
61
|
"description": "TypeScript-specific rules for oxlint."
|
|
42
62
|
},
|
|
43
63
|
"prettier": {
|
|
44
|
-
"version": "
|
|
64
|
+
"version": "3.8.1",
|
|
45
65
|
"description": "An opinionated code formatter."
|
|
46
66
|
},
|
|
47
67
|
"typescript": {
|
|
48
|
-
"version": "
|
|
68
|
+
"version": "5.9.3",
|
|
49
69
|
"description": "A superset of JavaScript that compiles to clean JavaScript output."
|
|
50
70
|
},
|
|
51
71
|
"vitest": {
|
|
52
|
-
"version": "
|
|
72
|
+
"version": "4.1.0",
|
|
53
73
|
"description": "A Vite-native unit test framework."
|
|
54
74
|
},
|
|
55
75
|
"commander": {
|
|
56
|
-
"version": "
|
|
76
|
+
"version": "14.0.3",
|
|
57
77
|
"description": "The complete solution for node.js command-line interfaces."
|
|
58
78
|
},
|
|
59
79
|
"cli-progress": {
|
|
60
|
-
"version": "
|
|
80
|
+
"version": "3.12.0",
|
|
61
81
|
"description": "Easy to use progress-bar for command-line/terminal applications."
|
|
62
82
|
},
|
|
63
83
|
"@types/cli-progress": {
|
|
64
|
-
"version": "
|
|
84
|
+
"version": "3.11.6",
|
|
65
85
|
"description": "TypeScript definitions for cli-progress."
|
|
66
86
|
},
|
|
67
87
|
"tsdown": {
|
|
68
|
-
"version": "
|
|
88
|
+
"version": "0.21.4",
|
|
69
89
|
"description": "A zero-config bundler for TypeScript."
|
|
70
90
|
},
|
|
71
91
|
"express": {
|
|
72
|
-
"version": "
|
|
92
|
+
"version": "5.2.1",
|
|
73
93
|
"description": "Fast, unopinionated, minimalist web framework for Node.js."
|
|
74
94
|
},
|
|
75
95
|
"@types/express": {
|
|
76
|
-
"version": "
|
|
96
|
+
"version": "5.0.6",
|
|
77
97
|
"description": "TypeScript definitions for Express."
|
|
78
98
|
},
|
|
79
99
|
"react": {
|
|
80
|
-
"version": "
|
|
100
|
+
"version": "19.2.4",
|
|
81
101
|
"description": "A JavaScript library for building user interfaces."
|
|
82
102
|
},
|
|
83
103
|
"react-dom": {
|
|
84
|
-
"version": "
|
|
104
|
+
"version": "19.2.4",
|
|
85
105
|
"description": "React package for working with the DOM."
|
|
86
106
|
},
|
|
87
107
|
"@mui/material": {
|
|
88
|
-
"version": "
|
|
108
|
+
"version": "7.3.9",
|
|
89
109
|
"description": "Material UI components."
|
|
90
110
|
},
|
|
91
111
|
"@mui/icons-material": {
|
|
92
|
-
"version": "
|
|
112
|
+
"version": "7.3.9",
|
|
93
113
|
"description": "Material Design icons distributed as SVG React components."
|
|
94
114
|
},
|
|
95
115
|
"@emotion/react": {
|
|
96
|
-
"version": "
|
|
116
|
+
"version": "11.14.0",
|
|
97
117
|
"description": "CSS-in-JS library designed for high performance."
|
|
98
118
|
},
|
|
99
119
|
"@emotion/styled": {
|
|
100
|
-
"version": "
|
|
120
|
+
"version": "11.14.1",
|
|
101
121
|
"description": "Styled components for Emotion."
|
|
102
122
|
},
|
|
103
123
|
"@types/react": {
|
|
104
|
-
"version": "
|
|
124
|
+
"version": "19.2.14",
|
|
105
125
|
"description": "TypeScript definitions for React."
|
|
106
126
|
},
|
|
107
127
|
"@types/react-dom": {
|
|
108
|
-
"version": "
|
|
128
|
+
"version": "19.2.3",
|
|
109
129
|
"description": "TypeScript definitions for React DOM."
|
|
110
130
|
},
|
|
111
131
|
"@playwright/test": {
|
|
112
|
-
"version": "
|
|
132
|
+
"version": "1.58.2",
|
|
113
133
|
"description": "End-to-end testing framework."
|
|
114
134
|
},
|
|
115
135
|
"@trpc/server": {
|
|
116
|
-
"version": "
|
|
136
|
+
"version": "11.13.4",
|
|
117
137
|
"description": "tRPC server library."
|
|
118
138
|
},
|
|
119
139
|
"@trpc/client": {
|
|
120
|
-
"version": "
|
|
140
|
+
"version": "11.13.4",
|
|
121
141
|
"description": "tRPC client library."
|
|
122
142
|
},
|
|
123
143
|
"@trpc/react-query": {
|
|
124
|
-
"version": "
|
|
144
|
+
"version": "11.13.4",
|
|
125
145
|
"description": "tRPC integration for React Query."
|
|
126
146
|
},
|
|
127
147
|
"@tanstack/react-query": {
|
|
128
|
-
"version": "^5.
|
|
148
|
+
"version": "^5.91.2",
|
|
129
149
|
"description": "Powerful asynchronous state management for TS/JS."
|
|
130
150
|
},
|
|
131
151
|
"zod": {
|
|
132
|
-
"version": "
|
|
152
|
+
"version": "4.3.6",
|
|
133
153
|
"description": "TypeScript-first schema validation with static type inference."
|
|
134
154
|
},
|
|
135
155
|
"tinyexec": {
|
|
136
|
-
"version": "
|
|
137
|
-
"description": "A minimal library for executing processes in Node
|
|
156
|
+
"version": "1.0.4",
|
|
157
|
+
"description": "A minimal library for executing processes in Node."
|
|
138
158
|
},
|
|
139
159
|
"react-router-dom": {
|
|
140
|
-
"version": "
|
|
160
|
+
"version": "7.13.1",
|
|
141
161
|
"description": "Declarative routing for React web applications."
|
|
142
162
|
},
|
|
143
163
|
"cors": {
|
|
144
|
-
"version": "
|
|
164
|
+
"version": "2.8.6",
|
|
145
165
|
"description": "Node.js CORS middleware."
|
|
146
166
|
},
|
|
147
167
|
"@types/cors": {
|
|
148
|
-
"version": "
|
|
168
|
+
"version": "2.8.19",
|
|
149
169
|
"description": "TypeScript definitions for cors."
|
|
150
170
|
},
|
|
151
171
|
"eslint-plugin-regexp": {
|
|
152
|
-
"version": "
|
|
172
|
+
"version": "3.1.0",
|
|
153
173
|
"description": "ESLint plugin for finding regexp mistakes and style guide violations."
|
|
154
174
|
}
|
|
155
175
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { getBaseTemplate } from "../templates/base/index.mjs";
|
|
2
|
+
import { getCliTemplate } from "../templates/cli/index.mjs";
|
|
3
|
+
import { getWebVanillaTemplate } from "../templates/web-vanilla/index.mjs";
|
|
4
|
+
import { getWebAppTemplate } from "../templates/web-app/index.mjs";
|
|
5
|
+
import { getWebFullstackTemplate } from "../templates/web-fullstack/index.mjs";
|
|
6
|
+
//#region src/generators/info.ts
|
|
7
|
+
const MOCK_OPTS = {
|
|
8
|
+
template: "cli",
|
|
9
|
+
projectName: "mock",
|
|
10
|
+
directory: ".",
|
|
11
|
+
packageManager: "npm",
|
|
12
|
+
overwrite: false,
|
|
13
|
+
update: false,
|
|
14
|
+
skipBuild: false,
|
|
15
|
+
installDependencies: false,
|
|
16
|
+
build: false,
|
|
17
|
+
dev: false,
|
|
18
|
+
open: false,
|
|
19
|
+
silent: true,
|
|
20
|
+
createGithubRepository: false
|
|
21
|
+
};
|
|
22
|
+
const getTemplateInfo = (type) => {
|
|
23
|
+
const opts = {
|
|
24
|
+
...MOCK_OPTS,
|
|
25
|
+
template: type
|
|
26
|
+
};
|
|
27
|
+
const base = getBaseTemplate(opts);
|
|
28
|
+
let template;
|
|
29
|
+
switch (type) {
|
|
30
|
+
case "cli":
|
|
31
|
+
template = getCliTemplate(opts);
|
|
32
|
+
break;
|
|
33
|
+
case "web-vanilla":
|
|
34
|
+
template = getWebVanillaTemplate(opts);
|
|
35
|
+
break;
|
|
36
|
+
case "web-app":
|
|
37
|
+
template = getWebAppTemplate(opts);
|
|
38
|
+
break;
|
|
39
|
+
case "web-fullstack":
|
|
40
|
+
template = getWebFullstackTemplate(opts);
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
name: template.name,
|
|
45
|
+
description: template.description,
|
|
46
|
+
components: [...base.components, ...template.components]
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
const getAllTemplatesInfo = () => {
|
|
50
|
+
return [
|
|
51
|
+
"cli",
|
|
52
|
+
"web-vanilla",
|
|
53
|
+
"web-app",
|
|
54
|
+
"web-fullstack"
|
|
55
|
+
].map((type) => getTemplateInfo(type));
|
|
56
|
+
};
|
|
57
|
+
//#endregion
|
|
58
|
+
export { getAllTemplatesInfo, getTemplateInfo };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getBaseTemplate } from "../templates/base/index.mjs";
|
|
2
2
|
import { getCliTemplate } from "../templates/cli/index.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { getWebVanillaTemplate } from "../templates/web-vanilla/index.mjs";
|
|
4
|
+
import { getWebAppTemplate } from "../templates/web-app/index.mjs";
|
|
5
|
+
import { getWebFullstackTemplate } from "../templates/web-fullstack/index.mjs";
|
|
6
6
|
import { getAllFiles, isSeedFile, mergeFile, mergePackageJson, processContent } from "../utils/file.mjs";
|
|
7
7
|
import * as p from "@clack/prompts";
|
|
8
8
|
import path from "node:path";
|
|
@@ -29,7 +29,11 @@ const getSpinner = (silent) => {
|
|
|
29
29
|
message: (msg) => !silent ? s.message(msg) : void 0
|
|
30
30
|
};
|
|
31
31
|
};
|
|
32
|
-
const showNote = (msg, title, silent) =>
|
|
32
|
+
const showNote = (msg, title, silent) => {
|
|
33
|
+
if (silent) return;
|
|
34
|
+
if (title) p.log.success(title);
|
|
35
|
+
p.note(msg);
|
|
36
|
+
};
|
|
33
37
|
const generateProject = async (opts) => {
|
|
34
38
|
const { template: type, projectName, directory, update, overwrite, skipBuild, silent } = opts;
|
|
35
39
|
const isSilent = !!silent;
|
|
@@ -56,17 +60,17 @@ const generateProject = async (opts) => {
|
|
|
56
60
|
debug("Applying template: cli");
|
|
57
61
|
templates.push(getCliTemplate(opts));
|
|
58
62
|
break;
|
|
59
|
-
case "
|
|
60
|
-
debug("Applying template:
|
|
61
|
-
templates.push(
|
|
63
|
+
case "web-vanilla":
|
|
64
|
+
debug("Applying template: web-vanilla");
|
|
65
|
+
templates.push(getWebVanillaTemplate(opts));
|
|
62
66
|
break;
|
|
63
|
-
case "
|
|
64
|
-
debug("Applying template:
|
|
65
|
-
templates.push(
|
|
67
|
+
case "web-app":
|
|
68
|
+
debug("Applying template: web-app");
|
|
69
|
+
templates.push(getWebAppTemplate(opts));
|
|
66
70
|
break;
|
|
67
|
-
case "fullstack":
|
|
68
|
-
debug("Applying template: fullstack");
|
|
69
|
-
templates.push(
|
|
71
|
+
case "web-fullstack":
|
|
72
|
+
debug("Applying template: web-fullstack");
|
|
73
|
+
templates.push(getWebFullstackTemplate(opts));
|
|
70
74
|
break;
|
|
71
75
|
}
|
|
72
76
|
debug("Ensuring directory exists: %s", projectDir);
|
|
@@ -124,6 +128,7 @@ const generateProject = async (opts) => {
|
|
|
124
128
|
Object.assign(finalPkg.scripts, t.scripts);
|
|
125
129
|
Object.assign(finalPkg.dependencies, templateDeps);
|
|
126
130
|
Object.assign(finalPkg.devDependencies, templateDevDeps);
|
|
131
|
+
if (t.workspaces) finalPkg.workspaces = t.workspaces;
|
|
127
132
|
if (t.templateDir) {
|
|
128
133
|
const templatePkgPath = path.join(t.templateDir, "package.json");
|
|
129
134
|
if (await pathExists(templatePkgPath)) {
|
|
@@ -156,8 +161,8 @@ const generateProject = async (opts) => {
|
|
|
156
161
|
let content = await fs.readFile(file, "utf8");
|
|
157
162
|
content = processContent(relativePath, content, opts, addedDeps);
|
|
158
163
|
let finalTargetPath = targetPath;
|
|
159
|
-
if (type === "
|
|
160
|
-
debug("Changing target path for
|
|
164
|
+
if (type === "web-vanilla" && skipBuild && relativePath === "src/index.ts") {
|
|
165
|
+
debug("Changing target path for web-vanilla index.ts to .js due to skipBuild");
|
|
161
166
|
finalTargetPath = path.join(projectDir, "src/index.js");
|
|
162
167
|
}
|
|
163
168
|
if (isUpdate && await pathExists(finalTargetPath)) {
|
|
@@ -209,37 +214,51 @@ const generateProject = async (opts) => {
|
|
|
209
214
|
const workspaceYaml = `packages:\n${finalPkg.workspaces.map((w) => ` - '${w}'`).join("\n")}\n`;
|
|
210
215
|
await fs.writeFile(path.join(projectDir, "pnpm-workspace.yaml"), workspaceYaml);
|
|
211
216
|
delete finalPkg.workspaces;
|
|
212
|
-
for (const
|
|
217
|
+
for (const key of Object.keys(finalPkg.scripts)) {
|
|
218
|
+
const value = finalPkg.scripts[key];
|
|
219
|
+
if (typeof value === "string" && value.includes("--workspaces")) finalPkg.scripts[key] = value.replace(" run ", " -r run ").replace(" --workspaces", "");
|
|
220
|
+
}
|
|
213
221
|
}
|
|
214
222
|
if (skipBuild) {
|
|
215
223
|
debug("Applying skipBuild overrides");
|
|
216
224
|
delete finalPkg.scripts.build;
|
|
217
225
|
delete finalPkg.scripts.dev;
|
|
218
|
-
if (finalPkg.devDependencies)
|
|
226
|
+
if (finalPkg.devDependencies) {
|
|
227
|
+
delete finalPkg.devDependencies.tsdown;
|
|
228
|
+
delete finalPkg.devDependencies.vite;
|
|
229
|
+
delete finalPkg.devDependencies["@vitejs/plugin-react"];
|
|
230
|
+
}
|
|
219
231
|
if (finalPkg.scripts.ci) finalPkg.scripts.ci = finalPkg.scripts.ci.replace(" && npm run build", "").replace(` && ${pm} run build`, "");
|
|
220
|
-
debug("Removing
|
|
232
|
+
debug("Removing build tool configs due to skipBuild");
|
|
221
233
|
await fs.rm(path.join(projectDir, "tsdown.config.ts"), { force: true });
|
|
222
|
-
await fs.rm(path.join(projectDir, "
|
|
223
|
-
await fs.rm(path.join(projectDir, "
|
|
234
|
+
await fs.rm(path.join(projectDir, "vite.config.ts"), { force: true });
|
|
235
|
+
await fs.rm(path.join(projectDir, "vite.config.server.ts"), { force: true });
|
|
236
|
+
await fs.rm(path.join(projectDir, "client/vite.config.ts"), { force: true });
|
|
237
|
+
await fs.rm(path.join(projectDir, "server/vite.config.ts"), { force: true });
|
|
224
238
|
}
|
|
225
239
|
debug("Writing final consolidated package.json to: %s", pkgPath);
|
|
226
240
|
await fs.writeFile(pkgPath, JSON.stringify(finalPkg, null, " "));
|
|
241
|
+
const stdio = debug.enabled ? "inherit" : "pipe";
|
|
227
242
|
if (!await pathExists(path.join(projectDir, ".git"))) {
|
|
228
243
|
debug("Initializing Git repository");
|
|
229
244
|
try {
|
|
245
|
+
debug("Executing: git init");
|
|
230
246
|
await execa("git", ["init"], {
|
|
231
247
|
cwd: projectDir,
|
|
248
|
+
stdio,
|
|
232
249
|
preferLocal: true
|
|
233
250
|
});
|
|
234
251
|
log.success("Initialized Git repository (git init).");
|
|
235
252
|
} catch (e) {
|
|
236
253
|
debug("Failed to initialize Git: %O", e);
|
|
237
|
-
|
|
254
|
+
const detail = e.stdout || e.stderr ? `\n\nOutput:\n${e.stdout}\n${e.stderr}` : "";
|
|
255
|
+
log.error(`Failed to initialize Git: ${e.message}${detail}`);
|
|
238
256
|
}
|
|
239
257
|
}
|
|
240
258
|
if (opts.createGithubRepository && !isUpdate) {
|
|
241
259
|
debug("Creating GitHub repository");
|
|
242
260
|
try {
|
|
261
|
+
debug("Executing: gh repo create %s --public --source=. --remote=origin", projectName);
|
|
243
262
|
await execa("gh", [
|
|
244
263
|
"repo",
|
|
245
264
|
"create",
|
|
@@ -249,12 +268,14 @@ const generateProject = async (opts) => {
|
|
|
249
268
|
"--remote=origin"
|
|
250
269
|
], {
|
|
251
270
|
cwd: projectDir,
|
|
271
|
+
stdio,
|
|
252
272
|
preferLocal: true
|
|
253
273
|
});
|
|
254
274
|
log.success("Created GitHub repository (gh repo create).");
|
|
255
275
|
} catch (e) {
|
|
256
276
|
debug("Failed to create GitHub repository: %O", e);
|
|
257
|
-
|
|
277
|
+
const detail = e.stdout || e.stderr ? `\n\nOutput:\n${e.stdout}\n${e.stderr}` : "";
|
|
278
|
+
log.warn(`Failed to create GitHub repository: ${e.message}${detail}\nEnsure "gh" CLI is installed and authenticated.`);
|
|
258
279
|
}
|
|
259
280
|
}
|
|
260
281
|
if (opts.installDependencies) {
|
|
@@ -262,16 +283,19 @@ const generateProject = async (opts) => {
|
|
|
262
283
|
const s = spinner();
|
|
263
284
|
s.start(`Installing dependencies using ${pm}...`);
|
|
264
285
|
try {
|
|
286
|
+
debug("Executing: %s install", pm);
|
|
265
287
|
await execa(pm, ["install"], {
|
|
266
288
|
cwd: projectDir,
|
|
289
|
+
stdio,
|
|
267
290
|
preferLocal: true
|
|
268
291
|
});
|
|
269
292
|
s.stop(`\x1b[1G\x1b[2K\x1b[32m◆\x1b[39m Dependencies installed (${pm} install).`);
|
|
270
293
|
} catch (e) {
|
|
271
294
|
debug("Failed to install dependencies: %O", e);
|
|
272
295
|
s.stop("Failed to install dependencies.");
|
|
273
|
-
|
|
274
|
-
|
|
296
|
+
const detail = e.stdout || e.stderr ? `\n\nOutput:\n${e.stdout}\n${e.stderr}` : "";
|
|
297
|
+
log.error(`${e.message}${detail}`);
|
|
298
|
+
throw new Error(`Failed to install dependencies: ${e.message}${detail}`);
|
|
275
299
|
}
|
|
276
300
|
}
|
|
277
301
|
if (opts.build && finalPkg.scripts.ci) {
|
|
@@ -280,35 +304,43 @@ const generateProject = async (opts) => {
|
|
|
280
304
|
if (finalPkg.scripts["prettier-write"]) {
|
|
281
305
|
s.start(`Formatting files with Prettier (${pm} run prettier-write)...`);
|
|
282
306
|
try {
|
|
307
|
+
debug("Executing: %s run prettier-write", pm);
|
|
283
308
|
await execa(pm, ["run", "prettier-write"], {
|
|
284
309
|
cwd: projectDir,
|
|
310
|
+
stdio,
|
|
285
311
|
preferLocal: true
|
|
286
312
|
});
|
|
287
313
|
s.stop(`\x1b[1G\x1b[2K\x1b[32m◆\x1b[39m Files formatted (${pm} run prettier-write).`);
|
|
288
314
|
} catch (e) {
|
|
289
315
|
debug("Failed to format files: %O", e);
|
|
290
316
|
s.stop("Failed to format files.");
|
|
317
|
+
const detail = e.stdout || e.stderr ? `\n\nOutput:\n${e.stdout}\n${e.stderr}` : "";
|
|
318
|
+
log.error(`${e.message}${detail}`);
|
|
291
319
|
}
|
|
292
320
|
}
|
|
293
321
|
s.start(`Running CI script (lint, build, test) (${pm} run ci)...`);
|
|
294
322
|
try {
|
|
323
|
+
debug("Executing: %s run ci", pm);
|
|
295
324
|
await execa(pm, ["run", "ci"], {
|
|
296
325
|
cwd: projectDir,
|
|
326
|
+
stdio,
|
|
297
327
|
preferLocal: true
|
|
298
328
|
});
|
|
299
329
|
s.stop(`\x1b[1G\x1b[2K\x1b[32m◆\x1b[39m CI script completed (${pm} run ci).`);
|
|
300
330
|
} catch (e) {
|
|
301
331
|
debug("Failed to run CI script: %O", e);
|
|
302
332
|
s.stop("Failed to run CI script.");
|
|
303
|
-
|
|
304
|
-
|
|
333
|
+
const detail = e.stdout || e.stderr ? `\n\nOutput:\n${e.stdout}\n${e.stderr}` : "";
|
|
334
|
+
log.error(`${e.message}${detail}`);
|
|
335
|
+
throw new Error(`Failed to run CI script: ${e.message}${detail}`);
|
|
305
336
|
}
|
|
306
337
|
}
|
|
307
|
-
log.
|
|
338
|
+
log.success(`Project "${projectName}" ${isUpdate ? "updated" : "scaffolded"} successfully in ${projectDir}`);
|
|
308
339
|
showSummary(opts, pm, isSilent);
|
|
309
340
|
if (opts.dev && finalPkg.scripts.dev) {
|
|
310
341
|
log.info("Starting dev server...");
|
|
311
342
|
if (opts.open) try {
|
|
343
|
+
debug("Executing: %s run dev -- --open", pm);
|
|
312
344
|
await execa(pm, [
|
|
313
345
|
"run",
|
|
314
346
|
"dev",
|
|
@@ -323,6 +355,7 @@ const generateProject = async (opts) => {
|
|
|
323
355
|
log.error("Dev server failed: " + e);
|
|
324
356
|
}
|
|
325
357
|
else try {
|
|
358
|
+
debug("Executing: %s run dev", pm);
|
|
326
359
|
await execa(pm, ["run", "dev"], {
|
|
327
360
|
cwd: projectDir,
|
|
328
361
|
stdio: "inherit",
|