obsidian-plugin-config 1.6.14 → 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 +80 -113
- package/scripts/inject-path.ts +1 -15
- package/scripts/inject-prompt.ts +1 -2
- package/tsconfig.json +1 -1
- 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;
|
|
@@ -277,14 +276,13 @@ export async function cleanOldLintFiles(targetPath: string): Promise<void> {
|
|
|
277
276
|
interface FileEntry {
|
|
278
277
|
src: string; // path relative to configRoot
|
|
279
278
|
dest: string; // absolute path in target plugin
|
|
280
|
-
optionKey: keyof InjectionOptions | null; // null = always inject
|
|
281
279
|
mergeEnv?: boolean; // special .env merge logic
|
|
282
280
|
}
|
|
283
281
|
|
|
284
282
|
/**
|
|
285
283
|
* Build the full list of files to inject, with source and destination paths
|
|
286
284
|
*/
|
|
287
|
-
function buildFileList(targetPath: string
|
|
285
|
+
function buildFileList(targetPath: string): FileEntry[] {
|
|
288
286
|
const scriptsPath = path.join(targetPath, 'scripts');
|
|
289
287
|
const entries: FileEntry[] = [];
|
|
290
288
|
|
|
@@ -300,27 +298,25 @@ function buildFileList(targetPath: string, options: InjectionOptions): FileEntry
|
|
|
300
298
|
for (const src of scriptFiles) {
|
|
301
299
|
entries.push({
|
|
302
300
|
src,
|
|
303
|
-
dest: path.join(scriptsPath, path.basename(src))
|
|
304
|
-
optionKey: 'scripts'
|
|
301
|
+
dest: path.join(scriptsPath, path.basename(src))
|
|
305
302
|
});
|
|
306
303
|
}
|
|
307
304
|
|
|
308
305
|
// Root config files
|
|
309
|
-
const configFileMap: Array<[string, string,
|
|
310
|
-
[
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
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) {
|
|
320
317
|
entries.push({
|
|
321
318
|
src,
|
|
322
319
|
dest: path.join(targetPath, destName),
|
|
323
|
-
optionKey,
|
|
324
320
|
mergeEnv: !!mergeEnv
|
|
325
321
|
});
|
|
326
322
|
}
|
|
@@ -328,13 +324,13 @@ function buildFileList(targetPath: string, options: InjectionOptions): FileEntry
|
|
|
328
324
|
// VSCode config files
|
|
329
325
|
const configVscodeMap: Array<[string, string]> = [
|
|
330
326
|
['templates/.vscode/settings.json', '.vscode/settings.json'],
|
|
331
|
-
['templates/.vscode/tasks.json', '.vscode/tasks.json']
|
|
327
|
+
['templates/.vscode/tasks.json', '.vscode/tasks.json'],
|
|
328
|
+
['templates/.vscode/extensions.json', '.vscode/extensions.json']
|
|
332
329
|
];
|
|
333
330
|
for (const [src, destName] of configVscodeMap) {
|
|
334
331
|
entries.push({
|
|
335
332
|
src,
|
|
336
|
-
dest: path.join(targetPath, destName)
|
|
337
|
-
optionKey: 'vscode'
|
|
333
|
+
dest: path.join(targetPath, destName)
|
|
338
334
|
});
|
|
339
335
|
}
|
|
340
336
|
|
|
@@ -346,8 +342,7 @@ function buildFileList(targetPath: string, options: InjectionOptions): FileEntry
|
|
|
346
342
|
for (const src of workflowFiles) {
|
|
347
343
|
entries.push({
|
|
348
344
|
src,
|
|
349
|
-
dest: path.join(targetPath, src.replace('templates/', ''))
|
|
350
|
-
optionKey: 'github'
|
|
345
|
+
dest: path.join(targetPath, src.replace('templates/', ''))
|
|
351
346
|
});
|
|
352
347
|
}
|
|
353
348
|
|
|
@@ -361,12 +356,12 @@ function buildFileList(targetPath: string, options: InjectionOptions): FileEntry
|
|
|
361
356
|
*/
|
|
362
357
|
export async function diffAndPromptFiles(
|
|
363
358
|
targetPath: string,
|
|
364
|
-
|
|
359
|
+
autoConfirm: boolean
|
|
365
360
|
): Promise<Set<string>> {
|
|
366
361
|
const { askConfirmation, createReadlineInterface } = await import('./utils.js');
|
|
367
|
-
const rl = createReadlineInterface();
|
|
362
|
+
const rl = autoConfirm ? null : createReadlineInterface();
|
|
368
363
|
const configRoot = findPluginConfigRoot();
|
|
369
|
-
const entries = buildFileList(targetPath
|
|
364
|
+
const entries = buildFileList(targetPath);
|
|
370
365
|
const approved = new Set<string>();
|
|
371
366
|
|
|
372
367
|
console.log(`\n🔍 Comparing files with existing content...`);
|
|
@@ -374,8 +369,6 @@ export async function diffAndPromptFiles(
|
|
|
374
369
|
let hasChanges = false;
|
|
375
370
|
|
|
376
371
|
for (const entry of entries) {
|
|
377
|
-
// Skip if disabled by options
|
|
378
|
-
if (entry.optionKey !== null && !options[entry.optionKey]) continue;
|
|
379
372
|
// Skip .env merge (always approved, merge logic handled separately)
|
|
380
373
|
if (entry.mergeEnv) {
|
|
381
374
|
approved.add(entry.dest);
|
|
@@ -418,17 +411,23 @@ export async function diffAndPromptFiles(
|
|
|
418
411
|
continue;
|
|
419
412
|
}
|
|
420
413
|
|
|
421
|
-
// Different → ask user
|
|
414
|
+
// Different → ask user (or auto-approve if autoConfirm)
|
|
422
415
|
hasChanges = true;
|
|
423
416
|
const relDest = path.relative(targetPath, entry.dest);
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
);
|
|
428
|
-
if (update) {
|
|
417
|
+
|
|
418
|
+
if (autoConfirm) {
|
|
419
|
+
console.log(` ✅ ${relDest} (will be updated)`);
|
|
429
420
|
approved.add(entry.dest);
|
|
430
421
|
} else {
|
|
431
|
-
|
|
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
|
+
}
|
|
432
431
|
}
|
|
433
432
|
}
|
|
434
433
|
|
|
@@ -436,7 +435,7 @@ export async function diffAndPromptFiles(
|
|
|
436
435
|
console.log(` ✅ All existing files are up to date`);
|
|
437
436
|
}
|
|
438
437
|
|
|
439
|
-
rl.close();
|
|
438
|
+
if (rl) rl.close();
|
|
440
439
|
return approved;
|
|
441
440
|
}
|
|
442
441
|
|
|
@@ -445,7 +444,6 @@ export async function diffAndPromptFiles(
|
|
|
445
444
|
*/
|
|
446
445
|
export async function injectScripts(
|
|
447
446
|
targetPath: string,
|
|
448
|
-
options: InjectionOptions,
|
|
449
447
|
approvedDests: Set<string>
|
|
450
448
|
): Promise<void> {
|
|
451
449
|
const scriptsPath = path.join(targetPath, 'scripts');
|
|
@@ -479,13 +477,15 @@ export async function injectScripts(
|
|
|
479
477
|
'templates/eslint.config.mts': 'eslint.config.mts',
|
|
480
478
|
'templates/.editorconfig': '.editorconfig',
|
|
481
479
|
'templates/.prettierrc': '.prettierrc',
|
|
480
|
+
'templates/.prettierignore': '.prettierignore',
|
|
482
481
|
'templates/npmrc.template': '.npmrc',
|
|
483
482
|
'templates/env.template': '.env'
|
|
484
483
|
};
|
|
485
484
|
|
|
486
485
|
const configVscodeMap: Record<string, string> = {
|
|
487
486
|
'templates/.vscode/settings.json': '.vscode/settings.json',
|
|
488
|
-
'templates/.vscode/tasks.json': '.vscode/tasks.json'
|
|
487
|
+
'templates/.vscode/tasks.json': '.vscode/tasks.json',
|
|
488
|
+
'templates/.vscode/extensions.json': '.vscode/extensions.json'
|
|
489
489
|
};
|
|
490
490
|
|
|
491
491
|
const workflowFiles = [
|
|
@@ -495,45 +495,26 @@ export async function injectScripts(
|
|
|
495
495
|
|
|
496
496
|
console.log(`\n📥 Copying scripts from local files...`);
|
|
497
497
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
continue;
|
|
506
|
-
}
|
|
507
|
-
const content = copyFromLocal(scriptFile);
|
|
508
|
-
fs.writeFileSync(targetFile, content, 'utf8');
|
|
509
|
-
console.log(` ✅ ${fileName}`);
|
|
510
|
-
} catch (error) {
|
|
511
|
-
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;
|
|
512
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}`);
|
|
513
511
|
}
|
|
514
|
-
} else {
|
|
515
|
-
console.log(` ⏭️ Skipped (user choice)`);
|
|
516
512
|
}
|
|
517
513
|
|
|
518
514
|
console.log(`\n📥 Copying config files...`);
|
|
519
515
|
|
|
520
516
|
// Copy root config files
|
|
521
517
|
for (const [src, destName] of Object.entries(configFileMap)) {
|
|
522
|
-
// Check if this file should be injected based on options
|
|
523
|
-
const shouldInject =
|
|
524
|
-
(destName === 'tsconfig.json' && options.tsconfig) ||
|
|
525
|
-
(destName === 'eslint.config.mts' && options.eslint) ||
|
|
526
|
-
(destName === '.prettierrc' && options.prettier) ||
|
|
527
|
-
(destName === '.editorconfig' && options.editorconfig) ||
|
|
528
|
-
(destName === '.gitignore' && options.gitignore) ||
|
|
529
|
-
(destName === '.env' && options.env) ||
|
|
530
|
-
(destName === '.npmrc'); // Always inject .npmrc
|
|
531
|
-
|
|
532
|
-
if (!shouldInject) {
|
|
533
|
-
console.log(` ⏭️ Skipped ${destName} (user choice)`);
|
|
534
|
-
continue;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
518
|
// Skip if not approved by diff step
|
|
538
519
|
const targetFile = path.join(targetPath, destName);
|
|
539
520
|
if (!approvedDests.has(targetFile)) {
|
|
@@ -579,49 +560,41 @@ export async function injectScripts(
|
|
|
579
560
|
}
|
|
580
561
|
|
|
581
562
|
// Copy .vscode config files
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
591
|
-
}
|
|
592
|
-
fs.writeFileSync(targetFile, content, 'utf8');
|
|
593
|
-
console.log(` ✅ ${destName}`);
|
|
594
|
-
} catch (error) {
|
|
595
|
-
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 });
|
|
596
571
|
}
|
|
572
|
+
fs.writeFileSync(targetFile, content, 'utf8');
|
|
573
|
+
console.log(` ✅ ${destName}`);
|
|
574
|
+
} catch (error) {
|
|
575
|
+
console.error(` ❌ Failed to inject ${destName}: ${error}`);
|
|
597
576
|
}
|
|
598
|
-
} else {
|
|
599
|
-
console.log(` ⏭️ Skipped .vscode/ (user choice)`);
|
|
600
577
|
}
|
|
601
578
|
|
|
602
579
|
console.log(`\n📥 Copying GitHub workflows from local files...`);
|
|
603
580
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
fs.writeFileSync(targetFile, content, 'utf8');
|
|
618
|
-
console.log(` ✅ ${relativePath}`);
|
|
619
|
-
} catch (error) {
|
|
620
|
-
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 });
|
|
621
591
|
}
|
|
592
|
+
|
|
593
|
+
fs.writeFileSync(targetFile, content, 'utf8');
|
|
594
|
+
console.log(` ✅ ${relativePath}`);
|
|
595
|
+
} catch (error) {
|
|
596
|
+
console.error(` ❌ Failed to inject ${workflowFile}: ${error}`);
|
|
622
597
|
}
|
|
623
|
-
} else {
|
|
624
|
-
console.log(` ⏭️ Skipped (user choice)`);
|
|
625
598
|
}
|
|
626
599
|
}
|
|
627
600
|
|
|
@@ -630,7 +603,6 @@ export async function injectScripts(
|
|
|
630
603
|
*/
|
|
631
604
|
export async function updatePackageJson(
|
|
632
605
|
targetPath: string,
|
|
633
|
-
options: InjectionOptions,
|
|
634
606
|
useSass: boolean = false
|
|
635
607
|
): Promise<void> {
|
|
636
608
|
const packageJsonPath = path.join(targetPath, 'package.json');
|
|
@@ -640,11 +612,6 @@ export async function updatePackageJson(
|
|
|
640
612
|
return;
|
|
641
613
|
}
|
|
642
614
|
|
|
643
|
-
if (!options.packageJson) {
|
|
644
|
-
console.log(`⏭️ Skipped package.json update (user choice)`);
|
|
645
|
-
return;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
615
|
try {
|
|
649
616
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
650
617
|
|
|
@@ -943,19 +910,19 @@ export async function runYarnInstall(targetPath: string): Promise<void> {
|
|
|
943
910
|
*/
|
|
944
911
|
export async function performInjection(
|
|
945
912
|
targetPath: string,
|
|
946
|
-
|
|
913
|
+
autoConfirm: boolean = false,
|
|
947
914
|
useSass: boolean = false
|
|
948
915
|
): Promise<void> {
|
|
949
916
|
console.log(`\n🚀 Starting injection process...`);
|
|
950
917
|
|
|
951
918
|
try {
|
|
952
|
-
const approvedDests = await diffAndPromptFiles(targetPath,
|
|
919
|
+
const approvedDests = await diffAndPromptFiles(targetPath, autoConfirm);
|
|
953
920
|
await cleanNpmArtifactsIfNeeded(targetPath);
|
|
954
921
|
await ensureTsxInstalled(targetPath);
|
|
955
|
-
await injectScripts(targetPath,
|
|
922
|
+
await injectScripts(targetPath, approvedDests);
|
|
956
923
|
|
|
957
924
|
console.log(`\n📦 Updating package.json...`);
|
|
958
|
-
await updatePackageJson(targetPath,
|
|
925
|
+
await updatePackageJson(targetPath, useSass);
|
|
959
926
|
|
|
960
927
|
await analyzeCentralizedImports(targetPath);
|
|
961
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
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
|
|
3
|
-
import type { Interface } from 'readline';
|
|
4
|
-
|
|
5
|
-
export interface InjectionOptions {
|
|
6
|
-
scripts: boolean;
|
|
7
|
-
packageJson: boolean;
|
|
8
|
-
tsconfig: boolean;
|
|
9
|
-
eslint: boolean;
|
|
10
|
-
prettier: boolean;
|
|
11
|
-
editorconfig: boolean;
|
|
12
|
-
vscode: boolean;
|
|
13
|
-
github: boolean;
|
|
14
|
-
gitignore: boolean;
|
|
15
|
-
env: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const DEFAULT_OPTIONS: InjectionOptions = {
|
|
19
|
-
scripts: true,
|
|
20
|
-
packageJson: true,
|
|
21
|
-
tsconfig: true,
|
|
22
|
-
eslint: true,
|
|
23
|
-
prettier: true,
|
|
24
|
-
editorconfig: true,
|
|
25
|
-
vscode: true,
|
|
26
|
-
github: true,
|
|
27
|
-
gitignore: true,
|
|
28
|
-
env: true
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const OPTION_DESCRIPTIONS: Record<keyof InjectionOptions, string> = {
|
|
32
|
-
scripts: 'Scripts (esbuild.config.ts, acp.ts, utils.ts, etc.)',
|
|
33
|
-
packageJson: 'package.json (scripts & dependencies)',
|
|
34
|
-
tsconfig: 'tsconfig.json',
|
|
35
|
-
eslint: 'eslint.config.mts',
|
|
36
|
-
prettier: '.prettierrc & .prettierignore',
|
|
37
|
-
editorconfig: '.editorconfig',
|
|
38
|
-
vscode: '.vscode/ (settings.json, tasks.json, extensions.json)',
|
|
39
|
-
github: '.github/workflows/ (release workflow)',
|
|
40
|
-
gitignore: '.gitignore',
|
|
41
|
-
env: '.env (template)'
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Ask user to select which files to inject
|
|
46
|
-
*/
|
|
47
|
-
export async function askInjectionOptions(
|
|
48
|
-
rl: Interface
|
|
49
|
-
): Promise<InjectionOptions> {
|
|
50
|
-
const { askConfirmation } = await import('./utils.js');
|
|
51
|
-
|
|
52
|
-
console.log(`\n🎯 Injection Options`);
|
|
53
|
-
console.log(`Select what you want to inject (default: all)\n`);
|
|
54
|
-
|
|
55
|
-
const useDefaults = await askConfirmation(
|
|
56
|
-
'Use default options (inject everything)?',
|
|
57
|
-
rl
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
if (useDefaults) {
|
|
61
|
-
console.log(`✅ Using default options (all files will be injected)`);
|
|
62
|
-
return DEFAULT_OPTIONS;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
console.log(`\n📋 Select individual options:\n`);
|
|
66
|
-
|
|
67
|
-
const options: InjectionOptions = { ...DEFAULT_OPTIONS };
|
|
68
|
-
|
|
69
|
-
for (const [key, description] of Object.entries(OPTION_DESCRIPTIONS)) {
|
|
70
|
-
const optionKey = key as keyof InjectionOptions;
|
|
71
|
-
const answer = await askConfirmation(`Inject ${description}?`, rl);
|
|
72
|
-
options[optionKey] = answer;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Display summary
|
|
76
|
-
console.log(`\n📋 Selected options:`);
|
|
77
|
-
for (const [key, value] of Object.entries(options)) {
|
|
78
|
-
const optionKey = key as keyof InjectionOptions;
|
|
79
|
-
const icon = value ? '✅' : '❌';
|
|
80
|
-
console.log(` ${icon} ${OPTION_DESCRIPTIONS[optionKey]}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const confirm = await askConfirmation('\nProceed with these options?', rl);
|
|
84
|
-
if (!confirm) {
|
|
85
|
-
console.log('❌ Injection cancelled');
|
|
86
|
-
process.exit(0);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return options;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Get quick preset options
|
|
94
|
-
*/
|
|
95
|
-
export function getPresetOptions(preset: string): InjectionOptions {
|
|
96
|
-
switch (preset) {
|
|
97
|
-
case 'minimal':
|
|
98
|
-
return {
|
|
99
|
-
scripts: true,
|
|
100
|
-
packageJson: true,
|
|
101
|
-
tsconfig: false,
|
|
102
|
-
eslint: false,
|
|
103
|
-
prettier: false,
|
|
104
|
-
editorconfig: false,
|
|
105
|
-
vscode: false,
|
|
106
|
-
github: false,
|
|
107
|
-
gitignore: false,
|
|
108
|
-
env: true
|
|
109
|
-
};
|
|
110
|
-
case 'scripts-only':
|
|
111
|
-
return {
|
|
112
|
-
scripts: true,
|
|
113
|
-
packageJson: false,
|
|
114
|
-
tsconfig: false,
|
|
115
|
-
eslint: false,
|
|
116
|
-
prettier: false,
|
|
117
|
-
editorconfig: false,
|
|
118
|
-
vscode: false,
|
|
119
|
-
github: false,
|
|
120
|
-
gitignore: false,
|
|
121
|
-
env: false
|
|
122
|
-
};
|
|
123
|
-
case 'config-only':
|
|
124
|
-
return {
|
|
125
|
-
scripts: false,
|
|
126
|
-
packageJson: false,
|
|
127
|
-
tsconfig: true,
|
|
128
|
-
eslint: true,
|
|
129
|
-
prettier: true,
|
|
130
|
-
editorconfig: true,
|
|
131
|
-
vscode: true,
|
|
132
|
-
github: false,
|
|
133
|
-
gitignore: true,
|
|
134
|
-
env: false
|
|
135
|
-
};
|
|
136
|
-
default:
|
|
137
|
-
return DEFAULT_OPTIONS;
|
|
138
|
-
}
|
|
139
|
-
}
|