obsidian-plugin-config 1.6.13 → 1.6.15
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 +9 -12
- package/bin/obsidian-inject.js +17 -4
- package/package.json +1 -1
- package/scripts/build-npm.ts +16 -3
- package/scripts/inject-core.ts +95 -114
- package/scripts/inject-path.ts +1 -15
- package/scripts/inject-prompt.ts +1 -2
- package/tsconfig.json +1 -1
- package/DONE.md +0 -60
- package/FINAL_SUMMARY.md +0 -163
- package/PROBLEM_FOR_CLAUDE.md +0 -82
- package/docs/APPLIED_MODIFS.md +0 -104
- package/docs/TECHNICAL_NOTES.md +0 -43
- package/docs/implementation_plan.md +0 -127
- package/docs/modifs.md +0 -434
- package/scripts/inject-options.ts +0 -139
package/README.md
CHANGED
|
@@ -20,25 +20,24 @@ npm install -g obsidian-plugin-config@latest --force
|
|
|
20
20
|
## Usage (global CLI)
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
# Inject in current plugin directory
|
|
23
|
+
# Inject in current plugin directory
|
|
24
|
+
# Prompts for confirmation before replacing each existing file
|
|
24
25
|
obsidian-inject
|
|
25
26
|
|
|
26
|
-
# Inject by path
|
|
27
|
+
# Inject by path
|
|
28
|
+
# Prompts for confirmation before replacing each existing file
|
|
27
29
|
obsidian-inject ../my-plugin
|
|
28
30
|
|
|
29
31
|
# Inject without confirmation
|
|
32
|
+
# Auto-confirms all file replacements (no prompts)
|
|
30
33
|
obsidian-inject ../my-plugin --no
|
|
31
34
|
|
|
32
|
-
# Inject with SASS support
|
|
35
|
+
# Inject with SASS support
|
|
36
|
+
# Adds esbuild-sass-plugin dependency and SCSS compilation
|
|
33
37
|
obsidian-inject ../my-plugin --sass
|
|
34
38
|
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# Use preset
|
|
39
|
-
obsidian-inject ../my-plugin --preset=minimal
|
|
40
|
-
|
|
41
|
-
# Verification only (no changes)
|
|
39
|
+
# Verification only (dry-run)
|
|
40
|
+
# Shows what would be injected without making any changes
|
|
42
41
|
obsidian-inject ../my-plugin --dry-run
|
|
43
42
|
|
|
44
43
|
# Help
|
|
@@ -49,8 +48,6 @@ obsidian-inject --help
|
|
|
49
48
|
|
|
50
49
|
- `--no`, `-n` - Skip confirmation prompts (auto-confirm)
|
|
51
50
|
- `--sass` - Add SASS support (esbuild-sass-plugin)
|
|
52
|
-
- `--interactive`, `-i` - Choose what to inject interactively
|
|
53
|
-
- `--preset=<name>` - Use preset (minimal, scripts-only, config-only)
|
|
54
51
|
- `--dry-run` - Verification only (no changes)
|
|
55
52
|
|
|
56
53
|
## What is injected
|
package/bin/obsidian-inject.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Obsidian Plugin Config - CLI Entry Point
|
|
5
5
|
* Global command: obsidian-inject
|
|
6
|
-
* Version: 1.6.
|
|
6
|
+
* Version: 1.6.15
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { execSync } from 'child_process';
|
|
@@ -25,20 +25,28 @@ Obsidian Plugin Config - Global CLI
|
|
|
25
25
|
Injection system for autonomous Obsidian plugins
|
|
26
26
|
|
|
27
27
|
USAGE:
|
|
28
|
-
obsidian-inject # Inject in current directory
|
|
29
|
-
obsidian-inject <path> # Inject by path
|
|
28
|
+
obsidian-inject # Inject in current directory (with confirmation)
|
|
29
|
+
obsidian-inject <path> # Inject by path (with confirmation)
|
|
30
|
+
obsidian-inject <path> --no # Inject without confirmation
|
|
30
31
|
obsidian-inject <path> --sass # Inject with SASS support
|
|
31
32
|
obsidian-inject --help, -h # Show this help
|
|
32
33
|
|
|
34
|
+
OPTIONS:
|
|
35
|
+
--no, -n # Skip confirmation prompts (auto-confirm all)
|
|
36
|
+
--sass # Add SASS support (esbuild-sass-plugin)
|
|
37
|
+
--dry-run # Verification only (no changes)
|
|
38
|
+
|
|
33
39
|
EXAMPLES:
|
|
34
40
|
cd my-plugin && obsidian-inject
|
|
35
41
|
obsidian-inject ../my-other-plugin
|
|
42
|
+
obsidian-inject ../my-plugin --no
|
|
36
43
|
obsidian-inject ../my-plugin --sass
|
|
37
44
|
obsidian-inject "C:\\Users\\dev\\plugins\\my-plugin"
|
|
38
45
|
|
|
39
46
|
WHAT IS INJECTED:
|
|
40
47
|
✅ Local scripts (esbuild.config.ts, acp.ts, utils.ts, etc.)
|
|
41
48
|
✅ Package.json configuration (scripts, dependencies)
|
|
49
|
+
✅ Config files (tsconfig, eslint, prettier, vscode, github)
|
|
42
50
|
✅ Yarn protection enforced
|
|
43
51
|
✅ Automatic dependency installation
|
|
44
52
|
🎨 SASS support (with --sass option): esbuild-sass-plugin + SCSS compilation
|
|
@@ -69,7 +77,9 @@ function main() {
|
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
// Parse arguments
|
|
80
|
+
const noConfirm = args.includes('--no') || args.includes('-n');
|
|
72
81
|
const sassFlag = args.includes('--sass');
|
|
82
|
+
const dryRun = args.includes('--dry-run');
|
|
73
83
|
const pathArg = args.find(arg => !arg.startsWith('-'));
|
|
74
84
|
|
|
75
85
|
// Determine target path (resolve relative to user's current directory)
|
|
@@ -84,6 +94,7 @@ function main() {
|
|
|
84
94
|
console.log(`🎯 Obsidian Plugin Config - Global Injection`);
|
|
85
95
|
console.log(`📁 Target: ${targetPath}`);
|
|
86
96
|
console.log(`🎨 SASS: ${sassFlag ? 'Enabled' : 'Disabled'}`);
|
|
97
|
+
console.log(`❓ Confirmation: ${noConfirm ? 'Disabled (auto-confirm)' : 'Enabled'}`);
|
|
87
98
|
console.log(`📦 From: ${packageRoot}\n`);
|
|
88
99
|
|
|
89
100
|
try {
|
|
@@ -154,7 +165,9 @@ function main() {
|
|
|
154
165
|
|
|
155
166
|
// Execute the injection script with tsx
|
|
156
167
|
const sassOption = sassFlag ? ' --sass' : '';
|
|
157
|
-
const
|
|
168
|
+
const yesOption = noConfirm ? ' --yes' : '';
|
|
169
|
+
const dryRunOption = dryRun ? ' --dry-run' : '';
|
|
170
|
+
const command = `npx tsx "${injectScriptPath}" "${targetPath}"${yesOption}${sassOption}${dryRunOption}`;
|
|
158
171
|
|
|
159
172
|
execSync(command, {
|
|
160
173
|
stdio: 'inherit',
|
package/package.json
CHANGED
package/scripts/build-npm.ts
CHANGED
|
@@ -49,20 +49,28 @@ Obsidian Plugin Config - Global CLI
|
|
|
49
49
|
Injection system for autonomous Obsidian plugins
|
|
50
50
|
|
|
51
51
|
USAGE:
|
|
52
|
-
obsidian-inject # Inject in current directory
|
|
53
|
-
obsidian-inject <path> # Inject by path
|
|
52
|
+
obsidian-inject # Inject in current directory (with confirmation)
|
|
53
|
+
obsidian-inject <path> # Inject by path (with confirmation)
|
|
54
|
+
obsidian-inject <path> --no # Inject without confirmation
|
|
54
55
|
obsidian-inject <path> --sass # Inject with SASS support
|
|
55
56
|
obsidian-inject --help, -h # Show this help
|
|
56
57
|
|
|
58
|
+
OPTIONS:
|
|
59
|
+
--no, -n # Skip confirmation prompts (auto-confirm all)
|
|
60
|
+
--sass # Add SASS support (esbuild-sass-plugin)
|
|
61
|
+
--dry-run # Verification only (no changes)
|
|
62
|
+
|
|
57
63
|
EXAMPLES:
|
|
58
64
|
cd my-plugin && obsidian-inject
|
|
59
65
|
obsidian-inject ../my-other-plugin
|
|
66
|
+
obsidian-inject ../my-plugin --no
|
|
60
67
|
obsidian-inject ../my-plugin --sass
|
|
61
68
|
obsidian-inject "C:\\\\Users\\\\dev\\\\plugins\\\\my-plugin"
|
|
62
69
|
|
|
63
70
|
WHAT IS INJECTED:
|
|
64
71
|
✅ Local scripts (esbuild.config.ts, acp.ts, utils.ts, etc.)
|
|
65
72
|
✅ Package.json configuration (scripts, dependencies)
|
|
73
|
+
✅ Config files (tsconfig, eslint, prettier, vscode, github)
|
|
66
74
|
✅ Yarn protection enforced
|
|
67
75
|
✅ Automatic dependency installation
|
|
68
76
|
🎨 SASS support (with --sass option): esbuild-sass-plugin + SCSS compilation
|
|
@@ -93,7 +101,9 @@ function main() {
|
|
|
93
101
|
}
|
|
94
102
|
|
|
95
103
|
// Parse arguments
|
|
104
|
+
const noConfirm = args.includes('--no') || args.includes('-n');
|
|
96
105
|
const sassFlag = args.includes('--sass');
|
|
106
|
+
const dryRun = args.includes('--dry-run');
|
|
97
107
|
const pathArg = args.find(arg => !arg.startsWith('-'));
|
|
98
108
|
|
|
99
109
|
// Determine target path (resolve relative to user's current directory)
|
|
@@ -108,6 +118,7 @@ function main() {
|
|
|
108
118
|
console.log(\`🎯 Obsidian Plugin Config - Global Injection\`);
|
|
109
119
|
console.log(\`📁 Target: \${targetPath}\`);
|
|
110
120
|
console.log(\`🎨 SASS: \${sassFlag ? 'Enabled' : 'Disabled'}\`);
|
|
121
|
+
console.log(\`❓ Confirmation: \${noConfirm ? 'Disabled (auto-confirm)' : 'Enabled'}\`);
|
|
111
122
|
console.log(\`📦 From: \${packageRoot}\\n\`);
|
|
112
123
|
|
|
113
124
|
try {
|
|
@@ -178,7 +189,9 @@ function main() {
|
|
|
178
189
|
|
|
179
190
|
// Execute the injection script with tsx
|
|
180
191
|
const sassOption = sassFlag ? ' --sass' : '';
|
|
181
|
-
const
|
|
192
|
+
const yesOption = noConfirm ? ' --yes' : '';
|
|
193
|
+
const dryRunOption = dryRun ? ' --dry-run' : '';
|
|
194
|
+
const command = \`npx tsx "\${injectScriptPath}" "\${targetPath}"\${yesOption}\${sassOption}\${dryRunOption}\`;
|
|
182
195
|
|
|
183
196
|
execSync(command, {
|
|
184
197
|
stdio: 'inherit',
|
package/scripts/inject-core.ts
CHANGED
|
@@ -5,7 +5,6 @@ import path from 'path';
|
|
|
5
5
|
import { execSync } from 'child_process';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import { isValidPath, gitExec } from './utils.js';
|
|
8
|
-
import type { InjectionOptions } from './inject-options.js';
|
|
9
8
|
|
|
10
9
|
export interface InjectionPlan {
|
|
11
10
|
targetPath: string;
|
|
@@ -257,7 +256,8 @@ export async function cleanOldLintFiles(targetPath: string): Promise<void> {
|
|
|
257
256
|
if (await isValidPath(filePath)) {
|
|
258
257
|
fs.unlinkSync(filePath);
|
|
259
258
|
console.log(
|
|
260
|
-
`🗑️ Removed old ESLint file: ${fileName} (replaced by
|
|
259
|
+
`🗑️ Removed old ESLint file: ${fileName} (replaced by 1
|
|
260
|
+
fig.ts)`
|
|
261
261
|
);
|
|
262
262
|
}
|
|
263
263
|
}
|
|
@@ -276,14 +276,13 @@ export async function cleanOldLintFiles(targetPath: string): Promise<void> {
|
|
|
276
276
|
interface FileEntry {
|
|
277
277
|
src: string; // path relative to configRoot
|
|
278
278
|
dest: string; // absolute path in target plugin
|
|
279
|
-
optionKey: keyof InjectionOptions | null; // null = always inject
|
|
280
279
|
mergeEnv?: boolean; // special .env merge logic
|
|
281
280
|
}
|
|
282
281
|
|
|
283
282
|
/**
|
|
284
283
|
* Build the full list of files to inject, with source and destination paths
|
|
285
284
|
*/
|
|
286
|
-
function buildFileList(targetPath: string
|
|
285
|
+
function buildFileList(targetPath: string): FileEntry[] {
|
|
287
286
|
const scriptsPath = path.join(targetPath, 'scripts');
|
|
288
287
|
const entries: FileEntry[] = [];
|
|
289
288
|
|
|
@@ -299,27 +298,25 @@ function buildFileList(targetPath: string, options: InjectionOptions): FileEntry
|
|
|
299
298
|
for (const src of scriptFiles) {
|
|
300
299
|
entries.push({
|
|
301
300
|
src,
|
|
302
|
-
dest: path.join(scriptsPath, path.basename(src))
|
|
303
|
-
optionKey: 'scripts'
|
|
301
|
+
dest: path.join(scriptsPath, path.basename(src))
|
|
304
302
|
});
|
|
305
303
|
}
|
|
306
304
|
|
|
307
305
|
// Root config files
|
|
308
|
-
const configFileMap: Array<[string, string,
|
|
309
|
-
[
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
for (const [src, destName,
|
|
306
|
+
const configFileMap: Array<[string, string, boolean?]> = [
|
|
307
|
+
['templates/tsconfig.json', 'tsconfig.json'],
|
|
308
|
+
['templates/gitignore.template', '.gitignore'],
|
|
309
|
+
['templates/eslint.config.mts', 'eslint.config.mts'],
|
|
310
|
+
['templates/.editorconfig', '.editorconfig'],
|
|
311
|
+
['templates/.prettierrc', '.prettierrc'],
|
|
312
|
+
['templates/.prettierignore', '.prettierignore'],
|
|
313
|
+
['templates/npmrc.template', '.npmrc'],
|
|
314
|
+
['templates/env.template', '.env', true]
|
|
315
|
+
];
|
|
316
|
+
for (const [src, destName, mergeEnv] of configFileMap) {
|
|
319
317
|
entries.push({
|
|
320
318
|
src,
|
|
321
319
|
dest: path.join(targetPath, destName),
|
|
322
|
-
optionKey,
|
|
323
320
|
mergeEnv: !!mergeEnv
|
|
324
321
|
});
|
|
325
322
|
}
|
|
@@ -327,13 +324,13 @@ function buildFileList(targetPath: string, options: InjectionOptions): FileEntry
|
|
|
327
324
|
// VSCode config files
|
|
328
325
|
const configVscodeMap: Array<[string, string]> = [
|
|
329
326
|
['templates/.vscode/settings.json', '.vscode/settings.json'],
|
|
330
|
-
['templates/.vscode/tasks.json', '.vscode/tasks.json']
|
|
327
|
+
['templates/.vscode/tasks.json', '.vscode/tasks.json'],
|
|
328
|
+
['templates/.vscode/extensions.json', '.vscode/extensions.json']
|
|
331
329
|
];
|
|
332
330
|
for (const [src, destName] of configVscodeMap) {
|
|
333
331
|
entries.push({
|
|
334
332
|
src,
|
|
335
|
-
dest: path.join(targetPath, destName)
|
|
336
|
-
optionKey: 'vscode'
|
|
333
|
+
dest: path.join(targetPath, destName)
|
|
337
334
|
});
|
|
338
335
|
}
|
|
339
336
|
|
|
@@ -345,8 +342,7 @@ function buildFileList(targetPath: string, options: InjectionOptions): FileEntry
|
|
|
345
342
|
for (const src of workflowFiles) {
|
|
346
343
|
entries.push({
|
|
347
344
|
src,
|
|
348
|
-
dest: path.join(targetPath, src.replace('templates/', ''))
|
|
349
|
-
optionKey: 'github'
|
|
345
|
+
dest: path.join(targetPath, src.replace('templates/', ''))
|
|
350
346
|
});
|
|
351
347
|
}
|
|
352
348
|
|
|
@@ -360,12 +356,12 @@ function buildFileList(targetPath: string, options: InjectionOptions): FileEntry
|
|
|
360
356
|
*/
|
|
361
357
|
export async function diffAndPromptFiles(
|
|
362
358
|
targetPath: string,
|
|
363
|
-
|
|
359
|
+
autoConfirm: boolean
|
|
364
360
|
): Promise<Set<string>> {
|
|
365
361
|
const { askConfirmation, createReadlineInterface } = await import('./utils.js');
|
|
366
|
-
const rl = createReadlineInterface();
|
|
362
|
+
const rl = autoConfirm ? null : createReadlineInterface();
|
|
367
363
|
const configRoot = findPluginConfigRoot();
|
|
368
|
-
const entries = buildFileList(targetPath
|
|
364
|
+
const entries = buildFileList(targetPath);
|
|
369
365
|
const approved = new Set<string>();
|
|
370
366
|
|
|
371
367
|
console.log(`\n🔍 Comparing files with existing content...`);
|
|
@@ -373,8 +369,6 @@ export async function diffAndPromptFiles(
|
|
|
373
369
|
let hasChanges = false;
|
|
374
370
|
|
|
375
371
|
for (const entry of entries) {
|
|
376
|
-
// Skip if disabled by options
|
|
377
|
-
if (entry.optionKey !== null && !options[entry.optionKey]) continue;
|
|
378
372
|
// Skip .env merge (always approved, merge logic handled separately)
|
|
379
373
|
if (entry.mergeEnv) {
|
|
380
374
|
approved.add(entry.dest);
|
|
@@ -396,6 +390,19 @@ export async function diffAndPromptFiles(
|
|
|
396
390
|
continue;
|
|
397
391
|
}
|
|
398
392
|
|
|
393
|
+
// Special case: eslint.config.mts - auto-approve if old .eslintrc exists
|
|
394
|
+
if (entry.dest.endsWith('eslint.config.mts')) {
|
|
395
|
+
const oldEslintFiles = ['.eslintrc', '.eslintrc.js', '.eslintrc.json', '.eslintrc.cjs'];
|
|
396
|
+
const hasOldEslint = oldEslintFiles.some(file =>
|
|
397
|
+
fs.existsSync(path.join(targetPath, file))
|
|
398
|
+
);
|
|
399
|
+
if (hasOldEslint) {
|
|
400
|
+
console.log(` 🔄 ${path.relative(targetPath, entry.dest)} (migrating from old .eslintrc format)`);
|
|
401
|
+
approved.add(entry.dest);
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
399
406
|
const destContent = fs.readFileSync(entry.dest, 'utf8');
|
|
400
407
|
|
|
401
408
|
// Identical → skip silently
|
|
@@ -404,17 +411,23 @@ export async function diffAndPromptFiles(
|
|
|
404
411
|
continue;
|
|
405
412
|
}
|
|
406
413
|
|
|
407
|
-
// Different → ask user
|
|
414
|
+
// Different → ask user (or auto-approve if autoConfirm)
|
|
408
415
|
hasChanges = true;
|
|
409
416
|
const relDest = path.relative(targetPath, entry.dest);
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
);
|
|
414
|
-
if (update) {
|
|
417
|
+
|
|
418
|
+
if (autoConfirm) {
|
|
419
|
+
console.log(` ✅ ${relDest} (will be updated)`);
|
|
415
420
|
approved.add(entry.dest);
|
|
416
421
|
} else {
|
|
417
|
-
|
|
422
|
+
const update = await askConfirmation(
|
|
423
|
+
` Update ${relDest}? (content differs)`,
|
|
424
|
+
rl!
|
|
425
|
+
);
|
|
426
|
+
if (update) {
|
|
427
|
+
approved.add(entry.dest);
|
|
428
|
+
} else {
|
|
429
|
+
console.log(` ⏭️ Kept existing ${relDest}`);
|
|
430
|
+
}
|
|
418
431
|
}
|
|
419
432
|
}
|
|
420
433
|
|
|
@@ -422,7 +435,7 @@ export async function diffAndPromptFiles(
|
|
|
422
435
|
console.log(` ✅ All existing files are up to date`);
|
|
423
436
|
}
|
|
424
437
|
|
|
425
|
-
rl.close();
|
|
438
|
+
if (rl) rl.close();
|
|
426
439
|
return approved;
|
|
427
440
|
}
|
|
428
441
|
|
|
@@ -431,7 +444,6 @@ export async function diffAndPromptFiles(
|
|
|
431
444
|
*/
|
|
432
445
|
export async function injectScripts(
|
|
433
446
|
targetPath: string,
|
|
434
|
-
options: InjectionOptions,
|
|
435
447
|
approvedDests: Set<string>
|
|
436
448
|
): Promise<void> {
|
|
437
449
|
const scriptsPath = path.join(targetPath, 'scripts');
|
|
@@ -465,13 +477,15 @@ export async function injectScripts(
|
|
|
465
477
|
'templates/eslint.config.mts': 'eslint.config.mts',
|
|
466
478
|
'templates/.editorconfig': '.editorconfig',
|
|
467
479
|
'templates/.prettierrc': '.prettierrc',
|
|
480
|
+
'templates/.prettierignore': '.prettierignore',
|
|
468
481
|
'templates/npmrc.template': '.npmrc',
|
|
469
482
|
'templates/env.template': '.env'
|
|
470
483
|
};
|
|
471
484
|
|
|
472
485
|
const configVscodeMap: Record<string, string> = {
|
|
473
486
|
'templates/.vscode/settings.json': '.vscode/settings.json',
|
|
474
|
-
'templates/.vscode/tasks.json': '.vscode/tasks.json'
|
|
487
|
+
'templates/.vscode/tasks.json': '.vscode/tasks.json',
|
|
488
|
+
'templates/.vscode/extensions.json': '.vscode/extensions.json'
|
|
475
489
|
};
|
|
476
490
|
|
|
477
491
|
const workflowFiles = [
|
|
@@ -481,45 +495,26 @@ export async function injectScripts(
|
|
|
481
495
|
|
|
482
496
|
console.log(`\n📥 Copying scripts from local files...`);
|
|
483
497
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
continue;
|
|
492
|
-
}
|
|
493
|
-
const content = copyFromLocal(scriptFile);
|
|
494
|
-
fs.writeFileSync(targetFile, content, 'utf8');
|
|
495
|
-
console.log(` ✅ ${fileName}`);
|
|
496
|
-
} catch (error) {
|
|
497
|
-
console.error(` ❌ Failed to inject ${scriptFile}: ${error}`);
|
|
498
|
+
for (const scriptFile of scriptFiles) {
|
|
499
|
+
try {
|
|
500
|
+
const fileName = path.basename(scriptFile);
|
|
501
|
+
const targetFile = path.join(scriptsPath, fileName);
|
|
502
|
+
if (!approvedDests.has(targetFile)) {
|
|
503
|
+
console.log(` ⏭️ Skipped ${fileName} (kept existing)`);
|
|
504
|
+
continue;
|
|
498
505
|
}
|
|
506
|
+
const content = copyFromLocal(scriptFile);
|
|
507
|
+
fs.writeFileSync(targetFile, content, 'utf8');
|
|
508
|
+
console.log(` ✅ ${fileName}`);
|
|
509
|
+
} catch (error) {
|
|
510
|
+
console.error(` ❌ Failed to inject ${scriptFile}: ${error}`);
|
|
499
511
|
}
|
|
500
|
-
} else {
|
|
501
|
-
console.log(` ⏭️ Skipped (user choice)`);
|
|
502
512
|
}
|
|
503
513
|
|
|
504
514
|
console.log(`\n📥 Copying config files...`);
|
|
505
515
|
|
|
506
516
|
// Copy root config files
|
|
507
517
|
for (const [src, destName] of Object.entries(configFileMap)) {
|
|
508
|
-
// Check if this file should be injected based on options
|
|
509
|
-
const shouldInject =
|
|
510
|
-
(destName === 'tsconfig.json' && options.tsconfig) ||
|
|
511
|
-
(destName === 'eslint.config.mts' && options.eslint) ||
|
|
512
|
-
(destName === '.prettierrc' && options.prettier) ||
|
|
513
|
-
(destName === '.editorconfig' && options.editorconfig) ||
|
|
514
|
-
(destName === '.gitignore' && options.gitignore) ||
|
|
515
|
-
(destName === '.env' && options.env) ||
|
|
516
|
-
(destName === '.npmrc'); // Always inject .npmrc
|
|
517
|
-
|
|
518
|
-
if (!shouldInject) {
|
|
519
|
-
console.log(` ⏭️ Skipped ${destName} (user choice)`);
|
|
520
|
-
continue;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
518
|
// Skip if not approved by diff step
|
|
524
519
|
const targetFile = path.join(targetPath, destName);
|
|
525
520
|
if (!approvedDests.has(targetFile)) {
|
|
@@ -565,49 +560,41 @@ export async function injectScripts(
|
|
|
565
560
|
}
|
|
566
561
|
|
|
567
562
|
// Copy .vscode config files
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
577
|
-
}
|
|
578
|
-
fs.writeFileSync(targetFile, content, 'utf8');
|
|
579
|
-
console.log(` ✅ ${destName}`);
|
|
580
|
-
} catch (error) {
|
|
581
|
-
console.error(` ❌ Failed to inject ${destName}: ${error}`);
|
|
563
|
+
for (const [src, destName] of Object.entries(configVscodeMap)) {
|
|
564
|
+
try {
|
|
565
|
+
const targetFile = path.join(targetPath, destName);
|
|
566
|
+
if (!approvedDests.has(targetFile)) continue;
|
|
567
|
+
const content = copyFromLocal(src);
|
|
568
|
+
const targetDir = path.dirname(targetFile);
|
|
569
|
+
if (!(await isValidPath(targetDir))) {
|
|
570
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
582
571
|
}
|
|
572
|
+
fs.writeFileSync(targetFile, content, 'utf8');
|
|
573
|
+
console.log(` ✅ ${destName}`);
|
|
574
|
+
} catch (error) {
|
|
575
|
+
console.error(` ❌ Failed to inject ${destName}: ${error}`);
|
|
583
576
|
}
|
|
584
|
-
} else {
|
|
585
|
-
console.log(` ⏭️ Skipped .vscode/ (user choice)`);
|
|
586
577
|
}
|
|
587
578
|
|
|
588
579
|
console.log(`\n📥 Copying GitHub workflows from local files...`);
|
|
589
580
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
fs.writeFileSync(targetFile, content, 'utf8');
|
|
604
|
-
console.log(` ✅ ${relativePath}`);
|
|
605
|
-
} catch (error) {
|
|
606
|
-
console.error(` ❌ Failed to inject ${workflowFile}: ${error}`);
|
|
581
|
+
for (const workflowFile of workflowFiles) {
|
|
582
|
+
try {
|
|
583
|
+
const content = copyFromLocal(workflowFile);
|
|
584
|
+
const relativePath = workflowFile.replace('templates/', '');
|
|
585
|
+
const targetFile = path.join(targetPath, relativePath);
|
|
586
|
+
if (!approvedDests.has(targetFile)) continue;
|
|
587
|
+
const targetDir = path.dirname(targetFile);
|
|
588
|
+
|
|
589
|
+
if (!(await isValidPath(targetDir))) {
|
|
590
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
607
591
|
}
|
|
592
|
+
|
|
593
|
+
fs.writeFileSync(targetFile, content, 'utf8');
|
|
594
|
+
console.log(` ✅ ${relativePath}`);
|
|
595
|
+
} catch (error) {
|
|
596
|
+
console.error(` ❌ Failed to inject ${workflowFile}: ${error}`);
|
|
608
597
|
}
|
|
609
|
-
} else {
|
|
610
|
-
console.log(` ⏭️ Skipped (user choice)`);
|
|
611
598
|
}
|
|
612
599
|
}
|
|
613
600
|
|
|
@@ -616,7 +603,6 @@ export async function injectScripts(
|
|
|
616
603
|
*/
|
|
617
604
|
export async function updatePackageJson(
|
|
618
605
|
targetPath: string,
|
|
619
|
-
options: InjectionOptions,
|
|
620
606
|
useSass: boolean = false
|
|
621
607
|
): Promise<void> {
|
|
622
608
|
const packageJsonPath = path.join(targetPath, 'package.json');
|
|
@@ -626,11 +612,6 @@ export async function updatePackageJson(
|
|
|
626
612
|
return;
|
|
627
613
|
}
|
|
628
614
|
|
|
629
|
-
if (!options.packageJson) {
|
|
630
|
-
console.log(`⏭️ Skipped package.json update (user choice)`);
|
|
631
|
-
return;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
615
|
try {
|
|
635
616
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
636
617
|
|
|
@@ -929,19 +910,19 @@ export async function runYarnInstall(targetPath: string): Promise<void> {
|
|
|
929
910
|
*/
|
|
930
911
|
export async function performInjection(
|
|
931
912
|
targetPath: string,
|
|
932
|
-
|
|
913
|
+
autoConfirm: boolean = false,
|
|
933
914
|
useSass: boolean = false
|
|
934
915
|
): Promise<void> {
|
|
935
916
|
console.log(`\n🚀 Starting injection process...`);
|
|
936
917
|
|
|
937
918
|
try {
|
|
938
|
-
const approvedDests = await diffAndPromptFiles(targetPath,
|
|
919
|
+
const approvedDests = await diffAndPromptFiles(targetPath, autoConfirm);
|
|
939
920
|
await cleanNpmArtifactsIfNeeded(targetPath);
|
|
940
921
|
await ensureTsxInstalled(targetPath);
|
|
941
|
-
await injectScripts(targetPath,
|
|
922
|
+
await injectScripts(targetPath, approvedDests);
|
|
942
923
|
|
|
943
924
|
console.log(`\n📦 Updating package.json...`);
|
|
944
|
-
await updatePackageJson(targetPath,
|
|
925
|
+
await updatePackageJson(targetPath, useSass);
|
|
945
926
|
|
|
946
927
|
await analyzeCentralizedImports(targetPath);
|
|
947
928
|
|
package/scripts/inject-path.ts
CHANGED
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
showInjectionPlan
|
|
12
12
|
} from './inject-core.js';
|
|
13
13
|
import { createReadlineInterface, isValidPath } from './utils.js';
|
|
14
|
-
import { askInjectionOptions, DEFAULT_OPTIONS, getPresetOptions } from './inject-options.js';
|
|
15
14
|
|
|
16
15
|
const rl = createReadlineInterface();
|
|
17
16
|
|
|
@@ -36,8 +35,6 @@ async function main(): Promise<void> {
|
|
|
36
35
|
const autoConfirm = args.includes('--yes') || args.includes('-y');
|
|
37
36
|
const dryRun = args.includes('--dry-run') || args.includes('--check');
|
|
38
37
|
const useSass = args.includes('--sass');
|
|
39
|
-
const interactive = args.includes('--interactive') || args.includes('-i');
|
|
40
|
-
const preset = args.find(arg => arg.startsWith('--preset='))?.split('=')[1];
|
|
41
38
|
const targetPath = args.find((arg) => !arg.startsWith('-'));
|
|
42
39
|
|
|
43
40
|
if (!targetPath) {
|
|
@@ -47,8 +44,6 @@ async function main(): Promise<void> {
|
|
|
47
44
|
console.error(` --yes, -y Auto-confirm injection`);
|
|
48
45
|
console.error(` --dry-run Check only (no injection)`);
|
|
49
46
|
console.error(` --sass Add esbuild-sass-plugin dependency`);
|
|
50
|
-
console.error(` --interactive, -i Choose what to inject`);
|
|
51
|
-
console.error(` --preset=<name> Use preset (minimal, scripts-only, config-only)`);
|
|
52
47
|
console.error(` Shortcuts:`);
|
|
53
48
|
console.error(` yarn check-plugin ../plugin # Verification only`);
|
|
54
49
|
process.exit(1);
|
|
@@ -167,16 +162,7 @@ async function main(): Promise<void> {
|
|
|
167
162
|
process.exit(0);
|
|
168
163
|
}
|
|
169
164
|
|
|
170
|
-
|
|
171
|
-
let options = DEFAULT_OPTIONS;
|
|
172
|
-
if (preset) {
|
|
173
|
-
options = getPresetOptions(preset);
|
|
174
|
-
console.log(`\n🎯 Using preset: ${preset}`);
|
|
175
|
-
} else if (interactive) {
|
|
176
|
-
options = await askInjectionOptions(rl);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
await performInjection(resolvedPath, options, useSass);
|
|
165
|
+
await performInjection(resolvedPath, autoConfirm, useSass);
|
|
180
166
|
} catch (error) {
|
|
181
167
|
console.error(
|
|
182
168
|
`💥 Error: ${error instanceof Error ? error.message : String(error)}`
|
package/scripts/inject-prompt.ts
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
createReadlineInterface,
|
|
15
15
|
isValidPath
|
|
16
16
|
} from './utils.js';
|
|
17
|
-
import { DEFAULT_OPTIONS } from './inject-options.js';
|
|
18
17
|
|
|
19
18
|
const rl = createReadlineInterface();
|
|
20
19
|
|
|
@@ -96,7 +95,7 @@ async function main(): Promise<void> {
|
|
|
96
95
|
process.exit(0);
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
await performInjection(targetPath,
|
|
98
|
+
await performInjection(targetPath, false, useSass);
|
|
100
99
|
} catch (error) {
|
|
101
100
|
console.error(
|
|
102
101
|
`💥 Error: ${error instanceof Error ? error.message : String(error)}`
|
package/tsconfig.json
CHANGED