create-template-project 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/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/cli.mjs +272 -0
- package/dist/config/dependencies.json +156 -0
- package/dist/generators/project.mjs +354 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +32 -0
- package/dist/templates/base/files/.github/workflows/node.js.yml +20 -0
- package/dist/templates/base/files/.prettierrc.json +6 -0
- package/dist/templates/base/files/AGENTS.md +5 -0
- package/dist/templates/base/files/CONTRIBUTING.md +31 -0
- package/dist/templates/base/files/README.md +23 -0
- package/dist/templates/base/files/_oxlint.config.ts +74 -0
- package/dist/templates/base/files/commitlint.config.js +1 -0
- package/dist/templates/base/files/package.json +32 -0
- package/dist/templates/base/files/tsconfig.json +42 -0
- package/dist/templates/base/files/vitest.config.ts +3 -0
- package/dist/templates/base/index.mjs +16 -0
- package/dist/templates/cli/files/package.json +14 -0
- package/dist/templates/cli/files/src/index.test.ts +5 -0
- package/dist/templates/cli/files/src/index.ts +13 -0
- package/dist/templates/cli/files/tsdown.config.ts +3 -0
- package/dist/templates/cli/index.mjs +16 -0
- package/dist/templates/fullstack/files/client/index.html +8 -0
- package/dist/templates/fullstack/files/client/package.json +10 -0
- package/dist/templates/fullstack/files/client/src/App.test.tsx +8 -0
- package/dist/templates/fullstack/files/client/src/App.tsx +50 -0
- package/dist/templates/fullstack/files/client/src/components/ProtectedRoute.tsx +21 -0
- package/dist/templates/fullstack/files/client/src/contexts/AuthContext.tsx +63 -0
- package/dist/templates/fullstack/files/client/src/main.tsx +9 -0
- package/dist/templates/fullstack/files/client/src/pages/Dashboard.tsx +39 -0
- package/dist/templates/fullstack/files/client/src/pages/Login.tsx +81 -0
- package/dist/templates/fullstack/files/client/src/trpc.ts +4 -0
- package/dist/templates/fullstack/files/client/tsdown.config.ts +3 -0
- package/dist/templates/fullstack/files/package.json +35 -0
- package/dist/templates/fullstack/files/server/package.json +10 -0
- package/dist/templates/fullstack/files/server/src/context.ts +24 -0
- package/dist/templates/fullstack/files/server/src/index.test.ts +7 -0
- package/dist/templates/fullstack/files/server/src/index.ts +32 -0
- package/dist/templates/fullstack/files/server/src/routers/_app.ts +8 -0
- package/dist/templates/fullstack/files/server/src/routers/auth.ts +29 -0
- package/dist/templates/fullstack/files/server/src/trpc.ts +18 -0
- package/dist/templates/fullstack/files/server/tsdown.config.ts +3 -0
- package/dist/templates/fullstack/index.mjs +42 -0
- package/dist/templates/webapp/files/backend/src/index.ts +17 -0
- package/dist/templates/webapp/files/frontend/index.html +9 -0
- package/dist/templates/webapp/files/frontend/src/index.ts +4 -0
- package/dist/templates/webapp/files/package.json +13 -0
- package/dist/templates/webapp/files/src/index.test.ts +5 -0
- package/dist/templates/webapp/files/tsdown.config.ts +10 -0
- package/dist/templates/webapp/index.mjs +16 -0
- package/dist/templates/webpage/files/index.html +8 -0
- package/dist/templates/webpage/files/package.json +8 -0
- package/dist/templates/webpage/files/src/index.test.ts +5 -0
- package/dist/templates/webpage/files/src/index.ts +1 -0
- package/dist/templates/webpage/index.mjs +16 -0
- package/dist/types.mjs +30 -0
- package/dist/utils/file.mjs +101 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025- Dieter Oberkofler
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# create-template-project
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/create-template-project)
|
|
4
|
+
[](https://www.npmjs.com/package/create-template-project)
|
|
5
|
+
[](https://github.com/doberkofler/create-template-project/actions/workflows/node.js.yml)
|
|
6
|
+
[](https://coveralls.io/github/doberkofler/create-template-project?branch=master)
|
|
7
|
+
|
|
8
|
+
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.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Modern Tech Stack:** All templates come with `commitlint`, `husky`, `vitest`, `oxlint`, `prettier`, and `typescript` (strict mode).
|
|
13
|
+
- **Interactive CLI:** Prompts you for project details if CLI arguments are missing, using `@clack/prompts`.
|
|
14
|
+
- **Update Mode:** Detects existing projects and offers a safe update path using `git merge-file`.
|
|
15
|
+
- **No-Build Option:** Supports creating simple projects without a build step (strips `tsdown`).
|
|
16
|
+
- **GitHub Integration:** Automatically initializes a Git repository and can create a GitHub repository using the `gh` CLI.
|
|
17
|
+
- **CI Ready:** Generates GitHub Actions workflows for automated testing and linting.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g create-template-project
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or run directly using npx:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx create-template-project
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### Interactive Mode
|
|
34
|
+
|
|
35
|
+
To start the interactive wizard, use the `interactive` command:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
create-template-project interactive
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Running the tool without any command will display the help message.
|
|
42
|
+
|
|
43
|
+
### CLI Commands
|
|
44
|
+
|
|
45
|
+
You can skip the wizard by using the `create` or `update` commands with the appropriate options.
|
|
46
|
+
|
|
47
|
+
#### Create a new project
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
create-template-project create --template cli --name my-cool-tool --github
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### Update an existing project
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
create-template-project update --template cli --name existing-project
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### Global Options:
|
|
60
|
+
|
|
61
|
+
- `-h, --help`: Show help
|
|
62
|
+
- `-V, --version`: Show version
|
|
63
|
+
|
|
64
|
+
#### Command Options (create/update):
|
|
65
|
+
|
|
66
|
+
- `-t, --template <type>`: Template type (`cli`, `webpage`, `webapp`, `fullstack`)
|
|
67
|
+
- `-n, --name <name>`: Project name
|
|
68
|
+
- `--github`: Create GitHub project (requires `gh` CLI authenticated)
|
|
69
|
+
- `-d, --directory <path>`: Output directory (defaults to `.`)
|
|
70
|
+
- `--overwrite`: Overwrite existing directory by removing it first (create & update)
|
|
71
|
+
- `--no-build`: Create a project without a build step (not allowed for `webapp`)
|
|
72
|
+
- `--silent`: Reduce console output (useful for CI and scripts)
|
|
73
|
+
|
|
74
|
+
## Project Templates
|
|
75
|
+
|
|
76
|
+
### 🟢 CLI
|
|
77
|
+
A clean Node.js CLI environment featuring `commander` and `cli-progress`. Supports optional `tsdown` bundling.
|
|
78
|
+
|
|
79
|
+
### 🔵 Webpage
|
|
80
|
+
Standalone web page setup for modern browsers. Can be used with or without a build step.
|
|
81
|
+
|
|
82
|
+
### 🟡 Webapp
|
|
83
|
+
Classic web application structure with a `frontend/` and a `backend/` Express server. Built with TypeScript.
|
|
84
|
+
|
|
85
|
+
### ⚛️ Fullstack
|
|
86
|
+
A full-stack monorepo featuring:
|
|
87
|
+
- **Client**: React with MUI (including Icons) and TypeScript.
|
|
88
|
+
- **Server**: Express.js backend.
|
|
89
|
+
- **E2E**: Playwright for end-to-end testing.
|
|
90
|
+
|
|
91
|
+
## Contributing
|
|
92
|
+
|
|
93
|
+
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
MIT © [Dieter Oberkofler](https://github.com/doberkofler)
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { ProjectOptionsSchema } from "./types.mjs";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import * as p from "@clack/prompts";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import fs from "node:fs/promises";
|
|
6
|
+
import debugLib from "debug";
|
|
7
|
+
//#region src/cli.ts
|
|
8
|
+
const pathExists = (p) => fs.access(p).then(() => true).catch(() => false);
|
|
9
|
+
const debug = debugLib("create-template-project:cli");
|
|
10
|
+
const parseArgs = async () => {
|
|
11
|
+
debug("Parsing CLI arguments: %O", process.argv);
|
|
12
|
+
const program = new Command();
|
|
13
|
+
if (process.env.NODE_ENV === "test") program.configureOutput({
|
|
14
|
+
writeOut: () => {},
|
|
15
|
+
writeErr: () => {}
|
|
16
|
+
});
|
|
17
|
+
program.name("create-template-project").exitOverride().description("Scaffold a new project template").version("0.1.0").option("--debug", "Enable debug output").on("option:debug", () => {
|
|
18
|
+
debugLib.enable("create-template-project:*");
|
|
19
|
+
}).addHelpText("after", `
|
|
20
|
+
Templates:
|
|
21
|
+
cli - Node.js CLI application with commander and cli-progress.
|
|
22
|
+
webpage - Standalone web page (modern HTML/JS).
|
|
23
|
+
webapp - Web application with TypeScript and an Express backend.
|
|
24
|
+
fullstack - Full-stack monorepo with Express server and React/MUI client.
|
|
25
|
+
`);
|
|
26
|
+
let commandResult;
|
|
27
|
+
program.command("create").description("Create a new project from a template").option("-t, --template <type>", "Template type (cli, webpage, webapp, 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
|
+
debug("Executing \"create\" command with options: %O", opts);
|
|
29
|
+
if (opts.template === "webapp" && opts.skipBuild) {
|
|
30
|
+
p.log.error("The --skip-build option is not allowed for the \"webapp\" template.");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
commandResult = {
|
|
34
|
+
...opts,
|
|
35
|
+
update: false,
|
|
36
|
+
template: opts.template,
|
|
37
|
+
projectName: opts.name,
|
|
38
|
+
packageManager: opts.packageManager,
|
|
39
|
+
directory: path.resolve(opts.directory),
|
|
40
|
+
createGithubRepository: !!opts.createGithubRepository,
|
|
41
|
+
overwrite: !!opts.overwrite,
|
|
42
|
+
silent: !!opts.silent
|
|
43
|
+
};
|
|
44
|
+
debug("Processed \"create\" options: %O", commandResult);
|
|
45
|
+
});
|
|
46
|
+
program.command("update").description("Update an existing project from its template").option("-t, --template <type>", "Template type (cli, webpage, webapp, 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
|
+
debug("Executing \"update\" command with options: %O", opts);
|
|
48
|
+
if (opts.template === "webapp" && opts.skipBuild) {
|
|
49
|
+
p.log.error("The --skip-build option is not allowed for the \"webapp\" template.");
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
commandResult = {
|
|
53
|
+
...opts,
|
|
54
|
+
update: true,
|
|
55
|
+
template: opts.template,
|
|
56
|
+
projectName: opts.name,
|
|
57
|
+
packageManager: opts.packageManager,
|
|
58
|
+
directory: path.resolve(opts.directory),
|
|
59
|
+
createGithubRepository: !!opts.createGithubRepository,
|
|
60
|
+
overwrite: !!opts.overwrite,
|
|
61
|
+
silent: !!opts.silent
|
|
62
|
+
};
|
|
63
|
+
debug("Processed \"update\" options: %O", commandResult);
|
|
64
|
+
});
|
|
65
|
+
program.command("interactive").description("Start interactive project configuration").action(async () => {
|
|
66
|
+
debug("Starting interactive configuration");
|
|
67
|
+
const projectName = await p.text({
|
|
68
|
+
message: "Project name:",
|
|
69
|
+
placeholder: "my-app",
|
|
70
|
+
defaultValue: "my-app",
|
|
71
|
+
validate: (value) => value && value.length > 0 ? void 0 : "Project name is required"
|
|
72
|
+
});
|
|
73
|
+
if (p.isCancel(projectName)) {
|
|
74
|
+
p.cancel("Operation cancelled.");
|
|
75
|
+
process.exit(0);
|
|
76
|
+
}
|
|
77
|
+
const directory = await p.text({
|
|
78
|
+
message: "Target directory:",
|
|
79
|
+
initialValue: "."
|
|
80
|
+
});
|
|
81
|
+
if (p.isCancel(directory)) {
|
|
82
|
+
p.cancel("Operation cancelled.");
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
const projectDir = path.resolve(directory, projectName);
|
|
86
|
+
const exists = await pathExists(projectDir);
|
|
87
|
+
const pkgPath = path.join(projectDir, "package.json");
|
|
88
|
+
const pkgExists = await pathExists(pkgPath);
|
|
89
|
+
let existingConfig = {};
|
|
90
|
+
if (pkgExists) try {
|
|
91
|
+
existingConfig = JSON.parse(await fs.readFile(pkgPath, "utf8"))["create-template-project"] || {};
|
|
92
|
+
debug("Found existing project config: %O", existingConfig);
|
|
93
|
+
} catch (e) {
|
|
94
|
+
debug("Failed to read existing package.json: %O", e);
|
|
95
|
+
}
|
|
96
|
+
let update = false;
|
|
97
|
+
let overwrite = false;
|
|
98
|
+
if (exists) {
|
|
99
|
+
const action = await p.select({
|
|
100
|
+
message: `Directory "${projectDir}" already exists. What would you like to do?`,
|
|
101
|
+
options: [
|
|
102
|
+
{
|
|
103
|
+
label: "Run an update",
|
|
104
|
+
value: "update"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
label: "Overwrite existing directory by removing it first",
|
|
108
|
+
value: "overwrite"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
label: "Cancel",
|
|
112
|
+
value: "cancel"
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
});
|
|
116
|
+
if (p.isCancel(action) || action === "cancel") {
|
|
117
|
+
p.cancel("Operation cancelled.");
|
|
118
|
+
process.exit(0);
|
|
119
|
+
}
|
|
120
|
+
if (action === "update") update = true;
|
|
121
|
+
else if (action === "overwrite") overwrite = true;
|
|
122
|
+
}
|
|
123
|
+
let template = existingConfig.template;
|
|
124
|
+
if (!update || !template) {
|
|
125
|
+
template = await p.select({
|
|
126
|
+
message: "Select project template:",
|
|
127
|
+
initialValue: template || "cli",
|
|
128
|
+
options: [
|
|
129
|
+
{
|
|
130
|
+
label: "CLI Application (Node.js)",
|
|
131
|
+
value: "cli"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
label: "Webpage (Standalone)",
|
|
135
|
+
value: "webpage"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
label: "Webapp (Express Backend)",
|
|
139
|
+
value: "webapp"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
label: "Full-stack (Express + React/MUI Monorepo)",
|
|
143
|
+
value: "fullstack"
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
});
|
|
147
|
+
if (p.isCancel(template)) {
|
|
148
|
+
p.cancel("Operation cancelled.");
|
|
149
|
+
process.exit(0);
|
|
150
|
+
}
|
|
151
|
+
} else p.log.info(`Using existing template type: ${template}`);
|
|
152
|
+
let packageManager = "npm";
|
|
153
|
+
if (!update) {
|
|
154
|
+
packageManager = await p.select({
|
|
155
|
+
message: "Select package manager:",
|
|
156
|
+
initialValue: "npm",
|
|
157
|
+
options: [
|
|
158
|
+
{
|
|
159
|
+
label: "npm",
|
|
160
|
+
value: "npm"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
label: "pnpm",
|
|
164
|
+
value: "pnpm"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
label: "yarn",
|
|
168
|
+
value: "yarn"
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
});
|
|
172
|
+
if (p.isCancel(packageManager)) {
|
|
173
|
+
p.cancel("Operation cancelled.");
|
|
174
|
+
process.exit(0);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
let skipBuild = false;
|
|
178
|
+
if (template !== "webapp") {
|
|
179
|
+
const res = await p.confirm({
|
|
180
|
+
message: "Should we use build tooling? (Enables bundling using tsdown, and uses raw dist/ instead of src/)",
|
|
181
|
+
initialValue: true
|
|
182
|
+
});
|
|
183
|
+
if (p.isCancel(res)) {
|
|
184
|
+
p.cancel("Operation cancelled.");
|
|
185
|
+
process.exit(0);
|
|
186
|
+
}
|
|
187
|
+
skipBuild = !res;
|
|
188
|
+
}
|
|
189
|
+
const installDependenciesRes = await p.confirm({
|
|
190
|
+
message: "Should we install dependencies?",
|
|
191
|
+
initialValue: true
|
|
192
|
+
});
|
|
193
|
+
if (p.isCancel(installDependenciesRes)) {
|
|
194
|
+
p.cancel("Operation cancelled.");
|
|
195
|
+
process.exit(0);
|
|
196
|
+
}
|
|
197
|
+
const installDependencies = installDependenciesRes;
|
|
198
|
+
let build = false;
|
|
199
|
+
if (installDependencies) {
|
|
200
|
+
const res = await p.confirm({
|
|
201
|
+
message: "Should we run the CI script (lint, build, test)?",
|
|
202
|
+
initialValue: true
|
|
203
|
+
});
|
|
204
|
+
if (p.isCancel(res)) {
|
|
205
|
+
p.cancel("Operation cancelled.");
|
|
206
|
+
process.exit(0);
|
|
207
|
+
}
|
|
208
|
+
build = res;
|
|
209
|
+
}
|
|
210
|
+
const createGithubRepositoryRes = await p.confirm({
|
|
211
|
+
message: "Should we create a GitHub repository?",
|
|
212
|
+
initialValue: false
|
|
213
|
+
});
|
|
214
|
+
if (p.isCancel(createGithubRepositoryRes)) {
|
|
215
|
+
p.cancel("Operation cancelled.");
|
|
216
|
+
process.exit(0);
|
|
217
|
+
}
|
|
218
|
+
commandResult = {
|
|
219
|
+
template,
|
|
220
|
+
projectName,
|
|
221
|
+
packageManager,
|
|
222
|
+
createGithubRepository: createGithubRepositoryRes,
|
|
223
|
+
directory: path.resolve(directory),
|
|
224
|
+
update,
|
|
225
|
+
overwrite,
|
|
226
|
+
skipBuild,
|
|
227
|
+
installDependencies,
|
|
228
|
+
build,
|
|
229
|
+
dev: false,
|
|
230
|
+
open: false,
|
|
231
|
+
silent: false
|
|
232
|
+
};
|
|
233
|
+
});
|
|
234
|
+
if (process.argv.length <= 2) {
|
|
235
|
+
program.outputHelp();
|
|
236
|
+
process.exit(0);
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
await program.parseAsync(process.argv);
|
|
240
|
+
} catch (e) {
|
|
241
|
+
if (e.code === "commander.helpDisplayed" || e.code === "commander.version" || e.code === "PROCESS_EXIT_0") process.exit(0);
|
|
242
|
+
if (e.code === "PROCESS_EXIT_1") process.exit(1);
|
|
243
|
+
p.cancel(e.message);
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
if (!commandResult) {
|
|
247
|
+
debug("No command result found");
|
|
248
|
+
p.cancel("Unknown command or missing options.");
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
debug("Validating command result with Zod");
|
|
252
|
+
const validationResult = ProjectOptionsSchema.safeParse(commandResult);
|
|
253
|
+
if (!validationResult.success) {
|
|
254
|
+
const errors = validationResult.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
255
|
+
p.cancel(`Invalid options: ${errors}`);
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
commandResult = validationResult.data;
|
|
259
|
+
const projectDir = path.resolve(commandResult.directory, commandResult.projectName);
|
|
260
|
+
if (await pathExists(projectDir) && !commandResult.update && !commandResult.overwrite) {
|
|
261
|
+
p.cancel(`Directory "${projectDir}" already exists. Use --overwrite to overwrite or "update" command.`);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
if (commandResult.open) {
|
|
265
|
+
commandResult.dev = true;
|
|
266
|
+
commandResult.installDependencies = true;
|
|
267
|
+
}
|
|
268
|
+
if (commandResult.dev || commandResult.build) commandResult.installDependencies = true;
|
|
269
|
+
return commandResult;
|
|
270
|
+
};
|
|
271
|
+
//#endregion
|
|
272
|
+
export { parseArgs };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"debug": {
|
|
4
|
+
"version": "^4.4.3",
|
|
5
|
+
"description": "A tiny JavaScript debugging utility modelled after Node.js core debugging technique."
|
|
6
|
+
},
|
|
7
|
+
"@commitlint/cli": {
|
|
8
|
+
"version": "^20.4.4",
|
|
9
|
+
"description": "Lint commit messages to ensure they follow conventional commits."
|
|
10
|
+
},
|
|
11
|
+
"@commitlint/config-conventional": {
|
|
12
|
+
"version": "^20.4.4",
|
|
13
|
+
"description": "Shareable commitlint config enforcing conventional commits."
|
|
14
|
+
},
|
|
15
|
+
"@types/debug": {
|
|
16
|
+
"version": "^4.1.12",
|
|
17
|
+
"description": "TypeScript definitions for debug."
|
|
18
|
+
},
|
|
19
|
+
"@types/node": {
|
|
20
|
+
"version": "^25.5.0",
|
|
21
|
+
"description": "TypeScript definitions for Node.js."
|
|
22
|
+
},
|
|
23
|
+
"@vitest/coverage-v8": {
|
|
24
|
+
"version": "^4.1.0",
|
|
25
|
+
"description": "V8 coverage provider for Vitest."
|
|
26
|
+
},
|
|
27
|
+
"conventional-changelog": {
|
|
28
|
+
"version": "^7.2.0",
|
|
29
|
+
"description": "Generate a changelog from git metadata."
|
|
30
|
+
},
|
|
31
|
+
"husky": {
|
|
32
|
+
"version": "^9.1.7",
|
|
33
|
+
"description": "Modern native git hooks made easy."
|
|
34
|
+
},
|
|
35
|
+
"oxlint": {
|
|
36
|
+
"version": "^1.55.0",
|
|
37
|
+
"description": "A JavaScript linter written in Rust."
|
|
38
|
+
},
|
|
39
|
+
"oxlint-tsgolint": {
|
|
40
|
+
"version": "^0.16.0",
|
|
41
|
+
"description": "TypeScript-specific rules for oxlint."
|
|
42
|
+
},
|
|
43
|
+
"prettier": {
|
|
44
|
+
"version": "^3.8.1",
|
|
45
|
+
"description": "An opinionated code formatter."
|
|
46
|
+
},
|
|
47
|
+
"typescript": {
|
|
48
|
+
"version": "^5.9.3",
|
|
49
|
+
"description": "A superset of JavaScript that compiles to clean JavaScript output."
|
|
50
|
+
},
|
|
51
|
+
"vitest": {
|
|
52
|
+
"version": "^4.1.0",
|
|
53
|
+
"description": "A Vite-native unit test framework."
|
|
54
|
+
},
|
|
55
|
+
"commander": {
|
|
56
|
+
"version": "^14.0.3",
|
|
57
|
+
"description": "The complete solution for node.js command-line interfaces."
|
|
58
|
+
},
|
|
59
|
+
"cli-progress": {
|
|
60
|
+
"version": "^3.12.0",
|
|
61
|
+
"description": "Easy to use progress-bar for command-line/terminal applications."
|
|
62
|
+
},
|
|
63
|
+
"@types/cli-progress": {
|
|
64
|
+
"version": "^3.11.6",
|
|
65
|
+
"description": "TypeScript definitions for cli-progress."
|
|
66
|
+
},
|
|
67
|
+
"tsdown": {
|
|
68
|
+
"version": "^0.21.2",
|
|
69
|
+
"description": "A zero-config bundler for TypeScript."
|
|
70
|
+
},
|
|
71
|
+
"express": {
|
|
72
|
+
"version": "^5.2.1",
|
|
73
|
+
"description": "Fast, unopinionated, minimalist web framework for Node.js."
|
|
74
|
+
},
|
|
75
|
+
"@types/express": {
|
|
76
|
+
"version": "^5.0.6",
|
|
77
|
+
"description": "TypeScript definitions for Express."
|
|
78
|
+
},
|
|
79
|
+
"react": {
|
|
80
|
+
"version": "^19.2.4",
|
|
81
|
+
"description": "A JavaScript library for building user interfaces."
|
|
82
|
+
},
|
|
83
|
+
"react-dom": {
|
|
84
|
+
"version": "^19.2.4",
|
|
85
|
+
"description": "React package for working with the DOM."
|
|
86
|
+
},
|
|
87
|
+
"@mui/material": {
|
|
88
|
+
"version": "^7.3.9",
|
|
89
|
+
"description": "Material UI components."
|
|
90
|
+
},
|
|
91
|
+
"@mui/icons-material": {
|
|
92
|
+
"version": "^7.3.9",
|
|
93
|
+
"description": "Material Design icons distributed as SVG React components."
|
|
94
|
+
},
|
|
95
|
+
"@emotion/react": {
|
|
96
|
+
"version": "^11.14.0",
|
|
97
|
+
"description": "CSS-in-JS library designed for high performance."
|
|
98
|
+
},
|
|
99
|
+
"@emotion/styled": {
|
|
100
|
+
"version": "^11.14.1",
|
|
101
|
+
"description": "Styled components for Emotion."
|
|
102
|
+
},
|
|
103
|
+
"@types/react": {
|
|
104
|
+
"version": "^19.2.14",
|
|
105
|
+
"description": "TypeScript definitions for React."
|
|
106
|
+
},
|
|
107
|
+
"@types/react-dom": {
|
|
108
|
+
"version": "^19.2.3",
|
|
109
|
+
"description": "TypeScript definitions for React DOM."
|
|
110
|
+
},
|
|
111
|
+
"@playwright/test": {
|
|
112
|
+
"version": "^1.58.2",
|
|
113
|
+
"description": "End-to-end testing framework."
|
|
114
|
+
},
|
|
115
|
+
"@trpc/server": {
|
|
116
|
+
"version": "^11.12.0",
|
|
117
|
+
"description": "tRPC server library."
|
|
118
|
+
},
|
|
119
|
+
"@trpc/client": {
|
|
120
|
+
"version": "^11.12.0",
|
|
121
|
+
"description": "tRPC client library."
|
|
122
|
+
},
|
|
123
|
+
"@trpc/react-query": {
|
|
124
|
+
"version": "^11.12.0",
|
|
125
|
+
"description": "tRPC integration for React Query."
|
|
126
|
+
},
|
|
127
|
+
"@tanstack/react-query": {
|
|
128
|
+
"version": "^5.90.21",
|
|
129
|
+
"description": "Powerful asynchronous state management for TS/JS."
|
|
130
|
+
},
|
|
131
|
+
"zod": {
|
|
132
|
+
"version": "^4.3.6",
|
|
133
|
+
"description": "TypeScript-first schema validation with static type inference."
|
|
134
|
+
},
|
|
135
|
+
"tinyexec": {
|
|
136
|
+
"version": "^1.0.4",
|
|
137
|
+
"description": "A minimal library for executing processes in Node (pinned to 1.0.2 due to broken 1.0.3 release)."
|
|
138
|
+
},
|
|
139
|
+
"react-router-dom": {
|
|
140
|
+
"version": "^7.13.1",
|
|
141
|
+
"description": "Declarative routing for React web applications."
|
|
142
|
+
},
|
|
143
|
+
"cors": {
|
|
144
|
+
"version": "^2.8.6",
|
|
145
|
+
"description": "Node.js CORS middleware."
|
|
146
|
+
},
|
|
147
|
+
"@types/cors": {
|
|
148
|
+
"version": "^2.8.19",
|
|
149
|
+
"description": "TypeScript definitions for cors."
|
|
150
|
+
},
|
|
151
|
+
"eslint-plugin-regexp": {
|
|
152
|
+
"version": "^3.1.0",
|
|
153
|
+
"description": "ESLint plugin for finding regexp mistakes and style guide violations."
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|