create-template-project 0.1.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.
Files changed (84) hide show
  1. package/README.md +11 -11
  2. package/dist/config/dependencies.json +60 -44
  3. package/dist/index.js +1221 -0
  4. package/dist/templates/base/files/.github/workflows/node.js.yml +5 -3
  5. package/dist/templates/base/files/.husky/commit-msg +1 -0
  6. package/dist/templates/base/files/.husky/pre-commit +1 -0
  7. package/dist/templates/base/files/.prettierignore +53 -0
  8. package/dist/templates/base/files/.prettierrc.json +4 -2
  9. package/dist/templates/base/files/AGENTS.md +5 -2
  10. package/dist/templates/base/files/README.md +36 -13
  11. package/dist/templates/base/files/_oxlint.config.ts +17 -33
  12. package/dist/templates/base/files/package.json +1 -1
  13. package/dist/templates/base/files/tsconfig.json +32 -32
  14. package/dist/templates/base/files/vitest.config.ts +11 -2
  15. package/dist/templates/cli/files/package.json +4 -3
  16. package/dist/templates/cli/files/src/index.test.ts +10 -2
  17. package/dist/templates/cli/files/src/index.ts +4 -1
  18. package/dist/templates/cli/files/src/lib.ts +10 -0
  19. package/dist/templates/cli/files/vite.config.ts +22 -0
  20. package/dist/templates/web-app/files/index.html +11 -0
  21. package/dist/templates/web-app/files/playwright.config.ts +26 -0
  22. package/dist/templates/web-app/files/src/App.test.tsx +9 -0
  23. package/dist/templates/web-app/files/src/App.tsx +14 -0
  24. package/dist/templates/web-app/files/src/index.tsx +8 -0
  25. package/dist/templates/web-app/files/tests/e2e/basic.e2e-test.ts +13 -0
  26. package/dist/templates/web-app/files/vite.config.ts +34 -0
  27. package/dist/templates/web-fullstack/files/client/index.html +10 -0
  28. package/dist/templates/{fullstack → web-fullstack}/files/client/package.json +2 -2
  29. package/dist/templates/web-fullstack/files/client/src/App.test.tsx +11 -0
  30. package/dist/templates/{fullstack → web-fullstack}/files/client/src/contexts/AuthContext.tsx +1 -5
  31. package/dist/templates/{fullstack → web-fullstack}/files/client/src/pages/Login.tsx +4 -33
  32. package/dist/templates/web-fullstack/files/client/vite.config.ts +30 -0
  33. package/dist/templates/{fullstack → web-fullstack}/files/package.json +1 -2
  34. package/dist/templates/web-fullstack/files/playwright.config.ts +33 -0
  35. package/dist/templates/{fullstack → web-fullstack}/files/server/package.json +2 -2
  36. package/dist/templates/web-fullstack/files/server/src/index.test.ts +28 -0
  37. package/dist/templates/{fullstack → web-fullstack}/files/server/src/trpc.ts +1 -1
  38. package/dist/templates/web-fullstack/files/server/vite.config.ts +24 -0
  39. package/dist/templates/web-fullstack/files/tests/e2e/basic.e2e-test.ts +14 -0
  40. package/dist/templates/web-vanilla/files/index.html +11 -0
  41. package/dist/templates/web-vanilla/files/package.json +17 -0
  42. package/dist/templates/web-vanilla/files/playwright.config.ts +26 -0
  43. package/dist/templates/web-vanilla/files/src/index.test.ts +12 -0
  44. package/dist/templates/web-vanilla/files/src/index.ts +3 -0
  45. package/dist/templates/web-vanilla/files/src/lib.ts +9 -0
  46. package/dist/templates/web-vanilla/files/tests/e2e/basic.e2e-test.ts +11 -0
  47. package/dist/templates/web-vanilla/files/vite.config.ts +28 -0
  48. package/package.json +25 -27
  49. package/dist/cli.mjs +0 -272
  50. package/dist/generators/project.mjs +0 -354
  51. package/dist/index.d.mts +0 -4
  52. package/dist/index.mjs +0 -32
  53. package/dist/templates/base/index.mjs +0 -16
  54. package/dist/templates/cli/files/tsdown.config.ts +0 -3
  55. package/dist/templates/cli/index.mjs +0 -16
  56. package/dist/templates/fullstack/files/client/index.html +0 -8
  57. package/dist/templates/fullstack/files/client/src/App.test.tsx +0 -8
  58. package/dist/templates/fullstack/files/client/tsdown.config.ts +0 -3
  59. package/dist/templates/fullstack/files/server/src/index.test.ts +0 -7
  60. package/dist/templates/fullstack/files/server/tsdown.config.ts +0 -3
  61. package/dist/templates/fullstack/index.mjs +0 -42
  62. package/dist/templates/webapp/files/backend/src/index.ts +0 -17
  63. package/dist/templates/webapp/files/frontend/index.html +0 -9
  64. package/dist/templates/webapp/files/frontend/src/index.ts +0 -4
  65. package/dist/templates/webapp/files/package.json +0 -13
  66. package/dist/templates/webapp/files/src/index.test.ts +0 -5
  67. package/dist/templates/webapp/files/tsdown.config.ts +0 -10
  68. package/dist/templates/webapp/index.mjs +0 -16
  69. package/dist/templates/webpage/files/index.html +0 -8
  70. package/dist/templates/webpage/files/package.json +0 -8
  71. package/dist/templates/webpage/files/src/index.test.ts +0 -5
  72. package/dist/templates/webpage/files/src/index.ts +0 -1
  73. package/dist/templates/webpage/index.mjs +0 -16
  74. package/dist/types.mjs +0 -30
  75. package/dist/utils/file.mjs +0 -101
  76. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/App.tsx +0 -0
  77. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/components/ProtectedRoute.tsx +0 -0
  78. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/main.tsx +0 -0
  79. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/pages/Dashboard.tsx +0 -0
  80. /package/dist/templates/{fullstack → web-fullstack}/files/client/src/trpc.ts +0 -0
  81. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/context.ts +0 -0
  82. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/index.ts +0 -0
  83. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/routers/_app.ts +0 -0
  84. /package/dist/templates/{fullstack → web-fullstack}/files/server/src/routers/auth.ts +0 -0
