create-template-project 0.2.0 → 0.3.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 +3 -3
- package/dist/config/dependencies.json +10 -14
- package/dist/index.js +1221 -0
- package/dist/templates/base/files/.husky/commit-msg +1 -0
- package/dist/templates/base/files/.husky/pre-commit +1 -0
- package/dist/templates/base/files/.prettierignore +3 -0
- package/dist/templates/base/files/package.json +1 -1
- package/dist/templates/base/files/vitest.config.ts +10 -1
- package/dist/templates/cli/files/package.json +4 -3
- package/dist/templates/cli/files/src/index.test.ts +10 -2
- package/dist/templates/cli/files/src/index.ts +4 -1
- package/dist/templates/cli/files/src/lib.ts +10 -0
- package/dist/templates/cli/files/vite.config.ts +22 -0
- package/dist/templates/web-app/files/src/App.test.tsx +9 -0
- package/dist/templates/web-app/files/src/App.tsx +14 -0
- package/dist/templates/web-app/files/src/index.tsx +1 -14
- package/dist/templates/web-app/files/vite.config.ts +4 -0
- package/dist/templates/web-fullstack/files/client/src/App.test.tsx +5 -2
- package/dist/templates/web-fullstack/files/client/vite.config.ts +4 -0
- package/dist/templates/web-fullstack/files/package.json +1 -2
- package/dist/templates/web-fullstack/files/server/src/index.test.ts +24 -3
- package/dist/templates/web-fullstack/files/server/src/trpc.ts +1 -1
- package/dist/templates/web-fullstack/files/server/vite.config.ts +6 -3
- package/dist/templates/web-vanilla/files/index.html +1 -1
- package/dist/templates/web-vanilla/files/src/index.test.ts +9 -2
- package/dist/templates/web-vanilla/files/src/index.ts +3 -1
- package/dist/templates/web-vanilla/files/src/lib.ts +9 -0
- package/dist/templates/web-vanilla/files/vite.config.ts +4 -0
- package/package.json +13 -18
- package/dist/cli.mjs +0 -308
- package/dist/generators/info.mjs +0 -58
- package/dist/generators/project.mjs +0 -387
- package/dist/index.d.mts +0 -4
- package/dist/index.mjs +0 -35
- package/dist/templates/base/index.mjs +0 -55
- package/dist/templates/cli/files/tsdown.config.ts +0 -3
- package/dist/templates/cli/index.mjs +0 -29
- package/dist/templates/web-app/files/src/index.test.ts +0 -5
- package/dist/templates/web-app/index.mjs +0 -69
- package/dist/templates/web-fullstack/index.mjs +0 -78
- package/dist/templates/web-vanilla/index.mjs +0 -45
- package/dist/types.mjs +0 -30
- package/dist/utils/file.mjs +0 -119
package/dist/cli.mjs
DELETED
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { ProjectOptionsSchema, TemplateTypeSchema } from "./types.mjs";
|
|
2
|
-
import { getAllTemplatesInfo, getTemplateInfo } from "./generators/info.mjs";
|
|
3
|
-
import { Command } from "commander";
|
|
4
|
-
import * as p from "@clack/prompts";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import fs from "node:fs/promises";
|
|
7
|
-
import debugLib from "debug";
|
|
8
|
-
//#region src/cli.ts
|
|
9
|
-
const pathExists = (p) => fs.access(p).then(() => true).catch(() => false);
|
|
10
|
-
const debug = debugLib("create-template-project:cli");
|
|
11
|
-
const parseArgs = async () => {
|
|
12
|
-
debug("Parsing CLI arguments: %O", process.argv);
|
|
13
|
-
const program = new Command();
|
|
14
|
-
if (process.env.NODE_ENV === "test") program.configureOutput({
|
|
15
|
-
writeOut: () => {},
|
|
16
|
-
writeErr: () => {}
|
|
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:*";
|
|
20
|
-
debugLib.enable("create-template-project:*");
|
|
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
|
-
|
|
28
|
-
Templates:
|
|
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.
|
|
33
|
-
`);
|
|
34
|
-
let commandResult;
|
|
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) => {
|
|
64
|
-
debug("Executing \"create\" command with options: %O", opts);
|
|
65
|
-
if (opts.template === "web-app" && opts.skipBuild) {
|
|
66
|
-
p.log.error("The --skip-build option is not allowed for the \"web-app\" template.");
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
|
-
commandResult = {
|
|
70
|
-
...opts,
|
|
71
|
-
update: false,
|
|
72
|
-
template: opts.template,
|
|
73
|
-
projectName: opts.name,
|
|
74
|
-
packageManager: opts.packageManager,
|
|
75
|
-
directory: path.resolve(opts.directory),
|
|
76
|
-
createGithubRepository: !!opts.createGithubRepository,
|
|
77
|
-
overwrite: !!opts.overwrite,
|
|
78
|
-
silent: !!opts.silent
|
|
79
|
-
};
|
|
80
|
-
debug("Processed \"create\" options: %O", commandResult);
|
|
81
|
-
});
|
|
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) => {
|
|
83
|
-
debug("Executing \"update\" command with options: %O", opts);
|
|
84
|
-
if (opts.template === "web-app" && opts.skipBuild) {
|
|
85
|
-
p.log.error("The --skip-build option is not allowed for the \"web-app\" template.");
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
commandResult = {
|
|
89
|
-
...opts,
|
|
90
|
-
update: true,
|
|
91
|
-
template: opts.template,
|
|
92
|
-
projectName: opts.name,
|
|
93
|
-
packageManager: opts.packageManager,
|
|
94
|
-
directory: path.resolve(opts.directory),
|
|
95
|
-
createGithubRepository: !!opts.createGithubRepository,
|
|
96
|
-
overwrite: !!opts.overwrite,
|
|
97
|
-
silent: !!opts.silent
|
|
98
|
-
};
|
|
99
|
-
debug("Processed \"update\" options: %O", commandResult);
|
|
100
|
-
});
|
|
101
|
-
program.command("interactive").description("Start interactive project configuration").action(async () => {
|
|
102
|
-
debug("Starting interactive configuration");
|
|
103
|
-
const projectName = await p.text({
|
|
104
|
-
message: "Project name:",
|
|
105
|
-
placeholder: "my-app",
|
|
106
|
-
defaultValue: "my-app",
|
|
107
|
-
validate: (value) => value && value.length > 0 ? void 0 : "Project name is required"
|
|
108
|
-
});
|
|
109
|
-
if (p.isCancel(projectName)) {
|
|
110
|
-
p.cancel("Operation cancelled.");
|
|
111
|
-
process.exit(0);
|
|
112
|
-
}
|
|
113
|
-
const directory = await p.text({
|
|
114
|
-
message: "Target directory:",
|
|
115
|
-
initialValue: "."
|
|
116
|
-
});
|
|
117
|
-
if (p.isCancel(directory)) {
|
|
118
|
-
p.cancel("Operation cancelled.");
|
|
119
|
-
process.exit(0);
|
|
120
|
-
}
|
|
121
|
-
const projectDir = path.resolve(directory, projectName);
|
|
122
|
-
const exists = await pathExists(projectDir);
|
|
123
|
-
const pkgPath = path.join(projectDir, "package.json");
|
|
124
|
-
const pkgExists = await pathExists(pkgPath);
|
|
125
|
-
let existingConfig = {};
|
|
126
|
-
if (pkgExists) try {
|
|
127
|
-
existingConfig = JSON.parse(await fs.readFile(pkgPath, "utf8"))["create-template-project"] || {};
|
|
128
|
-
debug("Found existing project config: %O", existingConfig);
|
|
129
|
-
} catch (e) {
|
|
130
|
-
debug("Failed to read existing package.json: %O", e);
|
|
131
|
-
}
|
|
132
|
-
let update = false;
|
|
133
|
-
let overwrite = false;
|
|
134
|
-
if (exists) {
|
|
135
|
-
const action = await p.select({
|
|
136
|
-
message: `Directory "${projectDir}" already exists. What would you like to do?`,
|
|
137
|
-
options: [
|
|
138
|
-
{
|
|
139
|
-
label: "Run an update",
|
|
140
|
-
value: "update"
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
label: "Overwrite existing directory by removing it first",
|
|
144
|
-
value: "overwrite"
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
label: "Cancel",
|
|
148
|
-
value: "cancel"
|
|
149
|
-
}
|
|
150
|
-
]
|
|
151
|
-
});
|
|
152
|
-
if (p.isCancel(action) || action === "cancel") {
|
|
153
|
-
p.cancel("Operation cancelled.");
|
|
154
|
-
process.exit(0);
|
|
155
|
-
}
|
|
156
|
-
if (action === "update") update = true;
|
|
157
|
-
else if (action === "overwrite") overwrite = true;
|
|
158
|
-
}
|
|
159
|
-
let template = existingConfig.template;
|
|
160
|
-
if (!update || !template) {
|
|
161
|
-
template = await p.select({
|
|
162
|
-
message: "Select project template:",
|
|
163
|
-
initialValue: template || "cli",
|
|
164
|
-
options: [
|
|
165
|
-
{
|
|
166
|
-
label: "CLI Application (Node.js)",
|
|
167
|
-
value: "cli"
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
label: "Web-Vanilla (Standalone)",
|
|
171
|
-
value: "web-vanilla"
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
label: "Web-App (React + MUI)",
|
|
175
|
-
value: "web-app"
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
label: "Web-Fullstack (Express + React Monorepo)",
|
|
179
|
-
value: "web-fullstack"
|
|
180
|
-
}
|
|
181
|
-
]
|
|
182
|
-
});
|
|
183
|
-
if (p.isCancel(template)) {
|
|
184
|
-
p.cancel("Operation cancelled.");
|
|
185
|
-
process.exit(0);
|
|
186
|
-
}
|
|
187
|
-
} else p.log.info(`Using existing template type: ${template}`);
|
|
188
|
-
let packageManager = "npm";
|
|
189
|
-
if (!update) {
|
|
190
|
-
packageManager = await p.select({
|
|
191
|
-
message: "Select package manager:",
|
|
192
|
-
initialValue: "npm",
|
|
193
|
-
options: [
|
|
194
|
-
{
|
|
195
|
-
label: "npm",
|
|
196
|
-
value: "npm"
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
label: "pnpm",
|
|
200
|
-
value: "pnpm"
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
label: "yarn",
|
|
204
|
-
value: "yarn"
|
|
205
|
-
}
|
|
206
|
-
]
|
|
207
|
-
});
|
|
208
|
-
if (p.isCancel(packageManager)) {
|
|
209
|
-
p.cancel("Operation cancelled.");
|
|
210
|
-
process.exit(0);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
let skipBuild = false;
|
|
214
|
-
if (template !== "web-app") {
|
|
215
|
-
const res = await p.confirm({
|
|
216
|
-
message: "Should we use build tooling? (Enables bundling using tsdown, and uses raw dist/ instead of src/)",
|
|
217
|
-
initialValue: true
|
|
218
|
-
});
|
|
219
|
-
if (p.isCancel(res)) {
|
|
220
|
-
p.cancel("Operation cancelled.");
|
|
221
|
-
process.exit(0);
|
|
222
|
-
}
|
|
223
|
-
skipBuild = !res;
|
|
224
|
-
}
|
|
225
|
-
const installDependenciesRes = await p.confirm({
|
|
226
|
-
message: "Should we install dependencies?",
|
|
227
|
-
initialValue: true
|
|
228
|
-
});
|
|
229
|
-
if (p.isCancel(installDependenciesRes)) {
|
|
230
|
-
p.cancel("Operation cancelled.");
|
|
231
|
-
process.exit(0);
|
|
232
|
-
}
|
|
233
|
-
const installDependencies = installDependenciesRes;
|
|
234
|
-
let build = false;
|
|
235
|
-
if (installDependencies) {
|
|
236
|
-
const res = await p.confirm({
|
|
237
|
-
message: "Should we run the CI script (lint, build, test)?",
|
|
238
|
-
initialValue: true
|
|
239
|
-
});
|
|
240
|
-
if (p.isCancel(res)) {
|
|
241
|
-
p.cancel("Operation cancelled.");
|
|
242
|
-
process.exit(0);
|
|
243
|
-
}
|
|
244
|
-
build = res;
|
|
245
|
-
}
|
|
246
|
-
const createGithubRepositoryRes = await p.confirm({
|
|
247
|
-
message: "Should we create a GitHub repository?",
|
|
248
|
-
initialValue: false
|
|
249
|
-
});
|
|
250
|
-
if (p.isCancel(createGithubRepositoryRes)) {
|
|
251
|
-
p.cancel("Operation cancelled.");
|
|
252
|
-
process.exit(0);
|
|
253
|
-
}
|
|
254
|
-
commandResult = {
|
|
255
|
-
template,
|
|
256
|
-
projectName,
|
|
257
|
-
packageManager,
|
|
258
|
-
createGithubRepository: createGithubRepositoryRes,
|
|
259
|
-
directory: path.resolve(directory),
|
|
260
|
-
update,
|
|
261
|
-
overwrite,
|
|
262
|
-
skipBuild,
|
|
263
|
-
installDependencies,
|
|
264
|
-
build,
|
|
265
|
-
dev: false,
|
|
266
|
-
open: false,
|
|
267
|
-
silent: false
|
|
268
|
-
};
|
|
269
|
-
});
|
|
270
|
-
if (process.argv.length <= 2) {
|
|
271
|
-
program.outputHelp();
|
|
272
|
-
process.exit(0);
|
|
273
|
-
}
|
|
274
|
-
try {
|
|
275
|
-
await program.parseAsync(process.argv);
|
|
276
|
-
} catch (e) {
|
|
277
|
-
if (e.code === "commander.helpDisplayed" || e.code === "commander.version" || e.code === "PROCESS_EXIT_0") process.exit(0);
|
|
278
|
-
if (e.code === "PROCESS_EXIT_1") process.exit(1);
|
|
279
|
-
p.cancel(e.message);
|
|
280
|
-
process.exit(1);
|
|
281
|
-
}
|
|
282
|
-
if (!commandResult) {
|
|
283
|
-
debug("No command result found");
|
|
284
|
-
p.cancel("Unknown command or missing options.");
|
|
285
|
-
process.exit(1);
|
|
286
|
-
}
|
|
287
|
-
debug("Validating command result with Zod");
|
|
288
|
-
const validationResult = ProjectOptionsSchema.safeParse(commandResult);
|
|
289
|
-
if (!validationResult.success) {
|
|
290
|
-
const errors = validationResult.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
291
|
-
p.cancel(`Invalid options: ${errors}`);
|
|
292
|
-
process.exit(1);
|
|
293
|
-
}
|
|
294
|
-
commandResult = validationResult.data;
|
|
295
|
-
const projectDir = path.resolve(commandResult.directory, commandResult.projectName);
|
|
296
|
-
if (await pathExists(projectDir) && !commandResult.update && !commandResult.overwrite) {
|
|
297
|
-
p.cancel(`Directory "${projectDir}" already exists. Use --overwrite to overwrite or "update" command.`);
|
|
298
|
-
process.exit(1);
|
|
299
|
-
}
|
|
300
|
-
if (commandResult.open) {
|
|
301
|
-
commandResult.dev = true;
|
|
302
|
-
commandResult.installDependencies = true;
|
|
303
|
-
}
|
|
304
|
-
if (commandResult.dev || commandResult.build) commandResult.installDependencies = true;
|
|
305
|
-
return commandResult;
|
|
306
|
-
};
|
|
307
|
-
//#endregion
|
|
308
|
-
export { parseArgs };
|
package/dist/generators/info.mjs
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
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 };
|