obsidian-plugin-config 1.7.2 → 1.7.5
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 +7 -7
- package/bin/obsidian-inject.js +21 -13
- package/docs/INTERACTIVE_INJECTION.md +41 -50
- package/docs/LLM-GUIDE.md +8 -7
- package/docs/SCSS-FLOW.md +277 -0
- package/package.json +7 -1
- package/scripts/acp.ts +9 -8
- package/scripts/build-npm.ts +397 -393
- package/scripts/help.ts +87 -87
- package/scripts/inject-core.ts +870 -897
- package/scripts/inject-path.ts +157 -156
- package/scripts/inject-prompt.ts +104 -104
- package/scripts/utils.ts +173 -151
- package/templates/.github/workflows/release.yml +2 -2
- package/templates/.vscode/tasks.json +1 -1
- package/templates/{package.json → package.json.template} +1 -1
- package/templates/scripts/acp.ts +2 -2
- package/templates/scripts/env.ts +4 -5
- package/templates/scripts/esbuild.config.ts +4 -5
- package/templates/scripts/release.ts +14 -17
- package/templates/scripts/utils.ts +42 -25
- package/tsconfig.json +2 -2
- /package/templates/{tsconfig.json → tsconfig.json.template} +0 -0
package/scripts/build-npm.ts
CHANGED
|
@@ -1,393 +1,397 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { execSync } from 'child_process';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
obsidian-inject
|
|
64
|
-
obsidian-inject
|
|
65
|
-
obsidian-inject
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
// Step
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
`
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
console.log(
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
);
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
'scripts/
|
|
352
|
-
'scripts/
|
|
353
|
-
'scripts/
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
'
|
|
371
|
-
'
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
console.log(` ✅
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
|
|
3
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { execSync } from 'child_process';
|
|
6
|
+
import { gitExec, gitOutput, isValidPath } from './utils.ts';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generate bin/obsidian-inject.js from template
|
|
10
|
+
*/
|
|
11
|
+
async function generateBinFile(): Promise<void> {
|
|
12
|
+
console.log(`\n🔧 Generating bin/obsidian-inject.js...`);
|
|
13
|
+
|
|
14
|
+
const binDir = 'bin';
|
|
15
|
+
const binPath = path.join(binDir, 'obsidian-inject.js');
|
|
16
|
+
|
|
17
|
+
// Ensure bin directory exists
|
|
18
|
+
if (!(await isValidPath(binDir))) {
|
|
19
|
+
await mkdir(binDir, { recursive: true });
|
|
20
|
+
console.log(` 📁 Created ${binDir} directory`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Read package.json for version info
|
|
24
|
+
const packageJson = JSON.parse(await readFile('package.json', 'utf8'));
|
|
25
|
+
|
|
26
|
+
const binContent = `#!/usr/bin/env node
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Obsidian Plugin Config - CLI Entry Point
|
|
30
|
+
* Global command: obsidian-inject
|
|
31
|
+
* Version: ${packageJson.version}
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import { execSync } from 'child_process';
|
|
35
|
+
import { fileURLToPath } from 'url';
|
|
36
|
+
import { dirname, join, isAbsolute, resolve } from 'path';
|
|
37
|
+
import { readFile, access, unlink, rm } from 'fs/promises';
|
|
38
|
+
|
|
39
|
+
// Get the directory of this script
|
|
40
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
41
|
+
const __dirname = dirname(__filename);
|
|
42
|
+
const packageRoot = dirname(__dirname);
|
|
43
|
+
|
|
44
|
+
// Path to the injection script
|
|
45
|
+
const injectScriptPath = join(packageRoot, 'scripts', 'inject-path.ts');
|
|
46
|
+
|
|
47
|
+
async function pathExists(p) {
|
|
48
|
+
try {
|
|
49
|
+
await access(p);
|
|
50
|
+
return true;
|
|
51
|
+
} catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function showHelp() {
|
|
57
|
+
console.log(\`
|
|
58
|
+
Obsidian Plugin Config - Global CLI
|
|
59
|
+
Injection system for autonomous Obsidian plugins
|
|
60
|
+
|
|
61
|
+
USAGE:
|
|
62
|
+
obsidian-inject # Inject in current directory (with confirmation)
|
|
63
|
+
obsidian-inject <path> # Inject by path (with confirmation)
|
|
64
|
+
obsidian-inject <path> --no # Inject without confirmation
|
|
65
|
+
obsidian-inject --help, -h # Show this help
|
|
66
|
+
|
|
67
|
+
OPTIONS:
|
|
68
|
+
--no, -n # Skip confirmation prompts (auto-confirm all)
|
|
69
|
+
--dry-run # Verification only (no changes)
|
|
70
|
+
|
|
71
|
+
EXAMPLES:
|
|
72
|
+
cd my-plugin && obsidian-inject
|
|
73
|
+
obsidian-inject ../my-other-plugin
|
|
74
|
+
obsidian-inject ../my-plugin --no
|
|
75
|
+
obsidian-inject "C:\\\\Users\\\\dev\\\\plugins\\\\my-plugin"
|
|
76
|
+
|
|
77
|
+
WHAT IS INJECTED:
|
|
78
|
+
✅ Local scripts (esbuild.config.ts, acp.ts, utils.ts, etc.)
|
|
79
|
+
✅ Package.json configuration (scripts, dependencies)
|
|
80
|
+
✅ Config files (tsconfig, eslint, prettier, vscode, github)
|
|
81
|
+
✅ Yarn protection enforced
|
|
82
|
+
✅ Automatic dependency installation
|
|
83
|
+
|
|
84
|
+
ARCHITECTURE:
|
|
85
|
+
- Plugin becomes AUTONOMOUS with local scripts
|
|
86
|
+
- No external dependencies required after injection
|
|
87
|
+
- Updates possible via re-injection
|
|
88
|
+
|
|
89
|
+
More info: https://github.com/3C0D/obsidian-plugin-config
|
|
90
|
+
\`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function main() {
|
|
94
|
+
const args = process.argv.slice(2);
|
|
95
|
+
|
|
96
|
+
// Handle help flags
|
|
97
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
98
|
+
showHelp();
|
|
99
|
+
process.exit(0);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check if injection script exists
|
|
103
|
+
if (!(await pathExists(injectScriptPath))) {
|
|
104
|
+
console.error(\`❌ Error: Injection script not found at \${injectScriptPath}\`);
|
|
105
|
+
console.error(\` Make sure obsidian-plugin-config is properly installed.\`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Parse arguments
|
|
110
|
+
const noConfirm = args.includes('--no') || args.includes('-n');
|
|
111
|
+
const dryRun = args.includes('--dry-run');
|
|
112
|
+
const pathArg = args.find(arg => !arg.startsWith('-'));
|
|
113
|
+
|
|
114
|
+
// Determine target path (resolve relative to user's current directory)
|
|
115
|
+
const userCwd = process.cwd();
|
|
116
|
+
let targetPath = pathArg || userCwd;
|
|
117
|
+
|
|
118
|
+
// If relative path, resolve from user's current directory
|
|
119
|
+
if (pathArg && !isAbsolute(pathArg)) {
|
|
120
|
+
targetPath = resolve(userCwd, pathArg);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
console.log(\`🎯 Obsidian Plugin Config - Global Injection\`);
|
|
124
|
+
console.log(\`📁 Target: \${targetPath}\`);
|
|
125
|
+
console.log(\`❓ Confirmation: \${noConfirm ? 'Disabled (auto-confirm)' : 'Enabled'}\`);
|
|
126
|
+
console.log(\`📦 From: \${packageRoot}\\n\`);
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
// Check if target directory has package.json
|
|
130
|
+
const targetPackageJson = join(targetPath, 'package.json');
|
|
131
|
+
if (!(await pathExists(targetPackageJson))) {
|
|
132
|
+
console.error(\`❌ Error: package.json not found in \${targetPath}\`);
|
|
133
|
+
console.error(\` Make sure this is a valid Node.js project.\`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Prevent injecting into obsidian-plugin-config itself
|
|
138
|
+
const pkg = JSON.parse(await readFile(targetPackageJson, 'utf8'));
|
|
139
|
+
if (pkg.name === 'obsidian-plugin-config') {
|
|
140
|
+
console.error(\`❌ Cannot inject into obsidian-plugin-config itself.\`);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Clean NPM artifacts if package-lock.json exists
|
|
145
|
+
const packageLockPath = join(targetPath, 'package-lock.json');
|
|
146
|
+
if (await pathExists(packageLockPath)) {
|
|
147
|
+
console.log(\`🧹 NPM installation detected, cleaning...\`);
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
// Remove package-lock.json
|
|
151
|
+
await unlink(packageLockPath);
|
|
152
|
+
console.log(\` 🗑️ package-lock.json removed\`);
|
|
153
|
+
|
|
154
|
+
// Remove node_modules if it exists
|
|
155
|
+
const nodeModulesPath = join(targetPath, 'node_modules');
|
|
156
|
+
if (await pathExists(nodeModulesPath)) {
|
|
157
|
+
await rm(nodeModulesPath, { recursive: true, force: true });
|
|
158
|
+
console.log(\` 🗑️ node_modules removed (will be reinstalled with Yarn)\`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
console.log(\` ✅ NPM artifacts cleaned to avoid Yarn conflicts\`);
|
|
162
|
+
|
|
163
|
+
} catch (cleanError) {
|
|
164
|
+
console.error(\` ❌ Cleanup failed:\`, cleanError instanceof Error ? cleanError.message : String(cleanError));
|
|
165
|
+
console.log(\` 💡 Manually remove package-lock.json and node_modules\`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Check if tsx is available locally in target
|
|
170
|
+
try {
|
|
171
|
+
execSync('npx tsx --version', {
|
|
172
|
+
cwd: targetPath,
|
|
173
|
+
stdio: 'pipe'
|
|
174
|
+
});
|
|
175
|
+
console.log(\`✅ tsx available locally\`);
|
|
176
|
+
} catch {
|
|
177
|
+
console.log(\`⚠️ tsx not found, installing...\`);
|
|
178
|
+
|
|
179
|
+
// Install tsx locally in target directory
|
|
180
|
+
try {
|
|
181
|
+
execSync('yarn add -D tsx', {
|
|
182
|
+
cwd: targetPath,
|
|
183
|
+
stdio: 'inherit'
|
|
184
|
+
});
|
|
185
|
+
console.log(\`✅ tsx installed successfully\`);
|
|
186
|
+
} catch (installError) {
|
|
187
|
+
console.error(\`❌ tsx installation failed:\`, installError.message);
|
|
188
|
+
console.error(\` Try installing tsx manually: cd "\${targetPath}" && yarn add -D tsx\`);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Execute the injection script with tsx
|
|
194
|
+
const yesOption = noConfirm ? ' --yes' : '';
|
|
195
|
+
const dryRunOption = dryRun ? ' --dry-run' : '';
|
|
196
|
+
const command = \`npx tsx "\${injectScriptPath}" "\${targetPath}"\${yesOption}\${dryRunOption}\`;
|
|
197
|
+
|
|
198
|
+
execSync(command, {
|
|
199
|
+
stdio: 'inherit',
|
|
200
|
+
cwd: targetPath // Use target directory to ensure tsx is available
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
console.log(\`\\n✅ Injection completed successfully!\`);
|
|
204
|
+
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error(\`\\n❌ Injection error:\`, error.message);
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
main().catch(console.error);
|
|
212
|
+
`;
|
|
213
|
+
|
|
214
|
+
await writeFile(binPath, binContent, 'utf8');
|
|
215
|
+
console.log(` ✅ Generated ${binPath}`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Ensure NPM authentication, prompting login if needed, then verifying success.
|
|
220
|
+
*/
|
|
221
|
+
async function ensureNpmAuth(): Promise<void> {
|
|
222
|
+
console.log(`🔐 Checking NPM authentication...`);
|
|
223
|
+
|
|
224
|
+
const checkWhoami = (): string | null => {
|
|
225
|
+
try {
|
|
226
|
+
return execSync('npm whoami --registry https://registry.npmjs.org/', {
|
|
227
|
+
stdio: 'pipe',
|
|
228
|
+
encoding: 'utf8'
|
|
229
|
+
}).trim();
|
|
230
|
+
} catch {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const whoami = checkWhoami();
|
|
236
|
+
if (whoami) {
|
|
237
|
+
console.log(` ✅ Logged in as: ${whoami}\n`);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
console.log(` ⚠️ Not logged in to NPM`);
|
|
242
|
+
console.log(`🔑 Please login to NPM to publish the package`);
|
|
243
|
+
console.log(` Opening browser for authentication...\n`);
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
execSync('npm login --auth-type=web --registry https://registry.npmjs.org/', {
|
|
247
|
+
stdio: 'inherit'
|
|
248
|
+
});
|
|
249
|
+
} catch {
|
|
250
|
+
console.error(`\n ❌ NPM login failed`);
|
|
251
|
+
console.error(` Please run 'npm login' manually and try again`);
|
|
252
|
+
throw new Error('NPM authentication required');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Verify login actually succeeded
|
|
256
|
+
const whoamiAfter = checkWhoami();
|
|
257
|
+
if (!whoamiAfter) {
|
|
258
|
+
console.error(
|
|
259
|
+
`\n ❌ Login appeared to complete but authentication could not be verified`
|
|
260
|
+
);
|
|
261
|
+
throw new Error('NPM authentication required');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
console.log(`\n ✅ Successfully logged in as: ${whoamiAfter}\n`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Complete NPM workflow - Version, Commit, Push, Publish
|
|
269
|
+
*/
|
|
270
|
+
async function buildAndPublishNpm(): Promise<void> {
|
|
271
|
+
console.log(`🚀 Obsidian Plugin Config - NPM Publish Workflow`);
|
|
272
|
+
console.log(`Automation: version → bin → verify → commit → publish\n`);
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
// Step 0: Check NPM authentication
|
|
276
|
+
await ensureNpmAuth();
|
|
277
|
+
|
|
278
|
+
// Step 1: Update version
|
|
279
|
+
console.log(`📋 Step 1/5: Updating version...`);
|
|
280
|
+
gitExec('npx tsx scripts/update-version-config.ts');
|
|
281
|
+
|
|
282
|
+
// Step 2: Generate bin file
|
|
283
|
+
console.log(`\n🔧 Step 2/5: Generating bin/obsidian-inject.js...`);
|
|
284
|
+
await generateBinFile();
|
|
285
|
+
|
|
286
|
+
// Step 3: Verify package
|
|
287
|
+
console.log(`\n📋 Step 3/5: Verifying package...`);
|
|
288
|
+
await verifyPackage();
|
|
289
|
+
|
|
290
|
+
// Step 4: Commit and push
|
|
291
|
+
console.log(`\n📤 Step 4/5: Committing and pushing changes...`);
|
|
292
|
+
try {
|
|
293
|
+
// Add all changes
|
|
294
|
+
gitExec('git add -A');
|
|
295
|
+
|
|
296
|
+
// Check if there are changes to commit
|
|
297
|
+
const status = gitOutput('git status --porcelain');
|
|
298
|
+
if (status.trim()) {
|
|
299
|
+
const packageJson = JSON.parse(await readFile('package.json', 'utf8'));
|
|
300
|
+
gitExec(`git commit -m "Publish NPM package v${packageJson.version}"`);
|
|
301
|
+
|
|
302
|
+
// Get current branch and push
|
|
303
|
+
const currentBranch = gitOutput('git rev-parse --abbrev-ref HEAD');
|
|
304
|
+
gitExec(`git push origin ${currentBranch}`);
|
|
305
|
+
console.log(` ✅ Changes committed and pushed`);
|
|
306
|
+
} else {
|
|
307
|
+
console.log(` ℹ️ No changes to commit`);
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
console.error(
|
|
311
|
+
` ❌ Commit/push failed: ${error instanceof Error ? error.message : String(error)}`
|
|
312
|
+
);
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Step 5: Publish to NPM
|
|
317
|
+
console.log(`\n📤 Step 5/5: Publishing to NPM...`);
|
|
318
|
+
gitExec('npm publish --registry https://registry.npmjs.org/');
|
|
319
|
+
|
|
320
|
+
// Optional: Update global CLI automatically
|
|
321
|
+
console.log(`\n🌍 Updating global CLI...`);
|
|
322
|
+
console.log(` ⏳ Waiting 30s for NPM registry propagation...`);
|
|
323
|
+
await new Promise((resolve) => setTimeout(resolve, 30000));
|
|
324
|
+
try {
|
|
325
|
+
gitExec(
|
|
326
|
+
'npm install -g obsidian-plugin-config@latest --force --engine-strict=false'
|
|
327
|
+
);
|
|
328
|
+
console.log(` ✅ Global CLI updated`);
|
|
329
|
+
} catch {
|
|
330
|
+
console.log(` ⚠️ Global CLI update failed (NPM registry may need more time)`);
|
|
331
|
+
console.log(
|
|
332
|
+
` 💡 Run manually in a few minutes: npm install -g obsidian-plugin-config@latest --force`
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
console.log(`\n🎉 Complete workflow successful!`);
|
|
336
|
+
console.log(` Test: cd any-plugin && obsidian-inject`);
|
|
337
|
+
} catch (error) {
|
|
338
|
+
console.error(
|
|
339
|
+
`\n❌ Workflow failed: ${error instanceof Error ? error.message : String(error)}`
|
|
340
|
+
);
|
|
341
|
+
process.exit(1);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Verify package is ready for publication
|
|
347
|
+
*/
|
|
348
|
+
async function verifyPackage(): Promise<void> {
|
|
349
|
+
// Check required scripts
|
|
350
|
+
const requiredScripts = [
|
|
351
|
+
'scripts/inject-path.ts',
|
|
352
|
+
'scripts/inject-prompt.ts',
|
|
353
|
+
'scripts/inject-core.ts',
|
|
354
|
+
'scripts/utils.ts',
|
|
355
|
+
'scripts/acp.ts',
|
|
356
|
+
'scripts/update-version-config.ts',
|
|
357
|
+
'scripts/help.ts'
|
|
358
|
+
];
|
|
359
|
+
|
|
360
|
+
for (const script of requiredScripts) {
|
|
361
|
+
if (!(await isValidPath(script))) {
|
|
362
|
+
throw new Error(`Missing required script: ${script}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
console.log(` ✅ All required scripts present`);
|
|
366
|
+
|
|
367
|
+
// Check package.json
|
|
368
|
+
const packageJson = JSON.parse(await readFile('package.json', 'utf8'));
|
|
369
|
+
const requiredFields = [
|
|
370
|
+
'name',
|
|
371
|
+
'version',
|
|
372
|
+
'description',
|
|
373
|
+
'bin',
|
|
374
|
+
'repository',
|
|
375
|
+
'author'
|
|
376
|
+
];
|
|
377
|
+
|
|
378
|
+
for (const field of requiredFields) {
|
|
379
|
+
if (!packageJson[field]) {
|
|
380
|
+
throw new Error(`Missing required package.json field: ${field}`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
console.log(` ✅ Package.json valid (v${packageJson.version})`);
|
|
384
|
+
|
|
385
|
+
// Check bin file exists
|
|
386
|
+
if (!(await isValidPath('bin/obsidian-inject.js'))) {
|
|
387
|
+
throw new Error(`Missing bin file: bin/obsidian-inject.js`);
|
|
388
|
+
}
|
|
389
|
+
console.log(` ✅ Bin file ready`);
|
|
390
|
+
|
|
391
|
+
// Quick build test (suppress tsc output, only show pass/fail)
|
|
392
|
+
gitExec('npx tsc --noEmit', undefined, true);
|
|
393
|
+
console.log(` ✅ TypeScript check passed`);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Run the script
|
|
397
|
+
await buildAndPublishNpm();
|