@@ -1,16 +0,0 @@
1
- import path from "node:path";
2
- import { fileURLToPath } from "node:url";
3
- //#region src/templates/cli/index.ts
4
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
- const getCliTemplate = (_opts) => {
6
- return {
7
- name: "cli",
8
- dependencies: {},
9
- devDependencies: {},
10
- scripts: {},
11
- files: [],
12
- templateDir: path.resolve(__dirname, "files")
13
- };
14
- };
15
- //#endregion
16
- export { getCliTemplate };
@@ -1,8 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head><title>Server Template - Client</title></head>
4
- <body>
5
- <div id="root"></div>
6
- <script src="./dist/index.js"></script>
7
- </body>
8
- </html>
@@ -1,8 +0,0 @@
1
- import {describe, it, expect} from 'vitest';
2
- import {App} from './App.js';
3
-
4
- describe('App', () => {
5
- it('should be a function', () => {
6
- expect(typeof App).toBe('function');
7
- });
8
- });
@@ -1,3 +0,0 @@
1
- import {defineConfig} from 'tsdown';
2
-
3
- export default defineConfig({entry: ['./src/main.tsx'], format: ['esm'], clean: true});
@@ -1,7 +0,0 @@
1
- import {describe, it, expect} from 'vitest';
2
-
3
- describe('server', () => {
4
- it('should have a truthy test', () => {
5
- expect(true).toBe(true);
6
- });
7
- });
@@ -1,3 +0,0 @@
1
- import {defineConfig} from 'tsdown';
2
-
3
- export default defineConfig({entry: ['./src/index.ts'], format: ['esm'], clean: true});
@@ -1,42 +0,0 @@
1
- import path from "node:path";
2
- import { fileURLToPath } from "node:url";
3
- //#region src/templates/fullstack/index.ts
4
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
- const getFullstackTemplate = (_opts) => {
6
- return {
7
- name: "fullstack",
8
- dependencies: {
9
- react: "react",
10
- "react-dom": "react-dom",
11
- "@mui/material": "@mui/material",
12
- "@mui/icons-material": "@mui/icons-material",
13
- "@emotion/react": "@emotion/react",
14
- "@emotion/styled": "@emotion/styled",
15
- express: "express",
16
- "@trpc/server": "@trpc/server",
17
- "@trpc/client": "@trpc/client",
18
- "@trpc/react-query": "@trpc/react-query",
19
- "@tanstack/react-query": "@tanstack/react-query",
20
- zod: "zod",
21
- "react-router-dom": "react-router-dom",
22
- cors: "cors"
23
- },
24
- devDependencies: {
25
- "@types/react": "@types/react",
26
- "@types/react-dom": "@types/react-dom",
27
- "@types/express": "@types/express",
28
- "@types/cors": "@types/cors",
29
- "@playwright/test": "@playwright/test",
30
- tsdown: "tsdown"
31
- },
32
- scripts: {
33
- build: "npm run build --workspaces",
34
- dev: "npm run dev --workspaces",
35
- "test:e2e": "playwright test"
36
- },
37
- files: [],
38
- templateDir: path.resolve(__dirname, "files")
39
- };
40
- };
41
- //#endregion
42
- export { getFullstackTemplate };
@@ -1,17 +0,0 @@
1
- import express from 'express';
2
- import path from 'node:path';
3
- import {fileURLToPath} from 'node:url';
4
-
5
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
- const app = express();
7
- const port = process.env.PORT || 3000;
8
-
9
- app.use(express.static(path.join(__dirname, '../../frontend/dist')));
10
-
11
- app.get('/api/hello', (req, res) => {
12
- res.json({message: 'Hello from Express!'});
13
- });
14
-
15
- app.listen(port, () => {
16
- console.log(`Server running at http://localhost:${port}`);
17
- });
@@ -1,9 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head><title>Vanilla JS Template</title></head>
4
- <body>
5
- <h1>Vanilla JS Template</h1>
6
- <div id="app"></div>
7
- <script src="./dist/index.js"></script>
8
- </body>
9
- </html>
@@ -1,4 +0,0 @@
1
- console.log('Hello from Vanilla JS Frontend!');
2
- void fetch('/api/hello')
3
- .then((res) => res.json())
4
- .then((data) => console.log(data.message));
@@ -1,13 +0,0 @@
1
- {
2
- "dependencies": {
3
- "express": ""
4
- },
5
- "devDependencies": {
6
- "@types/express": "",
7
- "tsdown": ""
8
- },
9
- "scripts": {
10
- "build": "tsdown",
11
- "start": "node dist/server/index.js"
12
- }
13
- }
@@ -1,5 +0,0 @@
1
- import {expect, test} from 'vitest';
2
-
3
- test('math works', () => {
4
- expect(1 + 1).toBe(2);
5
- });
@@ -1,10 +0,0 @@
1
- import {defineConfig} from 'tsdown';
2
-
3
- export default defineConfig({
4
- entry: {
5
- server: 'backend/src/index.ts',
6
- client: 'frontend/src/index.ts',
7
- },
8
- format: ['esm'],
9
- clean: true,
10
- });
@@ -1,16 +0,0 @@
1
- import path from "node:path";
2
- import { fileURLToPath } from "node:url";
3
- //#region src/templates/webapp/index.ts
4
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
- const getWebappTemplate = (_opts) => {
6
- return {
7
- name: "webapp",
8
- dependencies: {},
9
- devDependencies: {},
10
- scripts: {},
11
- files: [],
12
- templateDir: path.resolve(__dirname, "files")
13
- };
14
- };
15
- //#endregion
16
- export { getWebappTemplate };
@@ -1,8 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head><title>Browser Template</title></head>
4
- <body>
5
- <h1>Browser Template</h1>
6
- <script src="{{scriptSrc}}"></script>
7
- </body>
8
- </html>
@@ -1,8 +0,0 @@
1
- {
2
- "devDependencies": {
3
- "tsdown": ""
4
- },
5
- "scripts": {
6
- "build": "tsdown"
7
- }
8
- }
@@ -1,5 +0,0 @@
1
- import {expect, test} from 'vitest';
2
-
3
- test('math works', () => {
4
- expect(1 + 1).toBe(2);
5
- });
@@ -1 +0,0 @@
1
- console.log('Hello from Browser Template!');
@@ -1,16 +0,0 @@
1
- import path from "node:path";
2
- import { fileURLToPath } from "node:url";
3
- //#region src/templates/webpage/index.ts
4
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
- const getWebpageTemplate = (_opts) => {
6
- return {
7
- name: "webpage",
8
- dependencies: {},
9
- devDependencies: {},
10
- scripts: {},
11
- files: [],
12
- templateDir: path.resolve(__dirname, "files")
13
- };
14
- };
15
- //#endregion
16
- export { getWebpageTemplate };
package/dist/types.mjs DELETED
@@ -1,30 +0,0 @@
1
- import { z } from "zod";
2
- //#region src/types.ts
3
- const TemplateTypeSchema = z.enum([
4
- "cli",
5
- "webpage",
6
- "webapp",
7
- "fullstack"
8
- ]);
9
- const PackageManagerSchema = z.enum([
10
- "npm",
11
- "pnpm",
12
- "yarn"
13
- ]);
14
- const ProjectOptionsSchema = z.object({
15
- template: TemplateTypeSchema,
16
- projectName: z.string().min(1, "Project name is required"),
17
- packageManager: PackageManagerSchema.optional().default("npm"),
18
- createGithubRepository: z.boolean().optional().default(false),
19
- directory: z.string(),
20
- overwrite: z.boolean().optional().default(false),
21
- update: z.boolean().optional().default(false),
22
- skipBuild: z.boolean().optional().default(false),
23
- installDependencies: z.boolean().optional().default(false),
24
- build: z.boolean().optional().default(false),
25
- dev: z.boolean().optional().default(false),
26
- open: z.boolean().optional().default(false),
27
- silent: z.boolean().optional().default(false)
28
- });
29
- //#endregion
30
- export { ProjectOptionsSchema };
@@ -1,101 +0,0 @@
1
- import path from "node:path";
2
- import fs from "node:fs/promises";
3
- import debugLib from "debug";
4
- import { execa } from "execa";
5
- //#region src/utils/file.ts
6
- const debug = debugLib("create-template-project:utils:file");
7
- async function getAllFiles(dirPath, arrayOfFiles = []) {
8
- const files = await fs.readdir(dirPath);
9
- for (const file of files) if ((await fs.stat(path.join(dirPath, file))).isDirectory()) arrayOfFiles = await getAllFiles(path.join(dirPath, file), arrayOfFiles);
10
- else arrayOfFiles.push(path.join(dirPath, file));
11
- return arrayOfFiles;
12
- }
13
- function processContent(filePath, content, opts, addedDeps) {
14
- const { projectName, template } = opts;
15
- let description = "";
16
- switch (template) {
17
- case "cli":
18
- description = "A modern Node.js CLI application with TypeScript and automated tooling.";
19
- break;
20
- case "webpage":
21
- description = "A standalone web page/application for modern browsers.";
22
- break;
23
- case "fullstack":
24
- description = "A full-stack monorepo with an Express server and a React/MUI client.";
25
- break;
26
- case "webapp":
27
- description = "A classic web application with an Express backend.";
28
- break;
29
- }
30
- let processed = content.replaceAll("{{projectName}}", projectName).replaceAll("{{description}}", description);
31
- if (template === "webpage" && filePath === "index.html") processed = processed.replace("{{scriptSrc}}", opts.skipBuild ? "./src/index.js" : "./dist/index.js");
32
- if (filePath === "CONTRIBUTING.md" && addedDeps.length > 0) {
33
- processed += "\n## Dependencies\n\n";
34
- const uniqueDeps = Array.from(new Set(addedDeps.map((d) => JSON.stringify(d)))).map((s) => JSON.parse(s));
35
- for (const dep of uniqueDeps) processed += `- **${dep.name}**: ${dep.description}\n`;
36
- }
37
- if (template === "fullstack" && filePath === "tsconfig.json") {
38
- processed = processed.replace(/"lib":\s*\["ESNext"\]/, "\"lib\": [\"ESNext\", \"DOM\"]");
39
- processed = processed.replace(/"module":\s*"NodeNext"/, "\"module\": \"NodeNext\",\n \"jsx\": \"react-jsx\"");
40
- processed = processed.replace(/"include":\s*\[\s*"src\/\*\*\/\*"\s*\]/, "\"include\": [\"client/src/**/*\", \"server/src/**/*\"]");
41
- }
42
- return processed;
43
- }
44
- function mergePackageJson(target, source) {
45
- if (source.scripts) target.scripts = {
46
- ...target.scripts,
47
- ...source.scripts
48
- };
49
- if (source.dependencies) target.dependencies = {
50
- ...target.dependencies,
51
- ...source.dependencies
52
- };
53
- if (source.devDependencies) target.devDependencies = {
54
- ...target.devDependencies,
55
- ...source.devDependencies
56
- };
57
- if (source.workspaces) target.workspaces = source.workspaces;
58
- }
59
- function isSeedFile(filePath) {
60
- return [
61
- "src/",
62
- "client/src/",
63
- "server/src/",
64
- "backend/src/",
65
- "frontend/src/"
66
- ].some((dir) => filePath.startsWith(dir)) || [
67
- "index.html",
68
- "App.tsx",
69
- "main.tsx"
70
- ].some((file) => filePath === file);
71
- }
72
- async function mergeFile(filePath, existing, template, log) {
73
- debug("Merging file: %s", filePath);
74
- const tempBase = filePath + ".base.tmp";
75
- const tempNew = filePath + ".new.tmp";
76
- try {
77
- await fs.writeFile(tempNew, template);
78
- await fs.writeFile(tempBase, "");
79
- try {
80
- await execa("git", [
81
- "merge-file",
82
- filePath,
83
- tempBase,
84
- tempNew
85
- ], { preferLocal: true });
86
- return (await fs.readFile(filePath, "utf8")).trim() !== template.trim() ? "merged" : "updated";
87
- } catch (e) {
88
- if (e.exitCode === 1) return "conflict";
89
- else {
90
- debug("Git merge-file failed: %O", e);
91
- log.error(`Failed to merge ${filePath}: ${e.message}`);
92
- return "error";
93
- }
94
- }
95
- } finally {
96
- await fs.rm(tempBase, { force: true });
97
- await fs.rm(tempNew, { force: true });
98
- }
99
- }
100
- //#endregion
101
- export { getAllFiles, isSeedFile, mergeFile, mergePackageJson, processContent };