website-api 1.1.7 → 1.1.9
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/dist/src/cli/ext.js +101 -0
- package/dist/src/util/args-parser.js +4 -0
- package/package.json +1 -1
package/dist/src/cli/ext.js
CHANGED
|
@@ -10,6 +10,7 @@ import { defineSite } from "../core/define-site.js";
|
|
|
10
10
|
import { addRegistry, installEntry, listInstalled, loadIndex, removeInstalled, removeRegistry, resolveEntry, resolveRegistries, searchRegistries, } from "../core/registry.js";
|
|
11
11
|
import { getSite, loadSites } from "../core/runtime.js";
|
|
12
12
|
import { parseArgsForWebsite } from "../util/args-parser.js";
|
|
13
|
+
// #region Helpers
|
|
13
14
|
/** Asks a yes/no question on the TTY; returns true on "y". */
|
|
14
15
|
async function confirm(question) {
|
|
15
16
|
if (!stdin.isTTY)
|
|
@@ -62,6 +63,7 @@ function printLocalHelp(site, entry) {
|
|
|
62
63
|
}
|
|
63
64
|
console.log();
|
|
64
65
|
}
|
|
66
|
+
// #endregion
|
|
65
67
|
/** Registers the `ext` command group on the given Commander program. */
|
|
66
68
|
export function registerExtCommands(program) {
|
|
67
69
|
// `test` forwards unknown flags (e.g. --limit) to the site being tested, which
|
|
@@ -71,6 +73,7 @@ export function registerExtCommands(program) {
|
|
|
71
73
|
.command("ext")
|
|
72
74
|
.description("Discover and install website extensions from a public registry")
|
|
73
75
|
.enablePositionalOptions();
|
|
76
|
+
// #region Command: ext test
|
|
74
77
|
// ── test (run a local file directly, no install) ──
|
|
75
78
|
ext
|
|
76
79
|
.command("test <path> [args...]")
|
|
@@ -131,6 +134,91 @@ export function registerExtCommands(program) {
|
|
|
131
134
|
await dispose();
|
|
132
135
|
}
|
|
133
136
|
});
|
|
137
|
+
// #endregion
|
|
138
|
+
// #region Command: ext run
|
|
139
|
+
// ── run (download/update and run in one command) ──
|
|
140
|
+
ext
|
|
141
|
+
.command("run <id> [args...]")
|
|
142
|
+
.description("Download/update a site from the registry and run it immediately")
|
|
143
|
+
.option("--registry <name>", "Disambiguate when multiple registries offer the id")
|
|
144
|
+
.allowUnknownOption()
|
|
145
|
+
.passThroughOptions()
|
|
146
|
+
.action(async (id, args, opts) => {
|
|
147
|
+
let resolved;
|
|
148
|
+
try {
|
|
149
|
+
resolved = await resolveEntry(id, {
|
|
150
|
+
registryName: opts.registry,
|
|
151
|
+
refresh: true, // Always pull the latest catalog from the network
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
fail(errMsg(err));
|
|
156
|
+
}
|
|
157
|
+
console.error(chalk.gray(`▶ fetching and updating "${resolved.entry.id}" from registry "${resolved.source.name}"...`));
|
|
158
|
+
let dir;
|
|
159
|
+
try {
|
|
160
|
+
const result = await installEntry(resolved.source, resolved.index, resolved.entry, {
|
|
161
|
+
refresh: true, // Always pull the latest files from the network
|
|
162
|
+
});
|
|
163
|
+
dir = result.dir;
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
fail(errMsg(err));
|
|
167
|
+
}
|
|
168
|
+
const entryFile = join(dir, resolved.entry.files[0].name);
|
|
169
|
+
let mod;
|
|
170
|
+
try {
|
|
171
|
+
mod = await import(pathToFileURL(entryFile).href);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
fail(`failed to import ${entryFile}: ${errMsg(err)}`);
|
|
175
|
+
}
|
|
176
|
+
const def = mod.default ?? mod.site;
|
|
177
|
+
if (!def || typeof def !== "object") {
|
|
178
|
+
fail(`${entryFile} does not default-export a site object`);
|
|
179
|
+
}
|
|
180
|
+
let site;
|
|
181
|
+
try {
|
|
182
|
+
site = defineSite(def);
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
fail(errMsg(err));
|
|
186
|
+
}
|
|
187
|
+
site.origin = "extension";
|
|
188
|
+
let parsed;
|
|
189
|
+
try {
|
|
190
|
+
const siteArgs = (args ?? []).filter((a) => a !== "--");
|
|
191
|
+
parsed = parseArgsForWebsite(site.positionals, site.parameters, siteArgs);
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
fail(errMsg(err));
|
|
195
|
+
}
|
|
196
|
+
if (parsed.helpRequested) {
|
|
197
|
+
printLocalHelp(site, entryFile);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
console.error(chalk.gray(`▶ running "${site.id}"`));
|
|
201
|
+
const { ctx, dispose } = createContext(site, parsed.options);
|
|
202
|
+
try {
|
|
203
|
+
const data = await site.run(ctx);
|
|
204
|
+
const output = typeof data === "string" ? data : JSON.stringify(data, null, 2);
|
|
205
|
+
if (parsed.options.out) {
|
|
206
|
+
writeFileSync(parsed.options.out, output + "\n", "utf8");
|
|
207
|
+
console.error(chalk.green(`✓ wrote ${parsed.options.out}`));
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
console.log(output);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
fail(errMsg(err));
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
await dispose();
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
// #endregion
|
|
221
|
+
// #region Command: ext search
|
|
134
222
|
// ── search ──
|
|
135
223
|
ext
|
|
136
224
|
.command("search [query]")
|
|
@@ -166,6 +254,8 @@ export function registerExtCommands(program) {
|
|
|
166
254
|
console.log(table.toString());
|
|
167
255
|
console.log(`\nInstall one with: ${chalk.bold.cyan("npx website-api ext install <id>")}\n`);
|
|
168
256
|
});
|
|
257
|
+
// #endregion
|
|
258
|
+
// #region Command: ext info
|
|
169
259
|
// ── info ──
|
|
170
260
|
ext
|
|
171
261
|
.command("info <id>")
|
|
@@ -188,6 +278,8 @@ export function registerExtCommands(program) {
|
|
|
188
278
|
console.log(` ${chalk.bold((k + ":").padEnd(16))} ${v}`);
|
|
189
279
|
console.log(`\nInstall with: ${chalk.bold.cyan(`npx website-api ext install ${entry.id}`)}\n`);
|
|
190
280
|
});
|
|
281
|
+
// #endregion
|
|
282
|
+
// #region Command: ext install
|
|
191
283
|
// ── install ──
|
|
192
284
|
ext
|
|
193
285
|
.command("install <id>")
|
|
@@ -224,6 +316,8 @@ export function registerExtCommands(program) {
|
|
|
224
316
|
console.log(chalk.green(`\n✓ Installed ${entry.id} → ${dir}`));
|
|
225
317
|
console.log(`Run it with: ${chalk.bold.cyan(`npx website-api ${entry.id}`)}\n`);
|
|
226
318
|
});
|
|
319
|
+
// #endregion
|
|
320
|
+
// #region Command: ext list
|
|
227
321
|
// ── list (installed) ──
|
|
228
322
|
ext
|
|
229
323
|
.command("list")
|
|
@@ -255,6 +349,8 @@ export function registerExtCommands(program) {
|
|
|
255
349
|
}
|
|
256
350
|
console.log(table.toString());
|
|
257
351
|
});
|
|
352
|
+
// #endregion
|
|
353
|
+
// #region Command: ext remove
|
|
258
354
|
// ── remove ──
|
|
259
355
|
ext
|
|
260
356
|
.command("remove <id>")
|
|
@@ -266,6 +362,8 @@ export function registerExtCommands(program) {
|
|
|
266
362
|
else
|
|
267
363
|
fail(`"${id}" is not installed`);
|
|
268
364
|
});
|
|
365
|
+
// #endregion
|
|
366
|
+
// #region Command: ext update
|
|
269
367
|
// ── update ──
|
|
270
368
|
ext
|
|
271
369
|
.command("update [id]")
|
|
@@ -298,6 +396,8 @@ export function registerExtCommands(program) {
|
|
|
298
396
|
}
|
|
299
397
|
console.log(updated ? chalk.green(`\nUpdated ${updated} site(s).`) : chalk.gray("\nNothing to update."));
|
|
300
398
|
});
|
|
399
|
+
// #endregion
|
|
400
|
+
// #region Registry Management Commands
|
|
301
401
|
// ── registry management ──
|
|
302
402
|
const reg = ext.command("registry").description("Manage the registries searched for sites");
|
|
303
403
|
reg
|
|
@@ -335,4 +435,5 @@ export function registerExtCommands(program) {
|
|
|
335
435
|
else
|
|
336
436
|
fail(`registry "${repoOrName}" not found in config`);
|
|
337
437
|
});
|
|
438
|
+
// #endregion
|
|
338
439
|
}
|
|
@@ -88,6 +88,10 @@ export function parseArgsForWebsite(positionalDefs = [], parameterDefs = [], arg
|
|
|
88
88
|
else if (matchedParam.type === "string") {
|
|
89
89
|
const nextVal = argv[i + 1];
|
|
90
90
|
if (nextVal === undefined || nextVal.startsWith("-")) {
|
|
91
|
+
if (matchedParam.name === "proxy") {
|
|
92
|
+
options[camelName] = true;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
91
95
|
throw new Error(`Option ${arg} requires a value`);
|
|
92
96
|
}
|
|
93
97
|
options[camelName] = nextVal;
|
package/package.json
CHANGED