@tsfpp/agents 1.2.1 → 1.2.2
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/CHANGELOG.md +8 -0
- package/init.mjs +59 -30
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,14 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [1.2.2] - 2026-05-16
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Updated `init.mjs` questionnaire flow to avoid overwriting existing `tsconfig` and ESLint config files.
|
|
18
|
+
- Added `N`/skip escape hatch for existing-file prompts.
|
|
19
|
+
- Added `SIGINT` handling by wrapping execution in `main` so Ctrl+C exits cleanly without hanging awaits.
|
|
20
|
+
|
|
13
21
|
## [1.2.1] - 2026-05-16
|
|
14
22
|
|
|
15
23
|
### Fixed
|
package/init.mjs
CHANGED
|
@@ -99,7 +99,9 @@ async function askProfile(label) {
|
|
|
99
99
|
console.log(` ${dim('1')} base ${dim('— TypeScript / Node.js')}`);
|
|
100
100
|
console.log(` ${dim('2')} react ${dim('— React / TSX')}`);
|
|
101
101
|
console.log(` ${dim('3')} api ${dim('— HTTP API / Node.js servers')}`);
|
|
102
|
-
|
|
102
|
+
console.log(` ${dim('n')} skip ${dim('— keep existing / do not generate')}`);
|
|
103
|
+
const choice = await ask(` ${dim('[1/2/3/n, default: 1]')} `);
|
|
104
|
+
if (choice === 'n') return null;
|
|
103
105
|
return choice === '2' ? 'react' : choice === '3' ? 'api' : 'base';
|
|
104
106
|
}
|
|
105
107
|
|
|
@@ -146,7 +148,7 @@ function generateSingleConfig(profile) {
|
|
|
146
148
|
return `${imp}\nexport default [...${spread}]\n`;
|
|
147
149
|
}
|
|
148
150
|
|
|
149
|
-
async function writeEslintConfig() {
|
|
151
|
+
async function writeEslintConfig(results) {
|
|
150
152
|
const packages = await detectWorkspacePackages();
|
|
151
153
|
|
|
152
154
|
let content;
|
|
@@ -158,12 +160,17 @@ async function writeEslintConfig() {
|
|
|
158
160
|
for (const pkg of packages) {
|
|
159
161
|
packageProfiles[pkg] = await askProfile(pkg);
|
|
160
162
|
}
|
|
161
|
-
|
|
163
|
+
const activeProfiles = Object.fromEntries(
|
|
164
|
+
Object.entries(packageProfiles).filter(([, p]) => p !== null)
|
|
165
|
+
);
|
|
166
|
+
if (Object.keys(activeProfiles).length === 0) return;
|
|
167
|
+
content = generateMonorepoConfig(activeProfiles);
|
|
162
168
|
description = 'monorepo';
|
|
163
169
|
} else {
|
|
164
170
|
const profile = await askProfile('this project');
|
|
165
|
-
|
|
166
|
-
|
|
171
|
+
if (profile === null) return;
|
|
172
|
+
content = generateSingleConfig(profile);
|
|
173
|
+
description = `profile: ${profile}`;
|
|
167
174
|
}
|
|
168
175
|
|
|
169
176
|
try {
|
|
@@ -199,11 +206,17 @@ async function confirm(question) {
|
|
|
199
206
|
|
|
200
207
|
// ─── Main ─────────────────────────────────────────────────────────────────────
|
|
201
208
|
|
|
202
|
-
|
|
203
|
-
console.log(
|
|
204
|
-
|
|
209
|
+
process.on('SIGINT', () => {
|
|
210
|
+
console.log('\n\n Aborted.\n');
|
|
211
|
+
process.exit(0);
|
|
212
|
+
});
|
|
205
213
|
|
|
206
|
-
|
|
214
|
+
async function main() {
|
|
215
|
+
console.log();
|
|
216
|
+
console.log(bold(' @tsfpp/agents — init'));
|
|
217
|
+
console.log(dim(' Sets up Copilot agents, instructions, prompts, skills, and ESLint config.\n'));
|
|
218
|
+
|
|
219
|
+
const results = { copied: [], skipped: [], failed: [] };
|
|
207
220
|
|
|
208
221
|
// ── Copy files ────────────────────────────────────────────────────────────────
|
|
209
222
|
|
|
@@ -240,17 +253,21 @@ console.log();
|
|
|
240
253
|
const eslintDest = join(cwd, 'eslint.config.js');
|
|
241
254
|
|
|
242
255
|
if (existsSync(eslintDest)) {
|
|
243
|
-
|
|
244
|
-
` ${yellow('!')} eslint.config.js already exists. Overwrite? ${dim('[y/N]')} `
|
|
245
|
-
);
|
|
246
|
-
if (!overwrite) {
|
|
256
|
+
if (yes) {
|
|
247
257
|
results.skipped.push('eslint.config.js');
|
|
248
|
-
console.log(` ${dim('–')} ${dim('eslint.config.js')} ${dim('(skipped)')}`);
|
|
258
|
+
console.log(` ${dim('–')} ${dim('eslint.config.js')} ${dim('(skipped — project-managed)')}`);
|
|
249
259
|
} else {
|
|
250
|
-
await
|
|
260
|
+
const overwrite = await confirm(
|
|
261
|
+
` ${yellow('!')} eslint.config.js already exists. Overwrite? ${dim('[y/N]')} `
|
|
262
|
+
);
|
|
263
|
+
if (overwrite) await writeEslintConfig(results);
|
|
264
|
+
else {
|
|
265
|
+
results.skipped.push('eslint.config.js');
|
|
266
|
+
console.log(` ${dim('–')} ${dim('eslint.config.js')} ${dim('(skipped)')}`);
|
|
267
|
+
}
|
|
251
268
|
}
|
|
252
269
|
} else {
|
|
253
|
-
await writeEslintConfig();
|
|
270
|
+
await writeEslintConfig(results);
|
|
254
271
|
}
|
|
255
272
|
|
|
256
273
|
|
|
@@ -259,9 +276,9 @@ if (existsSync(eslintDest)) {
|
|
|
259
276
|
|
|
260
277
|
console.log();
|
|
261
278
|
|
|
262
|
-
await writeTsConfigs(await detectWorkspacePackages());
|
|
279
|
+
await writeTsConfigs(await detectWorkspacePackages(), results);
|
|
263
280
|
|
|
264
|
-
async function writeTsConfigs(packages) {
|
|
281
|
+
async function writeTsConfigs(packages, results) {
|
|
265
282
|
const PRESETS = {
|
|
266
283
|
app: { extends: '@tsfpp/tsconfig/app', label: 'app — application / tool (noEmit)' },
|
|
267
284
|
lib: { extends: '@tsfpp/tsconfig/lib', label: 'lib — publishable package (declaration, composite)' },
|
|
@@ -271,7 +288,9 @@ async function writeTsConfigs(packages) {
|
|
|
271
288
|
console.log(`\n tsconfig preset for ${bold(label)}:`);
|
|
272
289
|
console.log(` ${dim('1')} app ${dim('— application / tool (noEmit: true)')}`);
|
|
273
290
|
console.log(` ${dim('2')} lib ${dim('— publishable package (declaration, composite)')}`);
|
|
274
|
-
|
|
291
|
+
console.log(` ${dim('n')} skip ${dim('— keep existing / do not generate')}`);
|
|
292
|
+
const choice = await ask(` ${dim('[1/2/n, default: 1]')} `);
|
|
293
|
+
if (choice === 'n') return null;
|
|
275
294
|
return choice === '2' ? 'lib' : 'app';
|
|
276
295
|
}
|
|
277
296
|
|
|
@@ -292,6 +311,11 @@ async function writeTsConfigs(packages) {
|
|
|
292
311
|
|
|
293
312
|
async function writeIfConfirmed(destPath, content, label) {
|
|
294
313
|
if (existsSync(destPath)) {
|
|
314
|
+
if (yes) {
|
|
315
|
+
results.skipped.push(label);
|
|
316
|
+
console.log(` ${dim('–')} ${dim(label)} ${dim('(skipped — project-managed)')}`);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
295
319
|
const overwrite = await confirm(
|
|
296
320
|
` ${yellow('!')} ${label} already exists. Overwrite? ${dim('[y/N]')} `
|
|
297
321
|
);
|
|
@@ -321,6 +345,7 @@ async function writeTsConfigs(packages) {
|
|
|
321
345
|
}
|
|
322
346
|
|
|
323
347
|
for (const [pkg, preset] of Object.entries(packagePresets)) {
|
|
348
|
+
if (preset === null) continue;
|
|
324
349
|
const destPath = join(cwd, pkg, 'tsconfig.json');
|
|
325
350
|
const content = generateTsConfig(preset);
|
|
326
351
|
await writeIfConfirmed(destPath, content, `${pkg}/tsconfig.json`);
|
|
@@ -332,22 +357,26 @@ async function writeTsConfigs(packages) {
|
|
|
332
357
|
await writeIfConfirmed(rootDest, rootContent, 'tsconfig.json (root references)');
|
|
333
358
|
} else {
|
|
334
359
|
// Single package
|
|
335
|
-
const preset
|
|
360
|
+
const preset = await askPreset('this project');
|
|
361
|
+
if (preset === null) return;
|
|
336
362
|
const dest = join(cwd, 'tsconfig.json');
|
|
337
363
|
const content = generateTsConfig(preset);
|
|
338
364
|
await writeIfConfirmed(dest, content, 'tsconfig.json');
|
|
339
365
|
}
|
|
340
366
|
}
|
|
341
367
|
|
|
342
|
-
console.log();
|
|
343
|
-
console.log(dim(' ─────────────────────────────────────────'));
|
|
344
|
-
console.log(` ${green(results.copied.length + ' copied')} ${yellow(results.skipped.length + ' skipped')} ${results.failed.length > 0 ? `\x1b[31m${results.failed.length} failed\x1b[0m` : dim('0 failed')}`);
|
|
345
|
-
console.log();
|
|
368
|
+
console.log();
|
|
369
|
+
console.log(dim(' ─────────────────────────────────────────'));
|
|
370
|
+
console.log(` ${green(results.copied.length + ' copied')} ${yellow(results.skipped.length + ' skipped')} ${results.failed.length > 0 ? `\x1b[31m${results.failed.length} failed\x1b[0m` : dim('0 failed')}`);
|
|
371
|
+
console.log();
|
|
346
372
|
|
|
347
|
-
if (results.failed.length === 0) {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
} else {
|
|
351
|
-
|
|
352
|
-
|
|
373
|
+
if (results.failed.length === 0) {
|
|
374
|
+
console.log(' ' + bold('Done.') + ' Reload VS Code to activate Copilot instructions.');
|
|
375
|
+
console.log(dim(' Commit the generated files — they are workspace configuration.\n'));
|
|
376
|
+
} else {
|
|
377
|
+
console.log(' Some files could not be copied. Check the errors above.\n');
|
|
378
|
+
process.exit(1);
|
|
379
|
+
}
|
|
353
380
|
}
|
|
381
|
+
|
|
382
|
+
main();
|