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