launchts 1.0.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.
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isValidProjectName = isValidProjectName;
7
+ exports.createProject = createProject;
8
+ const path_1 = __importDefault(require("path"));
9
+ const fs_extra_1 = __importDefault(require("fs-extra"));
10
+ const child_process_1 = require("child_process");
11
+ const configs_1 = require("./configs");
12
+ const messages_1 = require("./messages");
13
+ // Helper to run commands with consistent behavior
14
+ function runCommand(command, args, cwd, verbose, silent = false) {
15
+ const result = (0, child_process_1.spawnSync)(command, args, {
16
+ cwd,
17
+ stdio: verbose ? 'inherit' : 'pipe',
18
+ });
19
+ // Log errors even in non-verbose mode for better debugging
20
+ // Skip logging if silent=true (for check commands like git rev-parse)
21
+ if (result.status !== 0 && !verbose && !silent && result.stderr) {
22
+ const stderrOutput = result.stderr.toString().trim();
23
+ if (stderrOutput) {
24
+ console.error(`Error running ${command}: ${stderrOutput}`);
25
+ }
26
+ }
27
+ return result.status === 0;
28
+ }
29
+ // Validate project name: alphanumeric, hyphens, underscores, 1-214 characters
30
+ function isValidProjectName(name) {
31
+ if (!name || name.length > 214)
32
+ return false;
33
+ // Allow alphanumeric, hyphens, underscores, dots (but not starting with dot or dash)
34
+ if (/^[.-]/.test(name))
35
+ return false;
36
+ return /^[a-zA-Z0-9._-]+$/.test(name);
37
+ }
38
+ function minimalPackageJson(projectName) {
39
+ return {
40
+ name: projectName,
41
+ version: '0.1.0',
42
+ private: true,
43
+ type: 'module',
44
+ scripts: {
45
+ build: 'tsc -p tsconfig.json',
46
+ },
47
+ };
48
+ }
49
+ function baseTsconfig() {
50
+ return {
51
+ compilerOptions: {
52
+ target: 'ESNext',
53
+ module: 'NodeNext',
54
+ moduleResolution: 'NodeNext',
55
+ declaration: true,
56
+ outDir: 'dist',
57
+ rootDir: 'src',
58
+ strict: true,
59
+ esModuleInterop: true,
60
+ skipLibCheck: true,
61
+ forceConsistentCasingInFileNames: true,
62
+ resolveJsonModule: true,
63
+ isolatedModules: true,
64
+ },
65
+ };
66
+ }
67
+ // Helper functions for README generation
68
+ function generateReadmeHeader(projectName) {
69
+ return `# ${projectName}
70
+
71
+ TypeScript project generated with [launchts](https://github.com/Jszigeti/launchts).
72
+
73
+ ## Getting Started
74
+ `;
75
+ }
76
+ function generateReadmeScripts(toolOptions) {
77
+ let scripts = `### Development
78
+
79
+ \`\`\`bash
80
+ npm run build # Compile TypeScript to JavaScript
81
+ `;
82
+ if (toolOptions?.nodemon) {
83
+ scripts += `npm run dev # Start development server with auto-reload\n`;
84
+ }
85
+ if (toolOptions?.eslint) {
86
+ scripts += `npm run lint # Run ESLint\n`;
87
+ }
88
+ if (toolOptions?.prettier) {
89
+ scripts += `npm run format # Format code with Prettier\n`;
90
+ }
91
+ scripts += `\`\`\`
92
+ `;
93
+ return scripts;
94
+ }
95
+ function generateReadmeStructure(projectName, toolOptions) {
96
+ let structure = `### Project Structure
97
+
98
+ \`\`\`
99
+ ${projectName}/
100
+ ├── src/
101
+ │ └── index.ts # Entry point
102
+ ├── dist/ # Compiled output (generated)
103
+ ├── tsconfig.json # TypeScript configuration
104
+ ├── package.json # Project dependencies and scripts
105
+ `;
106
+ if (toolOptions?.eslint) {
107
+ structure += `├── eslint.config.js # ESLint configuration (flat config)\n`;
108
+ }
109
+ if (toolOptions?.prettier) {
110
+ structure += `├── .prettierrc # Prettier configuration\n`;
111
+ }
112
+ if (toolOptions?.husky) {
113
+ structure += `└── .husky/ # Git hooks\n`;
114
+ }
115
+ else {
116
+ structure += `└── ...\n`;
117
+ }
118
+ structure += `\`\`\`
119
+ `;
120
+ return structure;
121
+ }
122
+ function generateReadmeTechStack(toolOptions) {
123
+ let techStack = `## Technology Stack
124
+
125
+ - **TypeScript** - Type-safe JavaScript with ESNext target
126
+ - **Node.js** - Runtime environment with ESM modules
127
+ `;
128
+ if (toolOptions?.eslint) {
129
+ techStack += `- **ESLint** - Code quality and consistency with TypeScript support\n`;
130
+ }
131
+ if (toolOptions?.prettier) {
132
+ techStack += `- **Prettier** - Code formatting\n`;
133
+ }
134
+ if (toolOptions?.nodemon) {
135
+ techStack += `- **Nodemon** - Auto-reload during development\n`;
136
+ }
137
+ if (toolOptions?.husky) {
138
+ techStack += `- **Husky + lint-staged** - Pre-commit hooks for code quality\n`;
139
+ }
140
+ return techStack;
141
+ }
142
+ function generateReadmeScriptsDetails(toolOptions) {
143
+ let scriptsDetails = `
144
+ ## Scripts
145
+
146
+ - \`npm run build\` - Compiles TypeScript files to JavaScript in the \`dist/\` directory
147
+ `;
148
+ if (toolOptions?.nodemon) {
149
+ scriptsDetails += `- \`npm run dev\` - Starts the development server with auto-reload on file changes\n`;
150
+ }
151
+ if (toolOptions?.eslint) {
152
+ scriptsDetails += `- \`npm run lint\` - Checks code quality with ESLint\n`;
153
+ }
154
+ if (toolOptions?.prettier) {
155
+ scriptsDetails += `- \`npm run format\` - Formats all files with Prettier\n`;
156
+ }
157
+ return scriptsDetails;
158
+ }
159
+ function generateReadmeGitHooks(toolOptions) {
160
+ if (!toolOptions?.husky)
161
+ return '';
162
+ return `
163
+ ## Git Hooks
164
+
165
+ This project uses Husky to run quality checks before commits:
166
+
167
+ - **Pre-commit**: Automatically runs ESLint and Prettier on staged files
168
+ `;
169
+ }
170
+ function generateReadme(projectName, toolOptions) {
171
+ let readme = generateReadmeHeader(projectName);
172
+ readme += generateReadmeScripts(toolOptions);
173
+ readme += generateReadmeStructure(projectName, toolOptions);
174
+ readme += generateReadmeTechStack(toolOptions);
175
+ readme += generateReadmeScriptsDetails(toolOptions);
176
+ readme += generateReadmeGitHooks(toolOptions);
177
+ readme += `
178
+ ## License
179
+
180
+ MIT
181
+ `;
182
+ return readme;
183
+ }
184
+ // Helper to get dependency version from root package.json or fallback
185
+ function getDependencyVersion(rootPkg, depName, fallback) {
186
+ return (rootPkg.devDependencies?.[depName] ??
187
+ rootPkg.dependencies?.[depName] ??
188
+ fallback);
189
+ }
190
+ // Helper to add a tool's dependencies and scripts to package.json
191
+ function addToolToPackage(pkg, rootPkg, config) {
192
+ pkg.devDependencies = pkg.devDependencies || {};
193
+ // Add dependencies - resolve versions from rootPkg
194
+ for (const depName of config.deps) {
195
+ pkg.devDependencies[depName] = getDependencyVersion(rootPkg, depName, 'latest');
196
+ }
197
+ // Add scripts
198
+ pkg.scripts = pkg.scripts || {};
199
+ for (const [scriptName, scriptCmd] of Object.entries(config.scripts)) {
200
+ pkg.scripts[scriptName] = scriptCmd;
201
+ }
202
+ }
203
+ async function createProject(opts) {
204
+ const { name, options: toolOptions = {} } = opts;
205
+ const target = path_1.default.resolve(process.cwd(), name);
206
+ if (await fs_extra_1.default.pathExists(target)) {
207
+ throw new Error(messages_1.MESSAGES.targetFolderExists(target));
208
+ }
209
+ await fs_extra_1.default.ensureDir(target);
210
+ const projectName = path_1.default.basename(name);
211
+ // Create initial package.json object in memory
212
+ const pkg = minimalPackageJson(projectName);
213
+ // Write minimal project layout in parallel
214
+ await Promise.all([
215
+ fs_extra_1.default.outputFile(path_1.default.join(target, 'src', 'index.ts'), `console.log('Hello TypeScript')\n`),
216
+ fs_extra_1.default.outputFile(path_1.default.join(target, 'tsconfig.json'), JSON.stringify(baseTsconfig(), null, 2)),
217
+ ]);
218
+ // Read versions from this generator's package.json
219
+ const rootPkg = JSON.parse(await fs_extra_1.default.readFile(path_1.default.resolve(__dirname, '..', 'package.json'), 'utf8'));
220
+ pkg.scripts = pkg.scripts || {};
221
+ // TypeScript is always required for a TypeScript project
222
+ pkg.devDependencies = pkg.devDependencies || {};
223
+ pkg.devDependencies['typescript'] = getDependencyVersion(rootPkg, 'typescript', 'latest');
224
+ if (toolOptions.nodemon) {
225
+ addToolToPackage(pkg, rootPkg, configs_1.TOOL_CONFIGS.nodemon);
226
+ }
227
+ // Prepare all config files to write
228
+ const configFilesToWrite = [];
229
+ if (toolOptions.eslint) {
230
+ addToolToPackage(pkg, rootPkg, configs_1.TOOL_CONFIGS.eslint);
231
+ configFilesToWrite.push(fs_extra_1.default.outputFile(path_1.default.join(target, 'eslint.config.js'), configs_1.TOOL_CONFIGS.eslint.config, 'utf8'));
232
+ }
233
+ if (toolOptions.prettier) {
234
+ addToolToPackage(pkg, rootPkg, configs_1.TOOL_CONFIGS.prettier);
235
+ configFilesToWrite.push(fs_extra_1.default.outputFile(path_1.default.join(target, '.prettierrc'), JSON.stringify(configs_1.TOOL_CONFIGS.prettier.config, null, 2), 'utf8'));
236
+ }
237
+ if (toolOptions.husky) {
238
+ addToolToPackage(pkg, rootPkg, configs_1.TOOL_CONFIGS.husky);
239
+ pkg['lint-staged'] = pkg['lint-staged'] || configs_1.TOOL_CONFIGS.husky.lintStaged;
240
+ const huskyDir = path_1.default.join(target, '.husky');
241
+ await fs_extra_1.default.ensureDir(huskyDir);
242
+ configFilesToWrite.push(fs_extra_1.default.outputFile(path_1.default.join(huskyDir, 'pre-commit'), configs_1.TOOL_CONFIGS.husky.preCommitHook, { mode: 0o755 }));
243
+ }
244
+ // Generate README content
245
+ const readmeContent = generateReadme(projectName, toolOptions);
246
+ // Write package.json and README, plus all config files in parallel
247
+ configFilesToWrite.push(fs_extra_1.default.outputFile(path_1.default.join(target, 'package.json'), JSON.stringify(pkg, null, 2), 'utf8'), fs_extra_1.default.outputFile(path_1.default.join(target, 'README.md'), readmeContent, 'utf8'));
248
+ await Promise.all(configFilesToWrite);
249
+ // optionally initialize git and install dependencies
250
+ if (toolOptions.git ?? true) {
251
+ try {
252
+ const gitAvailable = runCommand('git', ['--version'], target, false, true);
253
+ if (gitAvailable) {
254
+ const insideRepo = runCommand('git', ['rev-parse', '--is-inside-work-tree'], target, false, true);
255
+ if (!insideRepo) {
256
+ runCommand('git', ['init'], target, toolOptions.verbose ?? false);
257
+ await fs_extra_1.default.outputFile(path_1.default.join(target, '.gitignore'), 'node_modules\ndist\n.env\n', 'utf8');
258
+ if (!(toolOptions.noCommit ?? false)) {
259
+ try {
260
+ runCommand('git', ['add', '-A'], target, toolOptions.verbose ?? false);
261
+ runCommand('git', ['commit', '-m', 'chore: initial commit'], target, toolOptions.verbose ?? false);
262
+ }
263
+ catch (e) {
264
+ const errMsg = e instanceof Error ? e.message : String(e);
265
+ console.warn(messages_1.MESSAGES.gitCommitFailed(errMsg));
266
+ }
267
+ }
268
+ }
269
+ }
270
+ }
271
+ catch (e) {
272
+ const errMsg = e instanceof Error ? e.message : String(e);
273
+ console.warn(messages_1.MESSAGES.gitInitFailed(errMsg));
274
+ }
275
+ }
276
+ if (toolOptions.install ?? true) {
277
+ const pm = (toolOptions && toolOptions.pm) || 'npm';
278
+ try {
279
+ if (pm === 'pnpm') {
280
+ runCommand('pnpm', ['install'], target, toolOptions.verbose ?? false);
281
+ }
282
+ else if (pm === 'yarn') {
283
+ runCommand('yarn', ['install'], target, toolOptions.verbose ?? false);
284
+ }
285
+ else {
286
+ runCommand('npm', ['install'], target, toolOptions.verbose ?? false);
287
+ }
288
+ if (toolOptions.husky) {
289
+ runCommand('npx', ['husky', 'install'], target, toolOptions.verbose ?? false);
290
+ const preCommitHook = path_1.default.join(target, '.husky', 'pre-commit');
291
+ if (!(await fs_extra_1.default.pathExists(preCommitHook))) {
292
+ runCommand('npx', ['husky', 'add', '.husky/pre-commit', 'npx lint-staged'], target, toolOptions.verbose ?? false);
293
+ }
294
+ }
295
+ }
296
+ catch (e) {
297
+ const errMsg = e instanceof Error ? e.message : String(e);
298
+ console.warn(messages_1.MESSAGES.installFailed(pm, errMsg));
299
+ }
300
+ }
301
+ }
302
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":";;;;;AAiCA,gDAKC;AAgOD,sCA2LC;AAjcD,gDAAwB;AACxB,wDAA0B;AAC1B,iDAA0C;AAE1C,uCAAyC;AACzC,yCAAsC;AAEtC,kDAAkD;AAClD,SAAS,UAAU,CACjB,OAAe,EACf,IAAc,EACd,GAAW,EACX,OAAgB,EAChB,MAAM,GAAG,KAAK;IAEd,MAAM,MAAM,GAAG,IAAA,yBAAS,EAAC,OAAO,EAAE,IAAI,EAAE;QACtC,GAAG;QACH,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;KACpC,CAAC,CAAC;IAEH,2DAA2D;IAC3D,sEAAsE;IACtE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAChE,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QACrD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,iBAAiB,OAAO,KAAK,YAAY,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,8EAA8E;AAC9E,SAAgB,kBAAkB,CAAC,IAAY;IAC7C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC;IAC7C,qFAAqF;IACrF,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,kBAAkB,CAAC,WAAmB;IAC7C,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE;YACP,KAAK,EAAE,sBAAsB;SAC9B;KACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY;IACnB,OAAO;QACL,eAAe,EAAE;YACf,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,UAAU;YAClB,gBAAgB,EAAE,UAAU;YAC5B,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;YACZ,eAAe,EAAE,IAAI;YACrB,YAAY,EAAE,IAAI;YAClB,gCAAgC,EAAE,IAAI;YACtC,iBAAiB,EAAE,IAAI;YACvB,eAAe,EAAE,IAAI;SACtB;KACF,CAAC;AACJ,CAAC;AAED,yCAAyC;AACzC,SAAS,oBAAoB,CAAC,WAAmB;IAC/C,OAAO,KAAK,WAAW;;;;;CAKxB,CAAC;AACF,CAAC;AAED,SAAS,qBAAqB,CAAC,WAAqC;IAClE,IAAI,OAAO,GAAG;;;;CAIf,CAAC;IAEA,IAAI,WAAW,EAAE,OAAO,EAAE,CAAC;QACzB,OAAO,IAAI,gEAAgE,CAAC;IAC9E,CAAC;IAED,IAAI,WAAW,EAAE,MAAM,EAAE,CAAC;QACxB,OAAO,IAAI,iCAAiC,CAAC;IAC/C,CAAC;IAED,IAAI,WAAW,EAAE,QAAQ,EAAE,CAAC;QAC1B,OAAO,IAAI,gDAAgD,CAAC;IAC9D,CAAC;IAED,OAAO,IAAI;CACZ,CAAC;IACA,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,uBAAuB,CAC9B,WAAmB,EACnB,WAAqC;IAErC,IAAI,SAAS,GAAG;;;EAGhB,WAAW;;;;;;CAMZ,CAAC;IAEA,IAAI,WAAW,EAAE,MAAM,EAAE,CAAC;QACxB,SAAS,IAAI,+DAA+D,CAAC;IAC/E,CAAC;IAED,IAAI,WAAW,EAAE,QAAQ,EAAE,CAAC;QAC1B,SAAS,IAAI,mDAAmD,CAAC;IACnE,CAAC;IAED,IAAI,WAAW,EAAE,KAAK,EAAE,CAAC;QACvB,SAAS,IAAI,sCAAsC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,SAAS,IAAI,WAAW,CAAC;IAC3B,CAAC;IAED,SAAS,IAAI;CACd,CAAC;IACA,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,uBAAuB,CAC9B,WAAqC;IAErC,IAAI,SAAS,GAAG;;;;CAIjB,CAAC;IAEA,IAAI,WAAW,EAAE,MAAM,EAAE,CAAC;QACxB,SAAS,IAAI,uEAAuE,CAAC;IACvF,CAAC;IAED,IAAI,WAAW,EAAE,QAAQ,EAAE,CAAC;QAC1B,SAAS,IAAI,oCAAoC,CAAC;IACpD,CAAC;IAED,IAAI,WAAW,EAAE,OAAO,EAAE,CAAC;QACzB,SAAS,IAAI,kDAAkD,CAAC;IAClE,CAAC;IAED,IAAI,WAAW,EAAE,KAAK,EAAE,CAAC;QACvB,SAAS,IAAI,iEAAiE,CAAC;IACjF,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,4BAA4B,CACnC,WAAqC;IAErC,IAAI,cAAc,GAAG;;;;CAItB,CAAC;IAEA,IAAI,WAAW,EAAE,OAAO,EAAE,CAAC;QACzB,cAAc,IAAI,sFAAsF,CAAC;IAC3G,CAAC;IAED,IAAI,WAAW,EAAE,MAAM,EAAE,CAAC;QACxB,cAAc,IAAI,wDAAwD,CAAC;IAC7E,CAAC;IAED,IAAI,WAAW,EAAE,QAAQ,EAAE,CAAC;QAC1B,cAAc,IAAI,0DAA0D,CAAC;IAC/E,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,SAAS,sBAAsB,CAAC,WAAqC;IACnE,IAAI,CAAC,WAAW,EAAE,KAAK;QAAE,OAAO,EAAE,CAAC;IAEnC,OAAO;;;;;;CAMR,CAAC;AACF,CAAC;AAED,SAAS,cAAc,CACrB,WAAmB,EACnB,WAAqC;IAErC,IAAI,MAAM,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,IAAI,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,IAAI,uBAAuB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC5D,MAAM,IAAI,uBAAuB,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,IAAI,4BAA4B,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,IAAI,sBAAsB,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,IAAI;;;;CAIX,CAAC;IAEA,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,sEAAsE;AACtE,SAAS,oBAAoB,CAC3B,OAAoB,EACpB,OAAe,EACf,QAAgB;IAEhB,OAAO,CACL,OAAO,CAAC,eAAe,EAAE,CAAC,OAAO,CAAC;QAClC,OAAO,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC;QAC/B,QAAQ,CACT,CAAC;AACJ,CAAC;AAED,kEAAkE;AAClE,SAAS,gBAAgB,CACvB,GAAqB,EACrB,OAAoB,EACpB,MAGC;IAED,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;IAEhD,mDAAmD;IACnD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAClC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,oBAAoB,CACjD,OAAO,EACP,OAAO,EACP,QAAQ,CACT,CAAC;IACJ,CAAC;IAED,cAAc;IACd,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACrE,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;IACtC,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,aAAa,CAAC,IAAmB;IACrD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;IACjD,MAAM,MAAM,GAAG,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;IAEjD,IAAI,MAAM,kBAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,mBAAQ,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,kBAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE3B,MAAM,WAAW,GAAG,cAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAExC,+CAA+C;IAC/C,MAAM,GAAG,GAAqB,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAE9D,2CAA2C;IAC3C,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,kBAAE,CAAC,UAAU,CACX,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,EACpC,mCAAmC,CACpC;QACD,kBAAE,CAAC,UAAU,CACX,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,EAClC,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CACxC;KACF,CAAC,CAAC;IAEH,mDAAmD;IACnD,MAAM,OAAO,GAAgB,IAAI,CAAC,KAAK,CACrC,MAAM,kBAAE,CAAC,QAAQ,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CACzE,CAAC;IAEF,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;IAEhC,yDAAyD;IACzD,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;IAChD,GAAG,CAAC,eAAe,CAAC,YAAY,CAAC,GAAG,oBAAoB,CACtD,OAAO,EACP,YAAY,EACZ,QAAQ,CACT,CAAC;IAEF,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;QACxB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,sBAAY,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC;IAED,oCAAoC;IACpC,MAAM,kBAAkB,GAAoB,EAAE,CAAC;IAE/C,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;QACvB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,sBAAY,CAAC,MAAM,CAAC,CAAC;QACpD,kBAAkB,CAAC,IAAI,CACrB,kBAAE,CAAC,UAAU,CACX,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACrC,sBAAY,CAAC,MAAM,CAAC,MAAM,EAC1B,MAAM,CACP,CACF,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;QACzB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,sBAAY,CAAC,QAAQ,CAAC,CAAC;QACtD,kBAAkB,CAAC,IAAI,CACrB,kBAAE,CAAC,UAAU,CACX,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,EAChC,IAAI,CAAC,SAAS,CAAC,sBAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EACrD,MAAM,CACP,CACF,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;QACtB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,sBAAY,CAAC,KAAK,CAAC,CAAC;QACnD,GAAG,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,sBAAY,CAAC,KAAK,CAAC,UAAU,CAAC;QAEzE,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC7C,MAAM,kBAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC7B,kBAAkB,CAAC,IAAI,CACrB,kBAAE,CAAC,UAAU,CACX,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EACjC,sBAAY,CAAC,KAAK,CAAC,aAAa,EAChC,EAAE,IAAI,EAAE,KAAK,EAAE,CAChB,CACF,CAAC;IACJ,CAAC;IAED,0BAA0B;IAC1B,MAAM,aAAa,GAAG,cAAc,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAE/D,mEAAmE;IACnE,kBAAkB,CAAC,IAAI,CACrB,kBAAE,CAAC,UAAU,CACX,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EACjC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAC5B,MAAM,CACP,EACD,kBAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,CACrE,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAEtC,qDAAqD;IACrD,IAAI,WAAW,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,UAAU,CAC7B,KAAK,EACL,CAAC,WAAW,CAAC,EACb,MAAM,EACN,KAAK,EACL,IAAI,CACL,CAAC;YACF,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,UAAU,GAAG,UAAU,CAC3B,KAAK,EACL,CAAC,WAAW,EAAE,uBAAuB,CAAC,EACtC,MAAM,EACN,KAAK,EACL,IAAI,CACL,CAAC;gBAEF,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;oBAClE,MAAM,kBAAE,CAAC,UAAU,CACjB,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,4BAA4B,EAC5B,MAAM,CACP,CAAC;oBACF,IAAI,CAAC,CAAC,WAAW,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,CAAC;wBACrC,IAAI,CAAC;4BACH,UAAU,CACR,KAAK,EACL,CAAC,KAAK,EAAE,IAAI,CAAC,EACb,MAAM,EACN,WAAW,CAAC,OAAO,IAAI,KAAK,CAC7B,CAAC;4BACF,UAAU,CACR,KAAK,EACL,CAAC,QAAQ,EAAE,IAAI,EAAE,uBAAuB,CAAC,EACzC,MAAM,EACN,WAAW,CAAC,OAAO,IAAI,KAAK,CAC7B,CAAC;wBACJ,CAAC;wBAAC,OAAO,CAAC,EAAE,CAAC;4BACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;4BAC1D,OAAO,CAAC,IAAI,CAAC,mBAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;wBACjD,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,mBAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,IAAI,WAAW,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;QAChC,MAAM,EAAE,GAAG,CAAC,WAAW,IAAI,WAAW,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC;QACpD,IAAI,CAAC;YACH,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;gBAClB,UAAU,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;YACxE,CAAC;iBAAM,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;gBACzB,UAAU,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;YACvE,CAAC;YAED,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;gBACtB,UAAU,CACR,KAAK,EACL,CAAC,OAAO,EAAE,SAAS,CAAC,EACpB,MAAM,EACN,WAAW,CAAC,OAAO,IAAI,KAAK,CAC7B,CAAC;gBACF,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;gBAChE,IAAI,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;oBAC1C,UAAU,CACR,KAAK,EACL,CAAC,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,CAAC,EACxD,MAAM,EACN,WAAW,CAAC,OAAO,IAAI,KAAK,CAC7B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,mBAAQ,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Centralized user-facing messages for better maintainability and potential i18n
3
+ */
4
+ export declare const MESSAGES: {
5
+ readonly projectCreated: (name: string) => string;
6
+ readonly invalidProjectName: (name: string) => string;
7
+ readonly invalidPackageManager: (pm: string, valid: string[]) => string;
8
+ readonly targetFolderExists: (target: string) => string;
9
+ readonly failedToCreateProject: (msg: string) => string;
10
+ readonly genericError: (msg: string) => string;
11
+ readonly unknownPackageManager: (pm: string) => string;
12
+ readonly unknownFlag: (flag: string) => string;
13
+ readonly gitInitFailed: (reason: string) => string;
14
+ readonly gitCommitFailed: (reason: string) => string;
15
+ readonly installFailed: (pm: string, reason: string) => string;
16
+ };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * Centralized user-facing messages for better maintainability and potential i18n
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MESSAGES = void 0;
7
+ exports.MESSAGES = {
8
+ // Success messages
9
+ projectCreated: (name) => `✔ Project ${name} created`,
10
+ // Error messages
11
+ invalidProjectName: (name) => `✖ Invalid project name: ${name}. Use alphanumeric, hyphens, underscores (1-214 chars).`,
12
+ invalidPackageManager: (pm, valid) => `✖ Invalid package manager: ${pm}. Choose from: ${valid.join(', ')}`,
13
+ targetFolderExists: (target) => `Target folder already exists: ${target}`,
14
+ failedToCreateProject: (msg) => `✖ Failed to create project: ${msg}`,
15
+ genericError: (msg) => `✖ ${msg}`,
16
+ // Warning messages
17
+ unknownPackageManager: (pm) => `⚠️ Unknown package manager: ${pm}. Defaulting to npm.`,
18
+ unknownFlag: (flag) => `⚠️ Unknown flag: ${flag}. Use --help to see available options.`,
19
+ gitInitFailed: (reason) => `⚠️ Warning: Could not initialize git.\n Reason: ${reason}\n Tip: Make sure git is installed ('git --version' should work)`,
20
+ gitCommitFailed: (reason) => `⚠️ Warning: Could not create git commit.\n Reason: ${reason}\n Tip: Run 'git config --global user.email "you@example.com"' and 'git config --global user.name "Your Name"'`,
21
+ installFailed: (pm, reason) => `⚠️ Warning: Could not install dependencies with ${pm}.\n Reason: ${reason}\n Tip: Make sure ${pm} is installed and try running '${pm} install' manually in the project directory`,
22
+ };
23
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEU,QAAA,QAAQ,GAAG;IACtB,mBAAmB;IACnB,cAAc,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,aAAa,IAAI,UAAU;IAE7D,iBAAiB;IACjB,kBAAkB,EAAE,CAAC,IAAY,EAAE,EAAE,CACnC,2BAA2B,IAAI,yDAAyD;IAC1F,qBAAqB,EAAE,CAAC,EAAU,EAAE,KAAe,EAAE,EAAE,CACrD,8BAA8B,EAAE,kBAAkB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;IACtE,kBAAkB,EAAE,CAAC,MAAc,EAAE,EAAE,CACrC,iCAAiC,MAAM,EAAE;IAC3C,qBAAqB,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,+BAA+B,GAAG,EAAE;IAC5E,YAAY,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,KAAK,GAAG,EAAE;IAEzC,mBAAmB;IACnB,qBAAqB,EAAE,CAAC,EAAU,EAAE,EAAE,CACpC,gCAAgC,EAAE,sBAAsB;IAC1D,WAAW,EAAE,CAAC,IAAY,EAAE,EAAE,CAC5B,qBAAqB,IAAI,wCAAwC;IACnE,aAAa,EAAE,CAAC,MAAc,EAAE,EAAE,CAChC,sDAAsD,MAAM,oEAAoE;IAClI,eAAe,EAAE,CAAC,MAAc,EAAE,EAAE,CAClC,yDAAyD,MAAM,kHAAkH;IACnL,aAAa,EAAE,CAAC,EAAU,EAAE,MAAc,EAAE,EAAE,CAC5C,oDAAoD,EAAE,iBAAiB,MAAM,uBAAuB,EAAE,kCAAkC,EAAE,6CAA6C;CACjL,CAAC"}
@@ -0,0 +1,69 @@
1
+ /** Package manager type: npm, yarn or pnpm */
2
+ export type PackageManager = 'npm' | 'yarn' | 'pnpm';
3
+ /** Options for configuring the generated project and CLI behavior */
4
+ export type ToolOptions = {
5
+ /** Enable ESLint for code linting */
6
+ eslint?: boolean;
7
+ /** Enable Prettier for code formatting */
8
+ prettier?: boolean;
9
+ /** Enable Husky for git pre-commit hooks */
10
+ husky?: boolean;
11
+ /** Enable nodemon for development auto-reload */
12
+ nodemon?: boolean;
13
+ /** Package manager to use (defaults to auto-detection) */
14
+ pm?: PackageManager;
15
+ /** Initialize a git repository */
16
+ git?: boolean;
17
+ /** Install dependencies after project creation */
18
+ install?: boolean;
19
+ /** Enable verbose output */
20
+ verbose?: boolean;
21
+ /** Skip initial git commit (when git is enabled) */
22
+ noCommit?: boolean;
23
+ /** Skip all prompts and use YES_DEFAULTS (all tools enabled) */
24
+ yes?: boolean;
25
+ /** Skip all prompts and use DEFAULT_OPTIONS (sensible defaults) */
26
+ useDefaults?: boolean;
27
+ };
28
+ /** Options for creating a new TypeScript project */
29
+ export type CreateOptions = {
30
+ /** Name of the project/directory to create */
31
+ name: string;
32
+ /** Tool and CLI configuration options */
33
+ options?: ToolOptions;
34
+ };
35
+ /** Root package.json structure with dependencies */
36
+ export type RootPackage = {
37
+ /** Production dependencies */
38
+ dependencies?: Record<string, string>;
39
+ /** Development dependencies */
40
+ devDependencies?: Record<string, string>;
41
+ /** Allow additional package.json fields */
42
+ [key: string]: unknown;
43
+ };
44
+ /** Generated package.json structure for the new project */
45
+ export type GeneratedPackage = {
46
+ /** Project name */
47
+ name?: string;
48
+ /** Project version */
49
+ version?: string;
50
+ /** Whether the package is private */
51
+ private?: boolean;
52
+ /** NPM scripts */
53
+ scripts?: Record<string, string>;
54
+ /** Development dependencies */
55
+ devDependencies?: Record<string, string>;
56
+ /** Allow additional package.json fields */
57
+ [key: string]: unknown;
58
+ };
59
+ /** Type for enquirer prompt questions */
60
+ export type PromptQuestion = {
61
+ /** Type of prompt (input, confirm, etc.) */
62
+ type: string;
63
+ /** Identifier for the prompt response */
64
+ name: string;
65
+ /** Question text displayed to the user */
66
+ message: string;
67
+ /** Default value for the prompt */
68
+ initial?: string | boolean;
69
+ };
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import js from '@eslint/js';
2
+ import tseslint from 'typescript-eslint';
3
+ import globals from 'globals';
4
+
5
+ export default tseslint.config(
6
+ js.configs.recommended,
7
+ ...tseslint.configs.recommended,
8
+ {
9
+ ignores: ['dist/**', 'node_modules/**'],
10
+ },
11
+ {
12
+ languageOptions: {
13
+ ecmaVersion: 'latest',
14
+ sourceType: 'module',
15
+ globals: {
16
+ ...globals.node,
17
+ ...globals.jest,
18
+ },
19
+ },
20
+ rules: {
21
+ 'no-unused-vars': 'off',
22
+ '@typescript-eslint/no-unused-vars': [
23
+ 'warn',
24
+ {
25
+ argsIgnorePattern: '^_',
26
+ varsIgnorePattern: '^_',
27
+ caughtErrorsIgnorePattern: '^_',
28
+ },
29
+ ],
30
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
31
+ '@typescript-eslint/no-var-requires': 'off',
32
+ '@typescript-eslint/no-explicit-any': 'off',
33
+ '@typescript-eslint/no-require-imports': 'off',
34
+ },
35
+ },
36
+ );
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "launchts",
3
+ "version": "1.0.0",
4
+ "description": "Fast, interactive CLI to scaffold TypeScript projects",
5
+ "bin": {
6
+ "launchts": "dist/cli.js"
7
+ },
8
+ "scripts": {
9
+ "build": "tsc -p tsconfig.json",
10
+ "dev": "ts-node src/cli.ts",
11
+ "test": "vitest",
12
+ "lint": "eslint .",
13
+ "prepare": "husky install",
14
+ "format": "prettier --write ."
15
+ },
16
+ "lint-staged": {
17
+ "*.ts": [
18
+ "eslint --fix",
19
+ "prettier --write"
20
+ ],
21
+ "*.json": [
22
+ "prettier --write"
23
+ ]
24
+ },
25
+ "keywords": [
26
+ "typescript",
27
+ "scaffold",
28
+ "cli"
29
+ ],
30
+ "author": "Jonas Szigeti <jonas.szigeti@icloud.com>",
31
+ "license": "MIT",
32
+ "dependencies": {
33
+ "cac": "^6.7.2",
34
+ "enquirer": "^2.3.6",
35
+ "fs-extra": "^11.1.1"
36
+ },
37
+ "devDependencies": {
38
+ "@eslint/js": "^9.39.1",
39
+ "@types/fs-extra": "^11.0.4",
40
+ "@types/node": "^24.10.1",
41
+ "eslint": "^9.39.1",
42
+ "eslint-config-prettier": "^9.0.0",
43
+ "globals": "^16.5.0",
44
+ "husky": "^8.0.0",
45
+ "lint-staged": "^16.2.7",
46
+ "nodemon": "^3.1.11",
47
+ "prettier": "^3.7.3",
48
+ "ts-node": "^10.9.1",
49
+ "typescript": "^5.7.0",
50
+ "typescript-eslint": "^8.48.0",
51
+ "vitest": "^4.0.14"
52
+ }
53
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "declaration": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "sourceMap": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist", "tests"]
19
+ }