create-template-project 0.2.0 → 0.4.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.
Files changed (43) hide show
  1. package/README.md +3 -3
  2. package/dist/config/dependencies.json +10 -14
  3. package/dist/index.js +1259 -0
  4. package/dist/templates/base/files/.husky/commit-msg +1 -0
  5. package/dist/templates/base/files/.husky/pre-commit +1 -0
  6. package/dist/templates/base/files/.prettierignore +3 -0
  7. package/dist/templates/base/files/package.json +1 -1
  8. package/dist/templates/base/files/vitest.config.ts +10 -1
  9. package/dist/templates/cli/files/package.json +4 -3
  10. package/dist/templates/cli/files/src/index.test.ts +10 -2
  11. package/dist/templates/cli/files/src/index.ts +4 -1
  12. package/dist/templates/cli/files/src/lib.ts +10 -0
  13. package/dist/templates/cli/files/vite.config.ts +22 -0
  14. package/dist/templates/web-app/files/src/App.test.tsx +9 -0
  15. package/dist/templates/web-app/files/src/App.tsx +14 -0
  16. package/dist/templates/web-app/files/src/index.tsx +1 -14
  17. package/dist/templates/web-app/files/vite.config.ts +4 -0
  18. package/dist/templates/web-fullstack/files/client/src/App.test.tsx +5 -2
  19. package/dist/templates/web-fullstack/files/client/vite.config.ts +4 -0
  20. package/dist/templates/web-fullstack/files/package.json +1 -2
  21. package/dist/templates/web-fullstack/files/server/src/index.test.ts +24 -3
  22. package/dist/templates/web-fullstack/files/server/src/trpc.ts +1 -1
  23. package/dist/templates/web-fullstack/files/server/vite.config.ts +6 -3
  24. package/dist/templates/web-vanilla/files/index.html +1 -1
  25. package/dist/templates/web-vanilla/files/src/index.test.ts +9 -2
  26. package/dist/templates/web-vanilla/files/src/index.ts +3 -1
  27. package/dist/templates/web-vanilla/files/src/lib.ts +9 -0
  28. package/dist/templates/web-vanilla/files/vite.config.ts +4 -0
  29. package/package.json +13 -18
  30. package/dist/cli.mjs +0 -308
  31. package/dist/generators/info.mjs +0 -58
  32. package/dist/generators/project.mjs +0 -387
  33. package/dist/index.d.mts +0 -4
  34. package/dist/index.mjs +0 -35
  35. package/dist/templates/base/index.mjs +0 -55
  36. package/dist/templates/cli/files/tsdown.config.ts +0 -3
  37. package/dist/templates/cli/index.mjs +0 -29
  38. package/dist/templates/web-app/files/src/index.test.ts +0 -5
  39. package/dist/templates/web-app/index.mjs +0 -69
  40. package/dist/templates/web-fullstack/index.mjs +0 -78
  41. package/dist/templates/web-vanilla/index.mjs +0 -45
  42. package/dist/types.mjs +0 -30
  43. 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 };
@@ -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 };