apcore-cli 0.3.2 → 0.5.0
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/CHANGELOG.md +12 -0
- package/README.md +7 -4
- package/dist/bin/apcore-cli.js +233 -11
- package/dist/bin/apcore-cli.js.map +1 -1
- package/dist/index.d.ts +41 -3
- package/dist/index.js +1135 -886
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
3
9
|
var __esm = (fn, res) => function __init() {
|
|
4
10
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
11
|
};
|
|
@@ -50,11 +56,19 @@ function exitCodeForError(error2) {
|
|
|
50
56
|
SCHEMA_CIRCULAR_REF: EXIT_CODES.SCHEMA_CIRCULAR_REF,
|
|
51
57
|
APPROVAL_DENIED: EXIT_CODES.APPROVAL_DENIED,
|
|
52
58
|
APPROVAL_TIMEOUT: EXIT_CODES.APPROVAL_TIMEOUT,
|
|
59
|
+
APPROVAL_PENDING: EXIT_CODES.APPROVAL_DENIED,
|
|
53
60
|
CONFIG_NOT_FOUND: EXIT_CODES.CONFIG_NOT_FOUND,
|
|
54
61
|
CONFIG_INVALID: EXIT_CODES.CONFIG_INVALID,
|
|
55
62
|
MODULE_EXECUTE_ERROR: EXIT_CODES.MODULE_EXECUTE_ERROR,
|
|
56
63
|
MODULE_TIMEOUT: EXIT_CODES.MODULE_TIMEOUT,
|
|
57
|
-
ACL_DENIED: EXIT_CODES.ACL_DENIED
|
|
64
|
+
ACL_DENIED: EXIT_CODES.ACL_DENIED,
|
|
65
|
+
// Config Bus errors (apcore >= 0.15.0)
|
|
66
|
+
CONFIG_NAMESPACE_RESERVED: EXIT_CODES.CONFIG_NAMESPACE_RESERVED,
|
|
67
|
+
CONFIG_NAMESPACE_DUPLICATE: EXIT_CODES.CONFIG_NAMESPACE_DUPLICATE,
|
|
68
|
+
CONFIG_ENV_PREFIX_CONFLICT: EXIT_CODES.CONFIG_ENV_PREFIX_CONFLICT,
|
|
69
|
+
CONFIG_MOUNT_ERROR: EXIT_CODES.CONFIG_MOUNT_ERROR,
|
|
70
|
+
CONFIG_BIND_ERROR: EXIT_CODES.CONFIG_BIND_ERROR,
|
|
71
|
+
ERROR_FORMATTER_DUPLICATE: EXIT_CODES.ERROR_FORMATTER_DUPLICATE
|
|
58
72
|
};
|
|
59
73
|
if (code && code in codeMap) {
|
|
60
74
|
return codeMap[code];
|
|
@@ -124,6 +138,13 @@ var init_errors = __esm({
|
|
|
124
138
|
CONFIG_INVALID: 47,
|
|
125
139
|
SCHEMA_CIRCULAR_REF: 48,
|
|
126
140
|
ACL_DENIED: 77,
|
|
141
|
+
// Config Bus errors (apcore >= 0.15.0)
|
|
142
|
+
CONFIG_NAMESPACE_RESERVED: 78,
|
|
143
|
+
CONFIG_NAMESPACE_DUPLICATE: 78,
|
|
144
|
+
CONFIG_ENV_PREFIX_CONFLICT: 78,
|
|
145
|
+
CONFIG_MOUNT_ERROR: 66,
|
|
146
|
+
CONFIG_BIND_ERROR: 65,
|
|
147
|
+
ERROR_FORMATTER_DUPLICATE: 70,
|
|
127
148
|
KEYBOARD_INTERRUPT: 130
|
|
128
149
|
};
|
|
129
150
|
}
|
|
@@ -137,9 +158,9 @@ __export(audit_exports, {
|
|
|
137
158
|
setAuditLogger: () => setAuditLogger
|
|
138
159
|
});
|
|
139
160
|
import * as crypto from "crypto";
|
|
140
|
-
import * as
|
|
161
|
+
import * as fs3 from "fs";
|
|
141
162
|
import * as os from "os";
|
|
142
|
-
import * as
|
|
163
|
+
import * as path4 from "path";
|
|
143
164
|
function setAuditLogger(auditLogger) {
|
|
144
165
|
_auditLogger = auditLogger;
|
|
145
166
|
}
|
|
@@ -153,7 +174,7 @@ var init_audit = __esm({
|
|
|
153
174
|
init_esm_shims();
|
|
154
175
|
_auditLogger = null;
|
|
155
176
|
AuditLogger = class _AuditLogger {
|
|
156
|
-
static DEFAULT_PATH =
|
|
177
|
+
static DEFAULT_PATH = path4.join(
|
|
157
178
|
os.homedir(),
|
|
158
179
|
".apcore-cli",
|
|
159
180
|
"audit.jsonl"
|
|
@@ -165,7 +186,7 @@ var init_audit = __esm({
|
|
|
165
186
|
}
|
|
166
187
|
ensureDirectory() {
|
|
167
188
|
try {
|
|
168
|
-
|
|
189
|
+
fs3.mkdirSync(path4.dirname(this.logPath), { recursive: true });
|
|
169
190
|
} catch {
|
|
170
191
|
}
|
|
171
192
|
}
|
|
@@ -180,7 +201,7 @@ var init_audit = __esm({
|
|
|
180
201
|
duration_ms: durationMs
|
|
181
202
|
};
|
|
182
203
|
try {
|
|
183
|
-
|
|
204
|
+
fs3.appendFileSync(this.logPath, JSON.stringify(entry) + "\n");
|
|
184
205
|
} catch (err) {
|
|
185
206
|
console.warn(`Could not write audit log: ${err}`);
|
|
186
207
|
}
|
|
@@ -381,9 +402,9 @@ var init_auth = __esm({
|
|
|
381
402
|
|
|
382
403
|
// src/security/sandbox.ts
|
|
383
404
|
import * as child_process from "child_process";
|
|
384
|
-
import * as
|
|
405
|
+
import * as fs4 from "fs";
|
|
385
406
|
import * as os3 from "os";
|
|
386
|
-
import * as
|
|
407
|
+
import * as path5 from "path";
|
|
387
408
|
var Sandbox;
|
|
388
409
|
var init_sandbox = __esm({
|
|
389
410
|
"src/security/sandbox.ts"() {
|
|
@@ -416,8 +437,8 @@ var init_sandbox = __esm({
|
|
|
416
437
|
env[key] = value;
|
|
417
438
|
}
|
|
418
439
|
}
|
|
419
|
-
const tmpDir =
|
|
420
|
-
|
|
440
|
+
const tmpDir = fs4.mkdtempSync(
|
|
441
|
+
path5.join(os3.tmpdir(), "apcore_sandbox_")
|
|
421
442
|
);
|
|
422
443
|
try {
|
|
423
444
|
env.HOME = tmpDir;
|
|
@@ -455,7 +476,7 @@ var init_sandbox = __esm({
|
|
|
455
476
|
);
|
|
456
477
|
} finally {
|
|
457
478
|
try {
|
|
458
|
-
|
|
479
|
+
fs4.rmSync(tmpDir, { recursive: true, force: true });
|
|
459
480
|
} catch {
|
|
460
481
|
}
|
|
461
482
|
}
|
|
@@ -491,10 +512,10 @@ init_esm_shims();
|
|
|
491
512
|
// src/main.ts
|
|
492
513
|
init_esm_shims();
|
|
493
514
|
init_errors();
|
|
494
|
-
import { readFileSync } from "fs";
|
|
495
|
-
import { fileURLToPath as
|
|
496
|
-
import * as
|
|
497
|
-
import { Command, CommanderError } from "commander";
|
|
515
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
516
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
517
|
+
import * as path6 from "path";
|
|
518
|
+
import { Command as Command2, CommanderError, Option as Option2 } from "commander";
|
|
498
519
|
|
|
499
520
|
// src/ref-resolver.ts
|
|
500
521
|
init_esm_shims();
|
|
@@ -1218,975 +1239,1196 @@ function getCliDisplayFields(descriptor) {
|
|
|
1218
1239
|
return [name, desc, tags];
|
|
1219
1240
|
}
|
|
1220
1241
|
|
|
1221
|
-
// src/
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
}
|
|
1242
|
+
// src/config.ts
|
|
1243
|
+
init_esm_shims();
|
|
1244
|
+
import * as fs2 from "fs";
|
|
1245
|
+
import yaml from "js-yaml";
|
|
1246
|
+
var DEFAULTS = {
|
|
1247
|
+
"extensions.root": "./extensions",
|
|
1248
|
+
"logging.level": "WARNING",
|
|
1249
|
+
"sandbox.enabled": false,
|
|
1250
|
+
"cli.stdin_buffer_limit": 10485760,
|
|
1251
|
+
"cli.auto_approve": false,
|
|
1252
|
+
"cli.help_text_max_length": 1e3,
|
|
1253
|
+
// Namespace-mode aliases (apcore >= 0.15.0 Config Bus)
|
|
1254
|
+
"apcore-cli.stdin_buffer_limit": 10485760,
|
|
1255
|
+
"apcore-cli.auto_approve": false,
|
|
1256
|
+
"apcore-cli.help_text_max_length": 1e3,
|
|
1257
|
+
"apcore-cli.logging_level": "WARNING"
|
|
1258
|
+
};
|
|
1259
|
+
var NAMESPACE_TO_LEGACY = {
|
|
1260
|
+
"apcore-cli.stdin_buffer_limit": "cli.stdin_buffer_limit",
|
|
1261
|
+
"apcore-cli.auto_approve": "cli.auto_approve",
|
|
1262
|
+
"apcore-cli.help_text_max_length": "cli.help_text_max_length",
|
|
1263
|
+
"apcore-cli.logging_level": "logging.level"
|
|
1264
|
+
};
|
|
1265
|
+
var LEGACY_TO_NAMESPACE = Object.fromEntries(
|
|
1266
|
+
Object.entries(NAMESPACE_TO_LEGACY).map(([k, v]) => [v, k])
|
|
1267
|
+
);
|
|
1268
|
+
function registerConfigNamespace() {
|
|
1249
1269
|
try {
|
|
1250
|
-
const
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1270
|
+
const { Config } = __require("apcore-js");
|
|
1271
|
+
if (typeof Config?.registerNamespace === "function") {
|
|
1272
|
+
Config.registerNamespace({
|
|
1273
|
+
name: "apcore-cli",
|
|
1274
|
+
envPrefix: "APCORE_CLI",
|
|
1275
|
+
defaults: {
|
|
1276
|
+
stdin_buffer_limit: 10485760,
|
|
1277
|
+
auto_approve: false,
|
|
1278
|
+
help_text_max_length: 1e3,
|
|
1279
|
+
logging_level: "WARNING"
|
|
1280
|
+
}
|
|
1281
|
+
});
|
|
1261
1282
|
}
|
|
1262
1283
|
} catch {
|
|
1263
|
-
console.warn("apcore-toolkit not installed \u2014 toolkit features unavailable");
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
function main(progName) {
|
|
1267
|
-
const program = createCli(void 0, progName);
|
|
1268
|
-
try {
|
|
1269
|
-
program.parse(process.argv);
|
|
1270
|
-
} catch (error2) {
|
|
1271
|
-
if (error2 instanceof CommanderError) {
|
|
1272
|
-
process.exit(error2.exitCode);
|
|
1273
|
-
}
|
|
1274
|
-
const code = exitCodeForError(error2);
|
|
1275
|
-
if (error2 instanceof Error) {
|
|
1276
|
-
process.stderr.write(`Error: ${error2.message}
|
|
1277
|
-
`);
|
|
1278
|
-
}
|
|
1279
|
-
process.exit(code);
|
|
1280
1284
|
}
|
|
1281
1285
|
}
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
const inputSchema = moduleDef.inputSchema;
|
|
1291
|
-
if (inputSchema && typeof inputSchema === "object" && inputSchema.properties) {
|
|
1292
|
-
try {
|
|
1293
|
-
resolvedSchema = resolveRefs(inputSchema, 32, moduleId);
|
|
1294
|
-
} catch {
|
|
1295
|
-
resolvedSchema = inputSchema;
|
|
1296
|
-
}
|
|
1297
|
-
schemaOptions = schemaToCliOptions(resolvedSchema, helpTextMaxLength);
|
|
1298
|
-
}
|
|
1299
|
-
const cmd = new Command(effectiveCmdName).description(cmdHelp);
|
|
1300
|
-
cmd.option("--input <source>", "Read input from STDIN ('-')");
|
|
1301
|
-
cmd.option("-y, --yes", "Bypass approval prompts", false);
|
|
1302
|
-
cmd.option("--large-input", "Allow STDIN input larger than 10MB", false);
|
|
1303
|
-
cmd.option("--format <format>", "Output format (json|table)");
|
|
1304
|
-
cmd.option("--sandbox", "Run module in subprocess sandbox", false);
|
|
1305
|
-
for (const opt of schemaOptions) {
|
|
1306
|
-
if (opt.parseArg) {
|
|
1307
|
-
cmd.option(opt.flags, opt.description, opt.parseArg, opt.defaultValue);
|
|
1308
|
-
} else {
|
|
1309
|
-
cmd.option(opt.flags, opt.description, opt.defaultValue);
|
|
1310
|
-
}
|
|
1286
|
+
var ConfigResolver = class {
|
|
1287
|
+
cliFlags;
|
|
1288
|
+
configPath;
|
|
1289
|
+
fileCache = null;
|
|
1290
|
+
fileCacheLoaded = false;
|
|
1291
|
+
constructor(cliFlags, configPath) {
|
|
1292
|
+
this.cliFlags = cliFlags ?? {};
|
|
1293
|
+
this.configPath = configPath ?? "apcore.yaml";
|
|
1311
1294
|
}
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
if (!builtinKeys.has(k)) {
|
|
1322
|
-
schemaKwargs[k] = v;
|
|
1295
|
+
/**
|
|
1296
|
+
* Resolve a single configuration key across all four tiers.
|
|
1297
|
+
*/
|
|
1298
|
+
resolve(key, cliFlag, envVar) {
|
|
1299
|
+
const flagKey = cliFlag ?? key;
|
|
1300
|
+
if (flagKey in this.cliFlags) {
|
|
1301
|
+
const value = this.cliFlags[flagKey];
|
|
1302
|
+
if (value !== null && value !== void 0) {
|
|
1303
|
+
return value;
|
|
1323
1304
|
}
|
|
1324
1305
|
}
|
|
1325
|
-
|
|
1326
|
-
const
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
const { Sandbox: Sandbox2 } = await Promise.resolve().then(() => (init_security(), security_exports));
|
|
1330
|
-
const sandbox = new Sandbox2(sandboxEnabled);
|
|
1331
|
-
const startTime = performance.now();
|
|
1332
|
-
const result = await sandbox.execute(moduleId, reconverted, executor);
|
|
1333
|
-
const durationMs = Math.round(performance.now() - startTime);
|
|
1334
|
-
const { getAuditLogger: getAuditLogger2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
1335
|
-
const auditLogger = getAuditLogger2();
|
|
1336
|
-
if (auditLogger) {
|
|
1337
|
-
auditLogger.logExecution(moduleId, reconverted, "success", 0, durationMs);
|
|
1338
|
-
}
|
|
1339
|
-
formatExecResult(result, outputFormat);
|
|
1340
|
-
} catch (err) {
|
|
1341
|
-
const { getAuditLogger: getAuditLogger2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
1342
|
-
const auditLogger = getAuditLogger2();
|
|
1343
|
-
const code = exitCodeForError(err);
|
|
1344
|
-
if (auditLogger) {
|
|
1345
|
-
auditLogger.logExecution(moduleId, {}, "error", code, 0);
|
|
1306
|
+
if (envVar) {
|
|
1307
|
+
const envValue = process.env[envVar];
|
|
1308
|
+
if (envValue !== void 0 && envValue !== "") {
|
|
1309
|
+
return envValue;
|
|
1346
1310
|
}
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1311
|
+
}
|
|
1312
|
+
const fileValue = this.resolveFromFile(key);
|
|
1313
|
+
if (fileValue !== void 0) {
|
|
1314
|
+
return fileValue;
|
|
1315
|
+
}
|
|
1316
|
+
const altKey = NAMESPACE_TO_LEGACY[key] ?? LEGACY_TO_NAMESPACE[key];
|
|
1317
|
+
if (altKey) {
|
|
1318
|
+
const altFileValue = this.resolveFromFile(altKey);
|
|
1319
|
+
if (altFileValue !== void 0) {
|
|
1320
|
+
return altFileValue;
|
|
1350
1321
|
}
|
|
1351
|
-
process.exit(code);
|
|
1352
1322
|
}
|
|
1353
|
-
|
|
1354
|
-
return cmd;
|
|
1355
|
-
}
|
|
1356
|
-
function validateModuleId(moduleId) {
|
|
1357
|
-
if (moduleId.length > 128) {
|
|
1358
|
-
process.stderr.write(
|
|
1359
|
-
`Error: Invalid module ID format: '${moduleId}'. Maximum length is 128 characters.
|
|
1360
|
-
`
|
|
1361
|
-
);
|
|
1362
|
-
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
1363
|
-
}
|
|
1364
|
-
if (!/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/.test(moduleId)) {
|
|
1365
|
-
process.stderr.write(
|
|
1366
|
-
`Error: Invalid module ID format: '${moduleId}'.
|
|
1367
|
-
`
|
|
1368
|
-
);
|
|
1369
|
-
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
1323
|
+
return DEFAULTS[key];
|
|
1370
1324
|
}
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
if (
|
|
1376
|
-
|
|
1325
|
+
/**
|
|
1326
|
+
* Load a value from the config file using a dot-separated key path.
|
|
1327
|
+
*/
|
|
1328
|
+
resolveFromFile(key) {
|
|
1329
|
+
if (!this.fileCacheLoaded) {
|
|
1330
|
+
this.fileCache = this.loadConfigFile();
|
|
1331
|
+
this.fileCacheLoaded = true;
|
|
1377
1332
|
}
|
|
1333
|
+
if (this.fileCache === null) {
|
|
1334
|
+
return void 0;
|
|
1335
|
+
}
|
|
1336
|
+
return this.fileCache[key];
|
|
1378
1337
|
}
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1338
|
+
/**
|
|
1339
|
+
* Load and flatten a YAML config file.
|
|
1340
|
+
*/
|
|
1341
|
+
loadConfigFile() {
|
|
1342
|
+
let content;
|
|
1343
|
+
try {
|
|
1344
|
+
content = fs2.readFileSync(this.configPath, "utf-8");
|
|
1345
|
+
} catch (err) {
|
|
1346
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
1347
|
+
return null;
|
|
1348
|
+
}
|
|
1349
|
+
console.warn(
|
|
1350
|
+
`Configuration file '${this.configPath}' is malformed, using defaults.`
|
|
1388
1351
|
);
|
|
1389
|
-
|
|
1390
|
-
}
|
|
1391
|
-
if (!raw) {
|
|
1392
|
-
return cliKwargsNonNull;
|
|
1352
|
+
return null;
|
|
1393
1353
|
}
|
|
1394
|
-
let
|
|
1354
|
+
let parsed;
|
|
1395
1355
|
try {
|
|
1396
|
-
|
|
1356
|
+
parsed = yaml.load(content);
|
|
1397
1357
|
} catch {
|
|
1398
|
-
|
|
1399
|
-
|
|
1358
|
+
console.warn(
|
|
1359
|
+
`Configuration file '${this.configPath}' is malformed, using defaults.`
|
|
1400
1360
|
);
|
|
1401
|
-
|
|
1361
|
+
return null;
|
|
1402
1362
|
}
|
|
1403
|
-
if (typeof
|
|
1404
|
-
|
|
1405
|
-
`
|
|
1406
|
-
`
|
|
1363
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
1364
|
+
console.warn(
|
|
1365
|
+
`Configuration file '${this.configPath}' is malformed, using defaults.`
|
|
1407
1366
|
);
|
|
1408
|
-
|
|
1367
|
+
return null;
|
|
1409
1368
|
}
|
|
1410
|
-
return
|
|
1369
|
+
return this.flattenDict(parsed);
|
|
1411
1370
|
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
const
|
|
1417
|
-
const
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
process.stdin.removeListener("data", onData);
|
|
1428
|
-
process.stdin.removeListener("end", onEnd);
|
|
1429
|
-
process.stdin.removeListener("error", onError);
|
|
1430
|
-
};
|
|
1431
|
-
process.stdin.on("data", onData);
|
|
1432
|
-
process.stdin.on("end", onEnd);
|
|
1433
|
-
process.stdin.on("error", onError);
|
|
1434
|
-
process.stdin.resume();
|
|
1435
|
-
});
|
|
1436
|
-
}
|
|
1437
|
-
function reconvertEnumValues(kwargs, options) {
|
|
1438
|
-
const result = { ...kwargs };
|
|
1439
|
-
for (const opt of options) {
|
|
1440
|
-
if (!opt.enumOriginalTypes) continue;
|
|
1441
|
-
const paramName = opt.name;
|
|
1442
|
-
if (!(paramName in result) || result[paramName] === null || result[paramName] === void 0) {
|
|
1443
|
-
continue;
|
|
1444
|
-
}
|
|
1445
|
-
const strVal = String(result[paramName]);
|
|
1446
|
-
const origType = opt.enumOriginalTypes[strVal];
|
|
1447
|
-
if (origType === "int") {
|
|
1448
|
-
result[paramName] = parseInt(strVal, 10);
|
|
1449
|
-
} else if (origType === "float") {
|
|
1450
|
-
result[paramName] = parseFloat(strVal);
|
|
1451
|
-
} else if (origType === "bool") {
|
|
1452
|
-
result[paramName] = strVal.toLowerCase() === "true";
|
|
1371
|
+
/**
|
|
1372
|
+
* Flatten nested dict to dot-notation keys.
|
|
1373
|
+
*/
|
|
1374
|
+
flattenDict(d, prefix = "") {
|
|
1375
|
+
const result = {};
|
|
1376
|
+
for (const [key, value] of Object.entries(d)) {
|
|
1377
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
1378
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
1379
|
+
Object.assign(
|
|
1380
|
+
result,
|
|
1381
|
+
this.flattenDict(value, fullKey)
|
|
1382
|
+
);
|
|
1383
|
+
} else {
|
|
1384
|
+
result[fullKey] = value;
|
|
1385
|
+
}
|
|
1453
1386
|
}
|
|
1387
|
+
return result;
|
|
1454
1388
|
}
|
|
1455
|
-
|
|
1456
|
-
}
|
|
1389
|
+
};
|
|
1457
1390
|
|
|
1458
|
-
// src/
|
|
1391
|
+
// src/shell.ts
|
|
1459
1392
|
init_esm_shims();
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1393
|
+
init_errors();
|
|
1394
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
1395
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1396
|
+
import * as path3 from "path";
|
|
1397
|
+
import { spawnSync } from "child_process";
|
|
1398
|
+
import { Command, Help, Option } from "commander";
|
|
1399
|
+
var __dirname2 = path3.dirname(fileURLToPath2(import.meta.url));
|
|
1400
|
+
var SHELL_VERSION = "0.0.0";
|
|
1401
|
+
try {
|
|
1402
|
+
const pkg = JSON.parse(readFileSync2(path3.resolve(__dirname2, "../package.json"), "utf-8"));
|
|
1403
|
+
SHELL_VERSION = pkg.version;
|
|
1404
|
+
} catch {
|
|
1405
|
+
}
|
|
1406
|
+
function makeFunctionName(progName) {
|
|
1407
|
+
return "_" + progName.replace(/[^a-zA-Z0-9]/g, "_");
|
|
1408
|
+
}
|
|
1409
|
+
function shellQuote(s) {
|
|
1410
|
+
return "'" + s.replace(/'/g, "'\\''") + "'";
|
|
1411
|
+
}
|
|
1412
|
+
function generateBashCompletion(progName) {
|
|
1413
|
+
const fn = makeFunctionName(progName);
|
|
1414
|
+
const quoted = shellQuote(progName);
|
|
1415
|
+
const moduleListCmd = `${quoted} list --format json 2>/dev/null | node -e "process.stdin.on('data',d=>{JSON.parse(d).forEach(m=>console.log(m.id))})" 2>/dev/null`;
|
|
1416
|
+
const groupsAndTopCmd = `${quoted} list --format json 2>/dev/null | node -e "
|
|
1417
|
+
const m=require('fs').readFileSync('/dev/stdin','utf8');
|
|
1418
|
+
const ids=JSON.parse(m).map(x=>x.id);
|
|
1419
|
+
const g=new Set(),t=[];
|
|
1420
|
+
ids.forEach(i=>{if(i.includes('.'))g.add(i.split('.')[0]);else t.push(i)});
|
|
1421
|
+
console.log([...g].sort().concat(t.sort()).join(' '))
|
|
1422
|
+
" 2>/dev/null`;
|
|
1423
|
+
const groupCmdsCmd = `${quoted} list --format json 2>/dev/null | node -e "
|
|
1424
|
+
const m=require('fs').readFileSync('/dev/stdin','utf8');
|
|
1425
|
+
const g=process.env._APCORE_GRP;
|
|
1426
|
+
JSON.parse(m).map(x=>x.id).filter(i=>i.includes('.')&&i.split('.')[0]===g).forEach(i=>console.log(i.split('.',2)[1]))
|
|
1427
|
+
" 2>/dev/null`;
|
|
1428
|
+
return `${fn}() {
|
|
1429
|
+
local cur prev opts
|
|
1430
|
+
COMPREPLY=()
|
|
1431
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
1432
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
1433
|
+
|
|
1434
|
+
if [[ \${COMP_CWORD} -eq 1 ]]; then
|
|
1435
|
+
opts="completion describe exec init list man"
|
|
1436
|
+
local groups_and_top=$(${groupsAndTopCmd})
|
|
1437
|
+
COMPREPLY=( $(compgen -W "\${opts} \${groups_and_top}" -- \${cur}) )
|
|
1438
|
+
return 0
|
|
1439
|
+
fi
|
|
1440
|
+
|
|
1441
|
+
if [[ \${COMP_CWORD} -eq 2 ]]; then
|
|
1442
|
+
if [[ "\${COMP_WORDS[1]}" == "exec" ]]; then
|
|
1443
|
+
local modules=$(${moduleListCmd})
|
|
1444
|
+
COMPREPLY=( $(compgen -W "\${modules}" -- \${cur}) )
|
|
1445
|
+
return 0
|
|
1446
|
+
fi
|
|
1447
|
+
export _APCORE_GRP="\${COMP_WORDS[1]}"
|
|
1448
|
+
local group_cmds=$(${groupCmdsCmd})
|
|
1449
|
+
COMPREPLY=( $(compgen -W "\${group_cmds}" -- \${cur}) )
|
|
1450
|
+
return 0
|
|
1451
|
+
fi
|
|
1452
|
+
}
|
|
1453
|
+
complete -F ${fn} ${quoted}
|
|
1454
|
+
`;
|
|
1455
|
+
}
|
|
1456
|
+
function generateZshCompletion(progName) {
|
|
1457
|
+
const fn = makeFunctionName(progName);
|
|
1458
|
+
const quoted = shellQuote(progName);
|
|
1459
|
+
const moduleListCmd = `${quoted} list --format json 2>/dev/null | node -e "process.stdin.on('data',d=>{JSON.parse(d).forEach(m=>console.log(m.id))})" 2>/dev/null`;
|
|
1460
|
+
const groupsAndTopCmd = `${quoted} list --format json 2>/dev/null | node -e "
|
|
1461
|
+
const m=require('fs').readFileSync('/dev/stdin','utf8');
|
|
1462
|
+
const ids=JSON.parse(m).map(x=>x.id);
|
|
1463
|
+
const g=new Set(),t=[];
|
|
1464
|
+
ids.forEach(i=>{if(i.includes('.'))g.add(i.split('.')[0]);else t.push(i)});
|
|
1465
|
+
console.log([...g].sort().concat(t.sort()).join(' '))
|
|
1466
|
+
" 2>/dev/null`;
|
|
1467
|
+
const groupCmdsCmd = `${quoted} list --format json 2>/dev/null | node -e "
|
|
1468
|
+
const m=require('fs').readFileSync('/dev/stdin','utf8');
|
|
1469
|
+
const g=process.env._APCORE_GRP;
|
|
1470
|
+
JSON.parse(m).map(x=>x.id).filter(i=>i.includes('.')&&i.split('.')[0]===g).forEach(i=>console.log(i.split('.',2)[1]))
|
|
1471
|
+
" 2>/dev/null`;
|
|
1472
|
+
return `#compdef ${progName}
|
|
1473
|
+
|
|
1474
|
+
${fn}() {
|
|
1475
|
+
local -a commands
|
|
1476
|
+
commands=(
|
|
1477
|
+
'list:List available modules'
|
|
1478
|
+
'describe:Show module metadata and schema'
|
|
1479
|
+
'completion:Generate shell completion script'
|
|
1480
|
+
'init:Scaffolding commands'
|
|
1481
|
+
'man:Generate man page'
|
|
1482
|
+
)
|
|
1483
|
+
|
|
1484
|
+
_arguments -C \\
|
|
1485
|
+
'1:command:->command' \\
|
|
1486
|
+
'*::arg:->args'
|
|
1487
|
+
|
|
1488
|
+
case "$state" in
|
|
1489
|
+
command)
|
|
1490
|
+
_describe -t commands '${progName} commands' commands
|
|
1491
|
+
local -a groups_and_top
|
|
1492
|
+
groups_and_top=($(${groupsAndTopCmd}))
|
|
1493
|
+
compadd -a groups_and_top
|
|
1494
|
+
;;
|
|
1495
|
+
args)
|
|
1496
|
+
case "\${words[1]}" in
|
|
1497
|
+
exec)
|
|
1498
|
+
local modules
|
|
1499
|
+
modules=($(${moduleListCmd}))
|
|
1500
|
+
compadd -a modules
|
|
1501
|
+
;;
|
|
1502
|
+
*)
|
|
1503
|
+
export _APCORE_GRP="\${words[1]}"
|
|
1504
|
+
local -a group_cmds
|
|
1505
|
+
group_cmds=($(${groupCmdsCmd}))
|
|
1506
|
+
compadd -a group_cmds
|
|
1507
|
+
;;
|
|
1508
|
+
esac
|
|
1509
|
+
;;
|
|
1510
|
+
esac
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
compdef ${fn} ${quoted}
|
|
1514
|
+
`;
|
|
1515
|
+
}
|
|
1516
|
+
function generateFishCompletion(progName) {
|
|
1517
|
+
const quoted = shellQuote(progName);
|
|
1518
|
+
const moduleListCmd = `${quoted} list --format json 2>/dev/null | node -e \\"process.stdin.on('data',d=>{JSON.parse(d).forEach(m=>console.log(m.id))})\\" 2>/dev/null`;
|
|
1519
|
+
const groupsAndTopCmd = `${quoted} list --format json 2>/dev/null | node -e \\"const m=require('fs').readFileSync('/dev/stdin','utf8');const ids=JSON.parse(m).map(x=>x.id);const g=new Set(),t=[];ids.forEach(i=>{if(i.includes('.'))g.add(i.split('.')[0]);else t.push(i)});console.log([...g].sort().concat(t.sort()).join('\\\\n'))\\" 2>/dev/null`;
|
|
1520
|
+
return `# Fish completions for ${progName}
|
|
1521
|
+
complete -c ${quoted} -n "__fish_use_subcommand" -a list -d "List available modules"
|
|
1522
|
+
complete -c ${quoted} -n "__fish_use_subcommand" -a describe -d "Show module metadata and schema"
|
|
1523
|
+
complete -c ${quoted} -n "__fish_use_subcommand" -a completion -d "Generate shell completion script"
|
|
1524
|
+
complete -c ${quoted} -n "__fish_use_subcommand" -a init -d "Scaffolding commands"
|
|
1525
|
+
complete -c ${quoted} -n "__fish_use_subcommand" -a man -d "Generate man page"
|
|
1526
|
+
complete -c ${quoted} -n "__fish_use_subcommand" -a "(${groupsAndTopCmd})" -d "Module group"
|
|
1527
|
+
|
|
1528
|
+
complete -c ${quoted} -n "__fish_seen_subcommand_from exec" -a "(${moduleListCmd})"
|
|
1529
|
+
|
|
1530
|
+
function __apcore_group_cmds
|
|
1531
|
+
set -l grp (commandline -opc)[2]
|
|
1532
|
+
set -x _APCORE_GRP $grp
|
|
1533
|
+
${quoted} list --format json 2>/dev/null | node -e "
|
|
1534
|
+
const m=require('fs').readFileSync('/dev/stdin','utf8');
|
|
1535
|
+
const g=process.env._APCORE_GRP;
|
|
1536
|
+
JSON.parse(m).map(x=>x.id).filter(i=>i.includes('.')&&i.split('.')[0]===g).forEach(i=>console.log(i.split('.',2)[1]))
|
|
1537
|
+
" 2>/dev/null
|
|
1538
|
+
end
|
|
1539
|
+
|
|
1540
|
+
# Group subcommand completion \u2014 matches when position 1 is not a builtin
|
|
1541
|
+
complete -c ${quoted} -n "not __fish_use_subcommand; and not __fish_seen_subcommand_from list describe completion init man exec" -a "(__apcore_group_cmds)"
|
|
1542
|
+
`;
|
|
1543
|
+
}
|
|
1544
|
+
function buildSynopsis(command, progName, commandName) {
|
|
1545
|
+
if (!command) {
|
|
1546
|
+
return `\\fB${progName} ${commandName}\\fR [OPTIONS]`;
|
|
1476
1547
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1548
|
+
const parts = [`\\fB${progName} ${commandName}\\fR`];
|
|
1549
|
+
for (const opt of command.options) {
|
|
1550
|
+
const flag = opt.long ?? opt.short ?? "";
|
|
1551
|
+
if (opt.isBoolean?.()) {
|
|
1552
|
+
parts.push(`[${flag}]`);
|
|
1553
|
+
} else if (opt.required) {
|
|
1554
|
+
const typeName = (opt.argChoices ? "CHOICE" : "VALUE").toUpperCase();
|
|
1555
|
+
parts.push(`${flag} \\fI${typeName}\\fR`);
|
|
1556
|
+
} else {
|
|
1557
|
+
const typeName = (opt.argChoices ? "CHOICE" : "VALUE").toUpperCase();
|
|
1558
|
+
parts.push(`[${flag} \\fI${typeName}\\fR]`);
|
|
1483
1559
|
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
if (cliAlias && cliAlias !== moduleId) {
|
|
1492
|
-
this.aliasMap.set(cliAlias, moduleId);
|
|
1493
|
-
}
|
|
1494
|
-
}
|
|
1495
|
-
this.aliasMapBuilt = true;
|
|
1496
|
-
} catch {
|
|
1497
|
-
warn("Failed to build alias map from registry");
|
|
1560
|
+
}
|
|
1561
|
+
for (const arg of command.registeredArguments ?? []) {
|
|
1562
|
+
const meta = arg.name().toUpperCase();
|
|
1563
|
+
if (arg.required) {
|
|
1564
|
+
parts.push(`\\fI${meta}\\fR`);
|
|
1565
|
+
} else {
|
|
1566
|
+
parts.push(`[\\fI${meta}\\fR]`);
|
|
1498
1567
|
}
|
|
1499
1568
|
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
}
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
this.buildAliasMap();
|
|
1521
|
-
const moduleId = this.aliasMap.get(cmdName) ?? cmdName;
|
|
1522
|
-
let moduleDef = this.descriptorCache.get(moduleId);
|
|
1523
|
-
if (!moduleDef) {
|
|
1524
|
-
moduleDef = this.registry.getModule(moduleId) ?? void 0;
|
|
1525
|
-
}
|
|
1526
|
-
if (!moduleDef) {
|
|
1527
|
-
return null;
|
|
1528
|
-
}
|
|
1529
|
-
const cmd = buildModuleCommand(moduleDef, this.executor, this.helpTextMaxLength, cmdName);
|
|
1530
|
-
this.commandCache.set(cmdName, cmd);
|
|
1531
|
-
return cmd;
|
|
1569
|
+
return parts.join(" ");
|
|
1570
|
+
}
|
|
1571
|
+
function generateManPage(commandName, command, progName, version = SHELL_VERSION) {
|
|
1572
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1573
|
+
const title = `${progName}-${commandName}`.toUpperCase();
|
|
1574
|
+
const pkgLabel = `${progName} ${version}`;
|
|
1575
|
+
const manualLabel = `${progName} Manual`;
|
|
1576
|
+
const sections = [];
|
|
1577
|
+
sections.push(`.TH "${title}" "1" "${today}" "${pkgLabel}" "${manualLabel}"`);
|
|
1578
|
+
sections.push(".SH NAME");
|
|
1579
|
+
const desc = command?.description() ?? commandName;
|
|
1580
|
+
const nameDesc = desc.split("\n")[0].replace(/\.$/, "");
|
|
1581
|
+
sections.push(`${progName}-${commandName} \\- ${nameDesc}`);
|
|
1582
|
+
sections.push(".SH SYNOPSIS");
|
|
1583
|
+
sections.push(buildSynopsis(command, progName, commandName));
|
|
1584
|
+
if (command?.description()) {
|
|
1585
|
+
sections.push(".SH DESCRIPTION");
|
|
1586
|
+
sections.push(
|
|
1587
|
+
command.description().replace(/\\/g, "\\\\").replace(/-/g, "\\-")
|
|
1588
|
+
);
|
|
1532
1589
|
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
this._helpTextMaxLength,
|
|
1550
|
-
cmdName
|
|
1551
|
-
);
|
|
1552
|
-
this._cmdCache.set(cmdName, cmd);
|
|
1553
|
-
this.command.addCommand(cmd);
|
|
1590
|
+
if (command && command.options.length > 0) {
|
|
1591
|
+
sections.push(".SH OPTIONS");
|
|
1592
|
+
for (const opt of command.options) {
|
|
1593
|
+
const flag = [opt.short, opt.long].filter(Boolean).join(", ");
|
|
1594
|
+
sections.push(".TP");
|
|
1595
|
+
if (opt.isBoolean?.()) {
|
|
1596
|
+
sections.push(`\\fB${flag}\\fR`);
|
|
1597
|
+
} else {
|
|
1598
|
+
sections.push(`\\fB${flag}\\fR \\fIVALUE\\fR`);
|
|
1599
|
+
}
|
|
1600
|
+
if (opt.description) {
|
|
1601
|
+
sections.push(opt.description);
|
|
1602
|
+
}
|
|
1603
|
+
if (opt.defaultValue !== void 0 && !opt.isBoolean?.()) {
|
|
1604
|
+
sections.push(`Default: ${opt.defaultValue}.`);
|
|
1605
|
+
}
|
|
1554
1606
|
}
|
|
1555
1607
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1608
|
+
sections.push(".SH ENVIRONMENT");
|
|
1609
|
+
sections.push(".TP");
|
|
1610
|
+
sections.push("\\fBAPCORE_EXTENSIONS_ROOT\\fR");
|
|
1611
|
+
sections.push(
|
|
1612
|
+
"Path to the apcore extensions directory. Overrides the default \\fI./extensions\\fR."
|
|
1613
|
+
);
|
|
1614
|
+
sections.push(".TP");
|
|
1615
|
+
sections.push("\\fBAPCORE_CLI_AUTO_APPROVE\\fR");
|
|
1616
|
+
sections.push(
|
|
1617
|
+
"Set to \\fB1\\fR to bypass approval prompts for modules that require human-in-the-loop confirmation."
|
|
1618
|
+
);
|
|
1619
|
+
sections.push(".TP");
|
|
1620
|
+
sections.push("\\fBAPCORE_CLI_LOGGING_LEVEL\\fR");
|
|
1621
|
+
sections.push(
|
|
1622
|
+
"CLI-specific logging verbosity. One of: DEBUG, INFO, WARNING, ERROR. Takes priority over \\fBAPCORE_LOGGING_LEVEL\\fR. Default: WARNING."
|
|
1623
|
+
);
|
|
1624
|
+
sections.push(".TP");
|
|
1625
|
+
sections.push("\\fBAPCORE_LOGGING_LEVEL\\fR");
|
|
1626
|
+
sections.push(
|
|
1627
|
+
"Global apcore logging verbosity. One of: DEBUG, INFO, WARNING, ERROR. Used as fallback when \\fBAPCORE_CLI_LOGGING_LEVEL\\fR is not set. Default: WARNING."
|
|
1628
|
+
);
|
|
1629
|
+
sections.push(".TP");
|
|
1630
|
+
sections.push("\\fBAPCORE_AUTH_API_KEY\\fR");
|
|
1631
|
+
sections.push(
|
|
1632
|
+
"API key for authenticating with the apcore registry."
|
|
1633
|
+
);
|
|
1634
|
+
sections.push(".SH EXIT CODES");
|
|
1635
|
+
const exitCodes = [
|
|
1636
|
+
["0", "Success."],
|
|
1637
|
+
["1", "Module execution error."],
|
|
1638
|
+
["2", "Invalid CLI input or missing argument."],
|
|
1639
|
+
["44", "Module not found, disabled, or failed to load."],
|
|
1640
|
+
["45", "Input failed JSON Schema validation."],
|
|
1641
|
+
[
|
|
1642
|
+
"46",
|
|
1643
|
+
"Approval denied, timed out, or no interactive terminal available."
|
|
1644
|
+
],
|
|
1645
|
+
[
|
|
1646
|
+
"47",
|
|
1647
|
+
"Configuration error (extensions directory not found or unreadable)."
|
|
1648
|
+
],
|
|
1649
|
+
["48", "Schema contains a circular \\fB$ref\\fR."],
|
|
1650
|
+
["77", "ACL denied \u2014 insufficient permissions for this module."],
|
|
1651
|
+
["130", "Execution cancelled by user (SIGINT / Ctrl\\-C)."]
|
|
1652
|
+
];
|
|
1653
|
+
for (const [code, meaning] of exitCodes) {
|
|
1654
|
+
sections.push(`.TP
|
|
1655
|
+
\\fB${code}\\fR
|
|
1656
|
+
${meaning}`);
|
|
1558
1657
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1658
|
+
sections.push(".SH SEE ALSO");
|
|
1659
|
+
sections.push(
|
|
1660
|
+
[
|
|
1661
|
+
`\\fB${progName}\\fR(1)`,
|
|
1662
|
+
`\\fB${progName}\\-list\\fR(1)`,
|
|
1663
|
+
`\\fB${progName}\\-describe\\fR(1)`,
|
|
1664
|
+
`\\fB${progName}\\-completion\\fR(1)`
|
|
1665
|
+
].join(", ")
|
|
1666
|
+
);
|
|
1667
|
+
return sections.join("\n");
|
|
1668
|
+
}
|
|
1669
|
+
function roffEscape(s) {
|
|
1670
|
+
return s.replace(/\\/g, "\\\\").replace(/-/g, "\\-").replace(/'/g, "\\(aq");
|
|
1671
|
+
}
|
|
1672
|
+
function buildProgramManPage(program, progName, version, description, docsUrl2) {
|
|
1673
|
+
const help = new Help();
|
|
1674
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1675
|
+
const s = [];
|
|
1676
|
+
const resolvedDesc = description ?? program.description() ?? `${progName} CLI`;
|
|
1677
|
+
s.push(`.TH "${progName.toUpperCase()}" "1" "${today}" "${progName} ${version}" "${progName} Manual"`);
|
|
1678
|
+
s.push(".SH NAME");
|
|
1679
|
+
s.push(`${progName} \\- ${roffEscape(resolvedDesc)}`);
|
|
1680
|
+
s.push(".SH SYNOPSIS");
|
|
1681
|
+
s.push(`\\fB${progName}\\fR [\\fIglobal\\-options\\fR] \\fIcommand\\fR [\\fIcommand\\-options\\fR]`);
|
|
1682
|
+
if (resolvedDesc) {
|
|
1683
|
+
s.push(".SH DESCRIPTION");
|
|
1684
|
+
s.push(roffEscape(resolvedDesc));
|
|
1685
|
+
}
|
|
1686
|
+
const globalOpts = help.visibleOptions(program).filter((o) => !["help", "version", "all", "man"].includes(o.long?.replace("--", "") ?? ""));
|
|
1687
|
+
if (globalOpts.length > 0) {
|
|
1688
|
+
s.push(".SH GLOBAL OPTIONS");
|
|
1689
|
+
for (const opt of globalOpts) {
|
|
1690
|
+
const flag = [opt.short, opt.long].filter(Boolean).join(", ");
|
|
1691
|
+
s.push(".TP");
|
|
1692
|
+
s.push(`\\fB${roffEscape(flag)}\\fR`);
|
|
1693
|
+
if (opt.description) s.push(roffEscape(opt.description));
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
const allCommands = help.visibleCommands(program);
|
|
1697
|
+
if (allCommands.length > 0) {
|
|
1698
|
+
s.push(".SH COMMANDS");
|
|
1699
|
+
for (const cmd of allCommands) {
|
|
1700
|
+
if (cmd.name() === "help") continue;
|
|
1701
|
+
const desc = help.subcommandDescription(cmd);
|
|
1702
|
+
s.push(".TP");
|
|
1703
|
+
s.push(`\\fB${progName} ${roffEscape(cmd.name())}\\fR`);
|
|
1704
|
+
if (desc) s.push(roffEscape(desc));
|
|
1705
|
+
const cmdHelp = new Help();
|
|
1706
|
+
const opts = cmdHelp.visibleOptions(cmd).filter((o) => !["help", "version"].includes(o.long?.replace("--", "") ?? ""));
|
|
1707
|
+
for (const opt of opts) {
|
|
1708
|
+
const flag = [opt.short, opt.long].filter(Boolean).join(", ");
|
|
1709
|
+
s.push(".RS");
|
|
1710
|
+
s.push(".TP");
|
|
1711
|
+
s.push(`\\fB${roffEscape(flag)}\\fR`);
|
|
1712
|
+
if (opt.description) s.push(roffEscape(opt.description));
|
|
1713
|
+
s.push(".RE");
|
|
1714
|
+
}
|
|
1715
|
+
const subCmds = cmdHelp.visibleCommands(cmd).filter((c) => c.name() !== "help");
|
|
1716
|
+
for (const sub of subCmds) {
|
|
1717
|
+
const subDesc = help.subcommandDescription(sub);
|
|
1718
|
+
s.push(".TP");
|
|
1719
|
+
s.push(`\\fB${progName} ${roffEscape(cmd.name())} ${roffEscape(sub.name())}\\fR`);
|
|
1720
|
+
if (subDesc) s.push(roffEscape(subDesc));
|
|
1721
|
+
const subOpts = cmdHelp.visibleOptions(sub).filter((o) => !["help", "version"].includes(o.long?.replace("--", "") ?? ""));
|
|
1722
|
+
for (const opt of subOpts) {
|
|
1723
|
+
const flag = [opt.short, opt.long].filter(Boolean).join(", ");
|
|
1724
|
+
s.push(".RS");
|
|
1725
|
+
s.push(".TP");
|
|
1726
|
+
s.push(`\\fB${roffEscape(flag)}\\fR`);
|
|
1727
|
+
if (opt.description) s.push(roffEscape(opt.description));
|
|
1728
|
+
s.push(".RE");
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1566
1731
|
}
|
|
1567
|
-
const [, descriptor] = entry;
|
|
1568
|
-
const cmd = buildModuleCommand(
|
|
1569
|
-
descriptor,
|
|
1570
|
-
this._executor,
|
|
1571
|
-
this._helpTextMaxLength,
|
|
1572
|
-
cmdName
|
|
1573
|
-
);
|
|
1574
|
-
this._cmdCache.set(cmdName, cmd);
|
|
1575
|
-
return cmd;
|
|
1576
1732
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
const cliName = cliDisplay.alias ?? moduleId;
|
|
1604
|
-
if (cliName.includes(".")) {
|
|
1605
|
-
const dotIdx = cliName.indexOf(".");
|
|
1606
|
-
const group = cliName.substring(0, dotIdx);
|
|
1607
|
-
const cmd = cliName.substring(dotIdx + 1);
|
|
1608
|
-
return [group, cmd];
|
|
1609
|
-
}
|
|
1610
|
-
return [null, cliName];
|
|
1733
|
+
s.push(".SH ENVIRONMENT");
|
|
1734
|
+
s.push(".TP");
|
|
1735
|
+
s.push("\\fBAPCORE_EXTENSIONS_ROOT\\fR");
|
|
1736
|
+
s.push("Path to the apcore extensions directory.");
|
|
1737
|
+
s.push(".TP");
|
|
1738
|
+
s.push("\\fBAPCORE_CLI_AUTO_APPROVE\\fR");
|
|
1739
|
+
s.push("Set to \\fB1\\fR to bypass approval prompts.");
|
|
1740
|
+
s.push(".TP");
|
|
1741
|
+
s.push("\\fBAPCORE_CLI_LOGGING_LEVEL\\fR");
|
|
1742
|
+
s.push("CLI\\-specific logging verbosity (DEBUG|INFO|WARNING|ERROR).");
|
|
1743
|
+
s.push(".SH EXIT CODES");
|
|
1744
|
+
const exitCodes = [
|
|
1745
|
+
["0", "Success."],
|
|
1746
|
+
["1", "Module execution error."],
|
|
1747
|
+
["2", "Invalid CLI input or missing argument."],
|
|
1748
|
+
["44", "Module not found, disabled, or failed to load."],
|
|
1749
|
+
["45", "Input failed JSON Schema validation."],
|
|
1750
|
+
["46", "Approval denied or timed out."],
|
|
1751
|
+
["47", "Configuration error."],
|
|
1752
|
+
["77", "ACL denied."],
|
|
1753
|
+
["130", "Cancelled by user (SIGINT)."]
|
|
1754
|
+
];
|
|
1755
|
+
for (const [code, meaning] of exitCodes) {
|
|
1756
|
+
s.push(`.TP
|
|
1757
|
+
\\fB${code}\\fR
|
|
1758
|
+
${meaning}`);
|
|
1611
1759
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1760
|
+
s.push(".SH SEE ALSO");
|
|
1761
|
+
s.push(`\\fB${progName} \\-\\-help \\-\\-verbose\\fR for full option list.`);
|
|
1762
|
+
if (docsUrl2) {
|
|
1763
|
+
s.push(`.PP
|
|
1764
|
+
Full documentation at \\fI${roffEscape(docsUrl2)}\\fR`);
|
|
1765
|
+
}
|
|
1766
|
+
return s.join("\n");
|
|
1767
|
+
}
|
|
1768
|
+
function configureManHelp(program, progName, version, description, docsUrl2) {
|
|
1769
|
+
const manOpt = new Option("--man", "Output man page in roff format (use with --help)").hideHelp();
|
|
1770
|
+
program.addOption(manOpt);
|
|
1771
|
+
program.addHelpText("beforeAll", () => {
|
|
1772
|
+
if (program.opts().man) {
|
|
1773
|
+
const roff = buildProgramManPage(program, progName, version, description, docsUrl2) + "\n";
|
|
1774
|
+
if (process.stdout.isTTY) {
|
|
1775
|
+
const pagers = [
|
|
1776
|
+
{ cmd: "mandoc", args: ["-a"] },
|
|
1777
|
+
{ cmd: "groff", args: ["-man", "-Tutf8"] }
|
|
1778
|
+
];
|
|
1779
|
+
let rendered = false;
|
|
1780
|
+
for (const { cmd, args } of pagers) {
|
|
1781
|
+
const result = spawnSync(cmd, args, {
|
|
1782
|
+
input: roff,
|
|
1783
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1784
|
+
encoding: "utf-8"
|
|
1785
|
+
});
|
|
1786
|
+
if (result.status === 0 && result.stdout) {
|
|
1787
|
+
const pager = process.env.PAGER || "less";
|
|
1788
|
+
const pagerResult = spawnSync(pager, ["-R"], {
|
|
1789
|
+
input: result.stdout,
|
|
1790
|
+
stdio: ["pipe", "inherit", "inherit"]
|
|
1791
|
+
});
|
|
1792
|
+
if (pagerResult.status !== null) {
|
|
1793
|
+
rendered = true;
|
|
1794
|
+
break;
|
|
1795
|
+
}
|
|
1638
1796
|
}
|
|
1639
|
-
this.groupMap.get(group).set(cmd, [moduleId, cached]);
|
|
1640
1797
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
if (BUILTIN_COMMANDS.includes(groupName)) {
|
|
1644
|
-
warn(
|
|
1645
|
-
`Group name '${groupName}' collides with a built-in command and will be ignored`
|
|
1646
|
-
);
|
|
1798
|
+
if (!rendered) {
|
|
1799
|
+
process.stdout.write(roff);
|
|
1647
1800
|
}
|
|
1801
|
+
} else {
|
|
1802
|
+
process.stdout.write(roff);
|
|
1648
1803
|
}
|
|
1649
|
-
|
|
1650
|
-
} catch {
|
|
1651
|
-
warn("Failed to build group map");
|
|
1804
|
+
process.exit(0);
|
|
1652
1805
|
}
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
)
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
/**
|
|
1666
|
-
* Get a command by name: check builtins -> group cache -> group map -> top-level modules.
|
|
1667
|
-
*/
|
|
1668
|
-
getCommand(cmdName) {
|
|
1669
|
-
this.buildGroupMap();
|
|
1670
|
-
if (this.groupCache.has(cmdName)) {
|
|
1671
|
-
return this.groupCache.get(cmdName).command;
|
|
1672
|
-
}
|
|
1673
|
-
if (this.groupMap.has(cmdName)) {
|
|
1674
|
-
const lazyGrp = new LazyGroup(
|
|
1675
|
-
this.groupMap.get(cmdName),
|
|
1676
|
-
this.executor,
|
|
1677
|
-
cmdName,
|
|
1678
|
-
this.helpTextMaxLength
|
|
1806
|
+
return "";
|
|
1807
|
+
});
|
|
1808
|
+
}
|
|
1809
|
+
function registerShellCommands(cli, progName = "apcore-cli") {
|
|
1810
|
+
const completionCmd = new Command("completion").description(
|
|
1811
|
+
"Generate a shell completion script and print it to stdout."
|
|
1812
|
+
).argument("<shell>", "Shell type: bash, zsh, or fish").action((shell) => {
|
|
1813
|
+
const validShells = ["bash", "zsh", "fish"];
|
|
1814
|
+
if (!validShells.includes(shell)) {
|
|
1815
|
+
process.stderr.write(
|
|
1816
|
+
`Error: Unknown shell '${shell}'. Expected: bash, zsh, or fish.
|
|
1817
|
+
`
|
|
1679
1818
|
);
|
|
1680
|
-
|
|
1681
|
-
return lazyGrp.command;
|
|
1819
|
+
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
1682
1820
|
}
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1821
|
+
const resolved = cli.name() || progName;
|
|
1822
|
+
const generators = {
|
|
1823
|
+
bash: () => generateBashCompletion(resolved),
|
|
1824
|
+
zsh: () => generateZshCompletion(resolved),
|
|
1825
|
+
fish: () => generateFishCompletion(resolved)
|
|
1826
|
+
};
|
|
1827
|
+
process.stdout.write(generators[shell]());
|
|
1828
|
+
});
|
|
1829
|
+
cli.addCommand(completionCmd);
|
|
1830
|
+
const manCmd = new Command("man").description("Generate a roff man page for COMMAND and print it to stdout.").argument("<command>", "Command to generate man page for").action((commandName) => {
|
|
1831
|
+
const knownBuiltins = /* @__PURE__ */ new Set(["completion", "describe", "exec", "init", "list", "man"]);
|
|
1832
|
+
const cmd = cli.commands.find((c) => c.name() === commandName) ?? null;
|
|
1833
|
+
if (!cmd && !knownBuiltins.has(commandName)) {
|
|
1834
|
+
process.stderr.write(
|
|
1835
|
+
`Error: Unknown command '${commandName}'.
|
|
1836
|
+
`
|
|
1693
1837
|
);
|
|
1694
|
-
|
|
1695
|
-
return cmd;
|
|
1838
|
+
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
1696
1839
|
}
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
/** Expose topLevelModules for testing. */
|
|
1704
|
-
getTopLevelModules() {
|
|
1705
|
-
return this.topLevelModules;
|
|
1706
|
-
}
|
|
1707
|
-
/** Expose groupMapBuilt for testing. */
|
|
1708
|
-
isGroupMapBuilt() {
|
|
1709
|
-
return this.groupMapBuilt;
|
|
1710
|
-
}
|
|
1711
|
-
};
|
|
1840
|
+
const resolved = cli.name() || progName;
|
|
1841
|
+
const roff = generateManPage(commandName, cmd, resolved);
|
|
1842
|
+
process.stdout.write(roff);
|
|
1843
|
+
});
|
|
1844
|
+
cli.addCommand(manCmd);
|
|
1845
|
+
}
|
|
1712
1846
|
|
|
1713
|
-
// src/
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1847
|
+
// src/main.ts
|
|
1848
|
+
var __dirname3 = path6.dirname(fileURLToPath3(import.meta.url));
|
|
1849
|
+
var verboseHelp = false;
|
|
1850
|
+
function setVerboseHelp(verbose) {
|
|
1851
|
+
verboseHelp = verbose;
|
|
1852
|
+
}
|
|
1853
|
+
var docsUrl = null;
|
|
1854
|
+
function setDocsUrl(url) {
|
|
1855
|
+
docsUrl = url;
|
|
1856
|
+
}
|
|
1857
|
+
function hasVerboseFlag() {
|
|
1858
|
+
return process.argv.includes("--verbose");
|
|
1859
|
+
}
|
|
1860
|
+
var VERSION = "0.0.0";
|
|
1861
|
+
try {
|
|
1862
|
+
const pkg = JSON.parse(readFileSync3(path6.resolve(__dirname3, "../package.json"), "utf-8"));
|
|
1863
|
+
VERSION = pkg.version;
|
|
1864
|
+
} catch {
|
|
1865
|
+
}
|
|
1866
|
+
function createCli(extensionsDir, progName, verbose = false) {
|
|
1867
|
+
verboseHelp = verbose;
|
|
1868
|
+
registerConfigNamespace();
|
|
1869
|
+
const resolvedProgName = progName ?? path6.basename(process.argv[1] ?? "apcore-cli") ?? "apcore-cli";
|
|
1870
|
+
const cliLogLevel = process.env.APCORE_CLI_LOGGING_LEVEL ?? process.env.APCORE_LOGGING_LEVEL ?? "WARNING";
|
|
1871
|
+
setLogLevel(cliLogLevel);
|
|
1872
|
+
const program = new Command2(resolvedProgName).exitOverride().version(VERSION, "--version", `Show ${resolvedProgName} version`).description("apcore CLI \u2014 execute apcore modules from the command line").option("--extensions-dir <path>", "Path to extensions directory").option("--commands-dir <path>", "Path to convention-based commands directory").option("--binding <path>", "Path to binding.yaml for display overlay").option("--log-level <level>", "Logging level (DEBUG|INFO|WARNING|ERROR)", "WARNING").option("--verbose", "Show all options in help output (including built-in apcore options)");
|
|
1873
|
+
const resolvedExtDir = extensionsDir ?? process.env.APCORE_EXTENSIONS_ROOT ?? "./extensions";
|
|
1874
|
+
void resolvedExtDir;
|
|
1875
|
+
program.addHelpText("after", [
|
|
1876
|
+
"",
|
|
1877
|
+
"Use --help --verbose to show all options (including built-in apcore options).",
|
|
1878
|
+
"Use --help --man to display a formatted man page."
|
|
1879
|
+
].join("\n"));
|
|
1880
|
+
registerInitCommand(program);
|
|
1881
|
+
configureManHelp(program, resolvedProgName, VERSION);
|
|
1882
|
+
program.hook("preAction", async (thisCommand) => {
|
|
1883
|
+
const opts = thisCommand.opts();
|
|
1884
|
+
const commandsDir = opts.commandsDir;
|
|
1885
|
+
const bindingPath = opts.binding;
|
|
1886
|
+
await applyToolkitIntegration(commandsDir, bindingPath);
|
|
1887
|
+
});
|
|
1888
|
+
return program;
|
|
1889
|
+
}
|
|
1890
|
+
async function applyToolkitIntegration(commandsDir, bindingPath) {
|
|
1891
|
+
if (!commandsDir && !bindingPath) {
|
|
1892
|
+
return;
|
|
1733
1893
|
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
return value;
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
if (envVar) {
|
|
1746
|
-
const envValue = process.env[envVar];
|
|
1747
|
-
if (envValue !== void 0 && envValue !== "") {
|
|
1748
|
-
return envValue;
|
|
1749
|
-
}
|
|
1894
|
+
try {
|
|
1895
|
+
const toolkitModule = "apcore-toolkit";
|
|
1896
|
+
const toolkit = await import(
|
|
1897
|
+
/* @vite-ignore */
|
|
1898
|
+
toolkitModule
|
|
1899
|
+
);
|
|
1900
|
+
if (commandsDir) {
|
|
1901
|
+
console.warn("Convention scanning not yet available in TypeScript toolkit");
|
|
1750
1902
|
}
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1903
|
+
if (bindingPath) {
|
|
1904
|
+
const resolver = new toolkit.DisplayResolver();
|
|
1905
|
+
void resolver;
|
|
1754
1906
|
}
|
|
1755
|
-
|
|
1907
|
+
} catch {
|
|
1908
|
+
console.warn("apcore-toolkit not installed \u2014 toolkit features unavailable");
|
|
1756
1909
|
}
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1910
|
+
}
|
|
1911
|
+
function main(progName) {
|
|
1912
|
+
verboseHelp = hasVerboseFlag();
|
|
1913
|
+
const program = createCli(void 0, progName, verboseHelp);
|
|
1914
|
+
try {
|
|
1915
|
+
program.parse(process.argv);
|
|
1916
|
+
} catch (error2) {
|
|
1917
|
+
if (error2 instanceof CommanderError) {
|
|
1918
|
+
process.exit(error2.exitCode);
|
|
1764
1919
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1920
|
+
const code = exitCodeForError(error2);
|
|
1921
|
+
if (error2 instanceof Error) {
|
|
1922
|
+
process.stderr.write(`Error: ${error2.message}
|
|
1923
|
+
`);
|
|
1767
1924
|
}
|
|
1768
|
-
|
|
1925
|
+
process.exit(code);
|
|
1769
1926
|
}
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
console.warn(
|
|
1782
|
-
`Configuration file '${this.configPath}' is malformed, using defaults.`
|
|
1783
|
-
);
|
|
1784
|
-
return null;
|
|
1785
|
-
}
|
|
1786
|
-
let parsed;
|
|
1927
|
+
}
|
|
1928
|
+
function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdName, verbose = verboseHelp) {
|
|
1929
|
+
const moduleId = moduleDef.id;
|
|
1930
|
+
let resolvedSchema = {};
|
|
1931
|
+
let schemaOptions = [];
|
|
1932
|
+
const display = getDisplay(moduleDef);
|
|
1933
|
+
const cliDisplay = display.cli && typeof display.cli === "object" && !Array.isArray(display.cli) ? display.cli : {};
|
|
1934
|
+
const effectiveCmdName = cmdName ?? cliDisplay.alias ?? moduleId;
|
|
1935
|
+
const cmdHelp = cliDisplay.description ?? moduleDef.description;
|
|
1936
|
+
const inputSchema = moduleDef.inputSchema;
|
|
1937
|
+
if (inputSchema && typeof inputSchema === "object" && inputSchema.properties) {
|
|
1787
1938
|
try {
|
|
1788
|
-
|
|
1939
|
+
resolvedSchema = resolveRefs(inputSchema, 32, moduleId);
|
|
1789
1940
|
} catch {
|
|
1790
|
-
|
|
1791
|
-
`Configuration file '${this.configPath}' is malformed, using defaults.`
|
|
1792
|
-
);
|
|
1793
|
-
return null;
|
|
1941
|
+
resolvedSchema = inputSchema;
|
|
1794
1942
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1943
|
+
schemaOptions = schemaToCliOptions(resolvedSchema, helpTextMaxLength);
|
|
1944
|
+
}
|
|
1945
|
+
const cmd = new Command2(effectiveCmdName).description(cmdHelp);
|
|
1946
|
+
const inputOpt = new Option2("--input <source>", "Read JSON input from a file path, or use '-' to read from stdin pipe");
|
|
1947
|
+
const yesOpt = new Option2("-y, --yes", "Skip interactive approval prompts (for scripts and CI)").default(false);
|
|
1948
|
+
const largeInputOpt = new Option2("--large-input", "Allow stdin input larger than 10MB (default limit protects against accidental pipes)").default(false);
|
|
1949
|
+
const formatOpt = new Option2("--format <format>", "Set output format: 'json' for machine-readable, 'table' for human-readable");
|
|
1950
|
+
const sandboxOpt = new Option2("--sandbox", "Run module in an isolated subprocess with restricted filesystem and env access").default(false).hideHelp();
|
|
1951
|
+
if (!verbose) {
|
|
1952
|
+
inputOpt.hideHelp();
|
|
1953
|
+
yesOpt.hideHelp();
|
|
1954
|
+
largeInputOpt.hideHelp();
|
|
1955
|
+
formatOpt.hideHelp();
|
|
1956
|
+
}
|
|
1957
|
+
cmd.addOption(inputOpt);
|
|
1958
|
+
cmd.addOption(yesOpt);
|
|
1959
|
+
cmd.addOption(largeInputOpt);
|
|
1960
|
+
cmd.addOption(formatOpt);
|
|
1961
|
+
cmd.addOption(sandboxOpt);
|
|
1962
|
+
const footerParts = [];
|
|
1963
|
+
if (!verbose) {
|
|
1964
|
+
footerParts.push("Use --verbose to show all options (including built-in apcore options).");
|
|
1965
|
+
}
|
|
1966
|
+
if (docsUrl) {
|
|
1967
|
+
footerParts.push(`Docs: ${docsUrl}/commands/${effectiveCmdName}`);
|
|
1968
|
+
}
|
|
1969
|
+
if (footerParts.length > 0) {
|
|
1970
|
+
cmd.addHelpText("after", "\n" + footerParts.join("\n") + "\n");
|
|
1971
|
+
}
|
|
1972
|
+
for (const opt of schemaOptions) {
|
|
1973
|
+
if (opt.parseArg) {
|
|
1974
|
+
cmd.option(opt.flags, opt.description, opt.parseArg, opt.defaultValue);
|
|
1975
|
+
} else {
|
|
1976
|
+
cmd.option(opt.flags, opt.description, opt.defaultValue);
|
|
1800
1977
|
}
|
|
1801
|
-
return this.flattenDict(parsed);
|
|
1802
1978
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
const
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
);
|
|
1815
|
-
} else {
|
|
1816
|
-
result[fullKey] = value;
|
|
1979
|
+
cmd.action(async (options) => {
|
|
1980
|
+
const stdinFlag = options.input;
|
|
1981
|
+
const autoApprove = options.yes;
|
|
1982
|
+
const largeInput = options.largeInput;
|
|
1983
|
+
const outputFormat = options.format;
|
|
1984
|
+
const sandboxEnabled = options.sandbox;
|
|
1985
|
+
const schemaKwargs = {};
|
|
1986
|
+
const builtinKeys = /* @__PURE__ */ new Set(["input", "yes", "largeInput", "format", "sandbox", "verbose"]);
|
|
1987
|
+
for (const [k, v] of Object.entries(options)) {
|
|
1988
|
+
if (!builtinKeys.has(k)) {
|
|
1989
|
+
schemaKwargs[k] = v;
|
|
1817
1990
|
}
|
|
1818
1991
|
}
|
|
1819
|
-
|
|
1992
|
+
try {
|
|
1993
|
+
const merged = await collectInput(stdinFlag, schemaKwargs, largeInput);
|
|
1994
|
+
const reconverted = reconvertEnumValues(merged, schemaOptions);
|
|
1995
|
+
await checkApproval(moduleDef, autoApprove);
|
|
1996
|
+
const { Sandbox: Sandbox2 } = await Promise.resolve().then(() => (init_security(), security_exports));
|
|
1997
|
+
const sandbox = new Sandbox2(sandboxEnabled);
|
|
1998
|
+
const startTime = performance.now();
|
|
1999
|
+
const result = await sandbox.execute(moduleId, reconverted, executor);
|
|
2000
|
+
const durationMs = Math.round(performance.now() - startTime);
|
|
2001
|
+
const { getAuditLogger: getAuditLogger2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
2002
|
+
const auditLogger = getAuditLogger2();
|
|
2003
|
+
if (auditLogger) {
|
|
2004
|
+
auditLogger.logExecution(moduleId, reconverted, "success", 0, durationMs);
|
|
2005
|
+
}
|
|
2006
|
+
formatExecResult(result, outputFormat);
|
|
2007
|
+
} catch (err) {
|
|
2008
|
+
const { getAuditLogger: getAuditLogger2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
2009
|
+
const auditLogger = getAuditLogger2();
|
|
2010
|
+
const code = exitCodeForError(err);
|
|
2011
|
+
if (auditLogger) {
|
|
2012
|
+
auditLogger.logExecution(moduleId, {}, "error", code, 0);
|
|
2013
|
+
}
|
|
2014
|
+
if (err instanceof Error) {
|
|
2015
|
+
process.stderr.write(`Error: ${err.message}
|
|
2016
|
+
`);
|
|
2017
|
+
}
|
|
2018
|
+
process.exit(code);
|
|
2019
|
+
}
|
|
2020
|
+
});
|
|
2021
|
+
return cmd;
|
|
2022
|
+
}
|
|
2023
|
+
function validateModuleId(moduleId) {
|
|
2024
|
+
if (moduleId.length > 128) {
|
|
2025
|
+
process.stderr.write(
|
|
2026
|
+
`Error: Invalid module ID format: '${moduleId}'. Maximum length is 128 characters.
|
|
2027
|
+
`
|
|
2028
|
+
);
|
|
2029
|
+
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
1820
2030
|
}
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
// src/discovery.ts
|
|
1824
|
-
init_esm_shims();
|
|
1825
|
-
init_errors();
|
|
1826
|
-
import { Command as Command3 } from "commander";
|
|
1827
|
-
var TAG_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
1828
|
-
function validateTag(tag) {
|
|
1829
|
-
if (!TAG_PATTERN.test(tag)) {
|
|
2031
|
+
if (!/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/.test(moduleId)) {
|
|
1830
2032
|
process.stderr.write(
|
|
1831
|
-
`Error: Invalid
|
|
2033
|
+
`Error: Invalid module ID format: '${moduleId}'.
|
|
1832
2034
|
`
|
|
1833
2035
|
);
|
|
1834
2036
|
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
1835
2037
|
}
|
|
1836
2038
|
}
|
|
1837
|
-
function
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
for (const t of opts.tag) {
|
|
1843
|
-
validateTag(t);
|
|
2039
|
+
async function collectInput(stdinFlag, cliKwargs = {}, largeInput) {
|
|
2040
|
+
const cliKwargsNonNull = {};
|
|
2041
|
+
for (const [k, v] of Object.entries(cliKwargs)) {
|
|
2042
|
+
if (v !== null && v !== void 0) {
|
|
2043
|
+
cliKwargsNonNull[k] = v;
|
|
1844
2044
|
}
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
2045
|
+
}
|
|
2046
|
+
if (!stdinFlag) {
|
|
2047
|
+
return cliKwargsNonNull;
|
|
2048
|
+
}
|
|
2049
|
+
if (stdinFlag === "-") {
|
|
2050
|
+
const raw = await readStdin();
|
|
2051
|
+
const rawSize = Buffer.byteLength(raw, "utf-8");
|
|
2052
|
+
if (rawSize > 10485760 && !largeInput) {
|
|
2053
|
+
process.stderr.write(
|
|
2054
|
+
"Error: STDIN input exceeds 10MB limit. Use --large-input to override.\n"
|
|
2055
|
+
);
|
|
2056
|
+
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
1848
2057
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
const filterTags = new Set(opts.tag);
|
|
1852
|
-
filtered = modules.filter((m) => {
|
|
1853
|
-
const mTags = m.tags ?? [];
|
|
1854
|
-
return [...filterTags].every((t) => mTags.includes(t));
|
|
1855
|
-
});
|
|
2058
|
+
if (!raw) {
|
|
2059
|
+
return cliKwargsNonNull;
|
|
1856
2060
|
}
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
const describeCmd = new Command3("describe").description("Show metadata, schema, and annotations for a module.").argument("<module-id>", "Module ID to describe").option("--format <format>", "Output format.", void 0).action((moduleId, opts) => {
|
|
1862
|
-
validateModuleId(moduleId);
|
|
1863
|
-
const moduleDef = registry.getModule(moduleId);
|
|
1864
|
-
if (!moduleDef) {
|
|
2061
|
+
let stdinData;
|
|
2062
|
+
try {
|
|
2063
|
+
stdinData = JSON.parse(raw);
|
|
2064
|
+
} catch {
|
|
1865
2065
|
process.stderr.write(
|
|
1866
|
-
|
|
2066
|
+
"Error: STDIN does not contain valid JSON.\n"
|
|
2067
|
+
);
|
|
2068
|
+
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
2069
|
+
}
|
|
2070
|
+
if (typeof stdinData !== "object" || stdinData === null || Array.isArray(stdinData)) {
|
|
2071
|
+
process.stderr.write(
|
|
2072
|
+
`Error: STDIN JSON must be an object, got ${Array.isArray(stdinData) ? "array" : typeof stdinData}.
|
|
1867
2073
|
`
|
|
1868
2074
|
);
|
|
1869
|
-
process.exit(EXIT_CODES.
|
|
2075
|
+
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
1870
2076
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
cli.addCommand(describeCmd);
|
|
1875
|
-
}
|
|
1876
|
-
|
|
1877
|
-
// src/shell.ts
|
|
1878
|
-
init_esm_shims();
|
|
1879
|
-
init_errors();
|
|
1880
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
1881
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1882
|
-
import * as path6 from "path";
|
|
1883
|
-
import { Command as Command4 } from "commander";
|
|
1884
|
-
var __dirname3 = path6.dirname(fileURLToPath3(import.meta.url));
|
|
1885
|
-
var SHELL_VERSION = "0.0.0";
|
|
1886
|
-
try {
|
|
1887
|
-
const pkg = JSON.parse(readFileSync3(path6.resolve(__dirname3, "../package.json"), "utf-8"));
|
|
1888
|
-
SHELL_VERSION = pkg.version;
|
|
1889
|
-
} catch {
|
|
1890
|
-
}
|
|
1891
|
-
function makeFunctionName(progName) {
|
|
1892
|
-
return "_" + progName.replace(/[^a-zA-Z0-9]/g, "_");
|
|
1893
|
-
}
|
|
1894
|
-
function shellQuote(s) {
|
|
1895
|
-
return "'" + s.replace(/'/g, "'\\''") + "'";
|
|
1896
|
-
}
|
|
1897
|
-
function generateBashCompletion(progName) {
|
|
1898
|
-
const fn = makeFunctionName(progName);
|
|
1899
|
-
const quoted = shellQuote(progName);
|
|
1900
|
-
const moduleListCmd = `${quoted} list --format json 2>/dev/null | node -e "process.stdin.on('data',d=>{JSON.parse(d).forEach(m=>console.log(m.id))})" 2>/dev/null`;
|
|
1901
|
-
const groupsAndTopCmd = `${quoted} list --format json 2>/dev/null | node -e "
|
|
1902
|
-
const m=require('fs').readFileSync('/dev/stdin','utf8');
|
|
1903
|
-
const ids=JSON.parse(m).map(x=>x.id);
|
|
1904
|
-
const g=new Set(),t=[];
|
|
1905
|
-
ids.forEach(i=>{if(i.includes('.'))g.add(i.split('.')[0]);else t.push(i)});
|
|
1906
|
-
console.log([...g].sort().concat(t.sort()).join(' '))
|
|
1907
|
-
" 2>/dev/null`;
|
|
1908
|
-
const groupCmdsCmd = `${quoted} list --format json 2>/dev/null | node -e "
|
|
1909
|
-
const m=require('fs').readFileSync('/dev/stdin','utf8');
|
|
1910
|
-
const g=process.env._APCORE_GRP;
|
|
1911
|
-
JSON.parse(m).map(x=>x.id).filter(i=>i.includes('.')&&i.split('.')[0]===g).forEach(i=>console.log(i.split('.',2)[1]))
|
|
1912
|
-
" 2>/dev/null`;
|
|
1913
|
-
return `${fn}() {
|
|
1914
|
-
local cur prev opts
|
|
1915
|
-
COMPREPLY=()
|
|
1916
|
-
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
1917
|
-
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
1918
|
-
|
|
1919
|
-
if [[ \${COMP_CWORD} -eq 1 ]]; then
|
|
1920
|
-
opts="completion describe exec init list man"
|
|
1921
|
-
local groups_and_top=$(${groupsAndTopCmd})
|
|
1922
|
-
COMPREPLY=( $(compgen -W "\${opts} \${groups_and_top}" -- \${cur}) )
|
|
1923
|
-
return 0
|
|
1924
|
-
fi
|
|
1925
|
-
|
|
1926
|
-
if [[ \${COMP_CWORD} -eq 2 ]]; then
|
|
1927
|
-
if [[ "\${COMP_WORDS[1]}" == "exec" ]]; then
|
|
1928
|
-
local modules=$(${moduleListCmd})
|
|
1929
|
-
COMPREPLY=( $(compgen -W "\${modules}" -- \${cur}) )
|
|
1930
|
-
return 0
|
|
1931
|
-
fi
|
|
1932
|
-
export _APCORE_GRP="\${COMP_WORDS[1]}"
|
|
1933
|
-
local group_cmds=$(${groupCmdsCmd})
|
|
1934
|
-
COMPREPLY=( $(compgen -W "\${group_cmds}" -- \${cur}) )
|
|
1935
|
-
return 0
|
|
1936
|
-
fi
|
|
1937
|
-
}
|
|
1938
|
-
complete -F ${fn} ${quoted}
|
|
1939
|
-
`;
|
|
2077
|
+
return { ...stdinData, ...cliKwargsNonNull };
|
|
2078
|
+
}
|
|
2079
|
+
return cliKwargsNonNull;
|
|
1940
2080
|
}
|
|
1941
|
-
function
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
const
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
"
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
'describe:Show module metadata and schema'
|
|
1964
|
-
'completion:Generate shell completion script'
|
|
1965
|
-
'init:Scaffolding commands'
|
|
1966
|
-
'man:Generate man page'
|
|
1967
|
-
)
|
|
1968
|
-
|
|
1969
|
-
_arguments -C \\
|
|
1970
|
-
'1:command:->command' \\
|
|
1971
|
-
'*::arg:->args'
|
|
1972
|
-
|
|
1973
|
-
case "$state" in
|
|
1974
|
-
command)
|
|
1975
|
-
_describe -t commands '${progName} commands' commands
|
|
1976
|
-
local -a groups_and_top
|
|
1977
|
-
groups_and_top=($(${groupsAndTopCmd}))
|
|
1978
|
-
compadd -a groups_and_top
|
|
1979
|
-
;;
|
|
1980
|
-
args)
|
|
1981
|
-
case "\${words[1]}" in
|
|
1982
|
-
exec)
|
|
1983
|
-
local modules
|
|
1984
|
-
modules=($(${moduleListCmd}))
|
|
1985
|
-
compadd -a modules
|
|
1986
|
-
;;
|
|
1987
|
-
*)
|
|
1988
|
-
export _APCORE_GRP="\${words[1]}"
|
|
1989
|
-
local -a group_cmds
|
|
1990
|
-
group_cmds=($(${groupCmdsCmd}))
|
|
1991
|
-
compadd -a group_cmds
|
|
1992
|
-
;;
|
|
1993
|
-
esac
|
|
1994
|
-
;;
|
|
1995
|
-
esac
|
|
2081
|
+
function readStdin() {
|
|
2082
|
+
return new Promise((resolve3, reject) => {
|
|
2083
|
+
const chunks = [];
|
|
2084
|
+
const onData = (chunk) => chunks.push(chunk);
|
|
2085
|
+
const onEnd = () => {
|
|
2086
|
+
cleanup();
|
|
2087
|
+
resolve3(Buffer.concat(chunks).toString("utf-8"));
|
|
2088
|
+
};
|
|
2089
|
+
const onError = (err) => {
|
|
2090
|
+
cleanup();
|
|
2091
|
+
reject(err);
|
|
2092
|
+
};
|
|
2093
|
+
const cleanup = () => {
|
|
2094
|
+
process.stdin.removeListener("data", onData);
|
|
2095
|
+
process.stdin.removeListener("end", onEnd);
|
|
2096
|
+
process.stdin.removeListener("error", onError);
|
|
2097
|
+
};
|
|
2098
|
+
process.stdin.on("data", onData);
|
|
2099
|
+
process.stdin.on("end", onEnd);
|
|
2100
|
+
process.stdin.on("error", onError);
|
|
2101
|
+
process.stdin.resume();
|
|
2102
|
+
});
|
|
1996
2103
|
}
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2104
|
+
function reconvertEnumValues(kwargs, options) {
|
|
2105
|
+
const result = { ...kwargs };
|
|
2106
|
+
for (const opt of options) {
|
|
2107
|
+
if (!opt.enumOriginalTypes) continue;
|
|
2108
|
+
const paramName = opt.name;
|
|
2109
|
+
if (!(paramName in result) || result[paramName] === null || result[paramName] === void 0) {
|
|
2110
|
+
continue;
|
|
2111
|
+
}
|
|
2112
|
+
const strVal = String(result[paramName]);
|
|
2113
|
+
const origType = opt.enumOriginalTypes[strVal];
|
|
2114
|
+
if (origType === "int") {
|
|
2115
|
+
result[paramName] = parseInt(strVal, 10);
|
|
2116
|
+
} else if (origType === "float") {
|
|
2117
|
+
result[paramName] = parseFloat(strVal);
|
|
2118
|
+
} else if (origType === "bool") {
|
|
2119
|
+
result[paramName] = strVal.toLowerCase() === "true";
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
return result;
|
|
2000
2123
|
}
|
|
2001
|
-
function generateFishCompletion(progName) {
|
|
2002
|
-
const quoted = shellQuote(progName);
|
|
2003
|
-
const moduleListCmd = `${quoted} list --format json 2>/dev/null | node -e \\"process.stdin.on('data',d=>{JSON.parse(d).forEach(m=>console.log(m.id))})\\" 2>/dev/null`;
|
|
2004
|
-
const groupsAndTopCmd = `${quoted} list --format json 2>/dev/null | node -e \\"const m=require('fs').readFileSync('/dev/stdin','utf8');const ids=JSON.parse(m).map(x=>x.id);const g=new Set(),t=[];ids.forEach(i=>{if(i.includes('.'))g.add(i.split('.')[0]);else t.push(i)});console.log([...g].sort().concat(t.sort()).join('\\\\n'))\\" 2>/dev/null`;
|
|
2005
|
-
return `# Fish completions for ${progName}
|
|
2006
|
-
complete -c ${quoted} -n "__fish_use_subcommand" -a list -d "List available modules"
|
|
2007
|
-
complete -c ${quoted} -n "__fish_use_subcommand" -a describe -d "Show module metadata and schema"
|
|
2008
|
-
complete -c ${quoted} -n "__fish_use_subcommand" -a completion -d "Generate shell completion script"
|
|
2009
|
-
complete -c ${quoted} -n "__fish_use_subcommand" -a init -d "Scaffolding commands"
|
|
2010
|
-
complete -c ${quoted} -n "__fish_use_subcommand" -a man -d "Generate man page"
|
|
2011
|
-
complete -c ${quoted} -n "__fish_use_subcommand" -a "(${groupsAndTopCmd})" -d "Module group"
|
|
2012
|
-
|
|
2013
|
-
complete -c ${quoted} -n "__fish_seen_subcommand_from exec" -a "(${moduleListCmd})"
|
|
2014
2124
|
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2125
|
+
// src/cli.ts
|
|
2126
|
+
init_esm_shims();
|
|
2127
|
+
import { Command as Command3 } from "commander";
|
|
2128
|
+
var BUILTIN_COMMANDS = ["completion", "describe", "exec", "init", "list", "man"];
|
|
2129
|
+
var LazyModuleGroup = class {
|
|
2130
|
+
registry;
|
|
2131
|
+
executor;
|
|
2132
|
+
helpTextMaxLength;
|
|
2133
|
+
commandCache = /* @__PURE__ */ new Map();
|
|
2134
|
+
/** alias -> canonical module_id (populated lazily) */
|
|
2135
|
+
aliasMap = /* @__PURE__ */ new Map();
|
|
2136
|
+
/** module_id -> descriptor cache (populated during alias map build) */
|
|
2137
|
+
descriptorCache = /* @__PURE__ */ new Map();
|
|
2138
|
+
aliasMapBuilt = false;
|
|
2139
|
+
constructor(registry, executor, helpTextMaxLength = 1e3) {
|
|
2140
|
+
this.registry = registry;
|
|
2141
|
+
this.executor = executor;
|
|
2142
|
+
this.helpTextMaxLength = helpTextMaxLength;
|
|
2032
2143
|
}
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2144
|
+
/**
|
|
2145
|
+
* Build alias->module_id map from display overlay metadata.
|
|
2146
|
+
*/
|
|
2147
|
+
buildAliasMap() {
|
|
2148
|
+
if (this.aliasMapBuilt) {
|
|
2149
|
+
return;
|
|
2150
|
+
}
|
|
2151
|
+
try {
|
|
2152
|
+
for (const descriptor of this.registry.listModules()) {
|
|
2153
|
+
const moduleId = descriptor.id;
|
|
2154
|
+
this.descriptorCache.set(moduleId, descriptor);
|
|
2155
|
+
const display = getDisplay(descriptor);
|
|
2156
|
+
const cliDisplay = display.cli && typeof display.cli === "object" && !Array.isArray(display.cli) ? display.cli : {};
|
|
2157
|
+
const cliAlias = cliDisplay.alias;
|
|
2158
|
+
if (cliAlias && cliAlias !== moduleId) {
|
|
2159
|
+
this.aliasMap.set(cliAlias, moduleId);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
this.aliasMapBuilt = true;
|
|
2163
|
+
} catch {
|
|
2164
|
+
warn("Failed to build alias map from registry");
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* List all available command names from the Registry.
|
|
2169
|
+
*/
|
|
2170
|
+
listCommands() {
|
|
2171
|
+
this.buildAliasMap();
|
|
2172
|
+
const reverse = /* @__PURE__ */ new Map();
|
|
2173
|
+
for (const [alias, moduleId] of this.aliasMap) {
|
|
2174
|
+
reverse.set(moduleId, alias);
|
|
2175
|
+
}
|
|
2176
|
+
const moduleIds = this.registry.listModules().map((m) => m.id);
|
|
2177
|
+
const names = moduleIds.map((mid) => reverse.get(mid) ?? mid);
|
|
2178
|
+
return [...new Set(names)].sort();
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Get or lazily build a Commander Command for the given module.
|
|
2182
|
+
*/
|
|
2183
|
+
getCommand(cmdName) {
|
|
2184
|
+
if (this.commandCache.has(cmdName)) {
|
|
2185
|
+
return this.commandCache.get(cmdName);
|
|
2186
|
+
}
|
|
2187
|
+
this.buildAliasMap();
|
|
2188
|
+
const moduleId = this.aliasMap.get(cmdName) ?? cmdName;
|
|
2189
|
+
let moduleDef = this.descriptorCache.get(moduleId);
|
|
2190
|
+
if (!moduleDef) {
|
|
2191
|
+
moduleDef = this.registry.getModule(moduleId) ?? void 0;
|
|
2192
|
+
}
|
|
2193
|
+
if (!moduleDef) {
|
|
2194
|
+
return null;
|
|
2195
|
+
}
|
|
2196
|
+
const cmd = buildModuleCommand(moduleDef, this.executor, this.helpTextMaxLength, cmdName);
|
|
2197
|
+
this.commandCache.set(cmdName, cmd);
|
|
2198
|
+
return cmd;
|
|
2199
|
+
}
|
|
2200
|
+
};
|
|
2201
|
+
var LazyGroup = class {
|
|
2202
|
+
members;
|
|
2203
|
+
_executor;
|
|
2204
|
+
_helpTextMaxLength;
|
|
2205
|
+
_cmdCache = /* @__PURE__ */ new Map();
|
|
2206
|
+
command;
|
|
2207
|
+
constructor(members, executor, name, helpTextMaxLength = 1e3) {
|
|
2208
|
+
this.members = members;
|
|
2209
|
+
this._executor = executor;
|
|
2210
|
+
this._helpTextMaxLength = helpTextMaxLength;
|
|
2211
|
+
this.command = new Command3(name).description(`${name} commands`);
|
|
2212
|
+
for (const [cmdName, [, descriptor]] of this.members) {
|
|
2213
|
+
const cmd = buildModuleCommand(
|
|
2214
|
+
descriptor,
|
|
2215
|
+
this._executor,
|
|
2216
|
+
this._helpTextMaxLength,
|
|
2217
|
+
cmdName
|
|
2218
|
+
);
|
|
2219
|
+
this._cmdCache.set(cmdName, cmd);
|
|
2220
|
+
this.command.addCommand(cmd);
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
listCommands() {
|
|
2224
|
+
return [...this.members.keys()].sort();
|
|
2225
|
+
}
|
|
2226
|
+
getCommand(cmdName) {
|
|
2227
|
+
if (this._cmdCache.has(cmdName)) {
|
|
2228
|
+
return this._cmdCache.get(cmdName);
|
|
2229
|
+
}
|
|
2230
|
+
const entry = this.members.get(cmdName);
|
|
2231
|
+
if (!entry) {
|
|
2232
|
+
return null;
|
|
2233
|
+
}
|
|
2234
|
+
const [, descriptor] = entry;
|
|
2235
|
+
const cmd = buildModuleCommand(
|
|
2236
|
+
descriptor,
|
|
2237
|
+
this._executor,
|
|
2238
|
+
this._helpTextMaxLength,
|
|
2239
|
+
cmdName
|
|
2240
|
+
);
|
|
2241
|
+
this._cmdCache.set(cmdName, cmd);
|
|
2242
|
+
return cmd;
|
|
2243
|
+
}
|
|
2244
|
+
};
|
|
2245
|
+
var GroupedModuleGroup = class _GroupedModuleGroup extends LazyModuleGroup {
|
|
2246
|
+
/** groupName -> { cmdName -> [moduleId, descriptor] } */
|
|
2247
|
+
groupMap = /* @__PURE__ */ new Map();
|
|
2248
|
+
/** cmdName -> [moduleId, descriptor] for top-level (ungrouped) modules */
|
|
2249
|
+
topLevelModules = /* @__PURE__ */ new Map();
|
|
2250
|
+
/** Cached LazyGroup instances */
|
|
2251
|
+
groupCache = /* @__PURE__ */ new Map();
|
|
2252
|
+
groupMapBuilt = false;
|
|
2253
|
+
/**
|
|
2254
|
+
* Determine (groupName | null, commandName) for a module from its display overlay.
|
|
2255
|
+
*/
|
|
2256
|
+
static resolveGroup(moduleId, descriptor) {
|
|
2257
|
+
if (!moduleId) {
|
|
2258
|
+
warn("Empty module_id encountered in resolveGroup");
|
|
2259
|
+
return [null, ""];
|
|
2260
|
+
}
|
|
2261
|
+
const display = getDisplay(descriptor);
|
|
2262
|
+
const cliDisplay = display.cli && typeof display.cli === "object" && !Array.isArray(display.cli) ? display.cli : {};
|
|
2263
|
+
const explicitGroup = cliDisplay.group;
|
|
2264
|
+
if (typeof explicitGroup === "string" && explicitGroup !== "") {
|
|
2265
|
+
return [explicitGroup, cliDisplay.alias ?? moduleId];
|
|
2266
|
+
}
|
|
2267
|
+
if (explicitGroup === "") {
|
|
2268
|
+
return [null, cliDisplay.alias ?? moduleId];
|
|
2269
|
+
}
|
|
2270
|
+
const cliName = cliDisplay.alias ?? moduleId;
|
|
2271
|
+
if (cliName.includes(".")) {
|
|
2272
|
+
const dotIdx = cliName.indexOf(".");
|
|
2273
|
+
const group = cliName.substring(0, dotIdx);
|
|
2274
|
+
const cmd = cliName.substring(dotIdx + 1);
|
|
2275
|
+
return [group, cmd];
|
|
2276
|
+
}
|
|
2277
|
+
return [null, cliName];
|
|
2278
|
+
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Build the group map from registry modules.
|
|
2281
|
+
*/
|
|
2282
|
+
buildGroupMap() {
|
|
2283
|
+
if (this.groupMapBuilt) {
|
|
2284
|
+
return;
|
|
2044
2285
|
}
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2286
|
+
try {
|
|
2287
|
+
this.buildAliasMap();
|
|
2288
|
+
for (const descriptor of this.registry.listModules()) {
|
|
2289
|
+
const moduleId = descriptor.id;
|
|
2290
|
+
const cached = this.descriptorCache.get(moduleId);
|
|
2291
|
+
if (!cached) {
|
|
2292
|
+
continue;
|
|
2293
|
+
}
|
|
2294
|
+
const [group, cmd] = _GroupedModuleGroup.resolveGroup(moduleId, cached);
|
|
2295
|
+
if (group === null) {
|
|
2296
|
+
this.topLevelModules.set(cmd, [moduleId, cached]);
|
|
2297
|
+
} else if (!/^[a-z][a-z0-9_-]*$/.test(group)) {
|
|
2298
|
+
warn(
|
|
2299
|
+
`Module '${moduleId}': group name '${group}' is not shell-safe \u2014 treating as top-level.`
|
|
2300
|
+
);
|
|
2301
|
+
this.topLevelModules.set(cmd, [moduleId, cached]);
|
|
2302
|
+
} else {
|
|
2303
|
+
if (!this.groupMap.has(group)) {
|
|
2304
|
+
this.groupMap.set(group, /* @__PURE__ */ new Map());
|
|
2305
|
+
}
|
|
2306
|
+
this.groupMap.get(group).set(cmd, [moduleId, cached]);
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
for (const groupName of this.groupMap.keys()) {
|
|
2310
|
+
if (BUILTIN_COMMANDS.includes(groupName)) {
|
|
2311
|
+
warn(
|
|
2312
|
+
`Group name '${groupName}' collides with a built-in command and will be ignored`
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
this.groupMapBuilt = true;
|
|
2317
|
+
} catch {
|
|
2318
|
+
warn("Failed to build group map");
|
|
2052
2319
|
}
|
|
2053
2320
|
}
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
const sections = [];
|
|
2062
|
-
sections.push(`.TH "${title}" "1" "${today}" "${pkgLabel}" "${manualLabel}"`);
|
|
2063
|
-
sections.push(".SH NAME");
|
|
2064
|
-
const desc = command?.description() ?? commandName;
|
|
2065
|
-
const nameDesc = desc.split("\n")[0].replace(/\.$/, "");
|
|
2066
|
-
sections.push(`${progName}-${commandName} \\- ${nameDesc}`);
|
|
2067
|
-
sections.push(".SH SYNOPSIS");
|
|
2068
|
-
sections.push(buildSynopsis(command, progName, commandName));
|
|
2069
|
-
if (command?.description()) {
|
|
2070
|
-
sections.push(".SH DESCRIPTION");
|
|
2071
|
-
sections.push(
|
|
2072
|
-
command.description().replace(/\\/g, "\\\\").replace(/-/g, "\\-")
|
|
2321
|
+
/**
|
|
2322
|
+
* List all available command names: builtins + group names + top-level module names.
|
|
2323
|
+
*/
|
|
2324
|
+
listCommands() {
|
|
2325
|
+
this.buildGroupMap();
|
|
2326
|
+
const groupNames = [...this.groupMap.keys()].filter(
|
|
2327
|
+
(g) => !BUILTIN_COMMANDS.includes(g)
|
|
2073
2328
|
);
|
|
2329
|
+
const topNames = [...this.topLevelModules.keys()];
|
|
2330
|
+
return [.../* @__PURE__ */ new Set([...BUILTIN_COMMANDS, ...groupNames, ...topNames])].sort();
|
|
2074
2331
|
}
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2332
|
+
/**
|
|
2333
|
+
* Get a command by name: check builtins -> group cache -> group map -> top-level modules.
|
|
2334
|
+
*/
|
|
2335
|
+
getCommand(cmdName) {
|
|
2336
|
+
this.buildGroupMap();
|
|
2337
|
+
if (this.groupCache.has(cmdName)) {
|
|
2338
|
+
return this.groupCache.get(cmdName).command;
|
|
2339
|
+
}
|
|
2340
|
+
if (this.groupMap.has(cmdName)) {
|
|
2341
|
+
const lazyGrp = new LazyGroup(
|
|
2342
|
+
this.groupMap.get(cmdName),
|
|
2343
|
+
this.executor,
|
|
2344
|
+
cmdName,
|
|
2345
|
+
this.helpTextMaxLength
|
|
2346
|
+
);
|
|
2347
|
+
this.groupCache.set(cmdName, lazyGrp);
|
|
2348
|
+
return lazyGrp.command;
|
|
2349
|
+
}
|
|
2350
|
+
if (this.topLevelModules.has(cmdName)) {
|
|
2351
|
+
if (this.commandCache.has(cmdName)) {
|
|
2352
|
+
return this.commandCache.get(cmdName);
|
|
2090
2353
|
}
|
|
2354
|
+
const [, descriptor] = this.topLevelModules.get(cmdName);
|
|
2355
|
+
const cmd = buildModuleCommand(
|
|
2356
|
+
descriptor,
|
|
2357
|
+
this.executor,
|
|
2358
|
+
this.helpTextMaxLength,
|
|
2359
|
+
cmdName
|
|
2360
|
+
);
|
|
2361
|
+
this.commandCache.set(cmdName, cmd);
|
|
2362
|
+
return cmd;
|
|
2091
2363
|
}
|
|
2364
|
+
return null;
|
|
2092
2365
|
}
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
sections.push(
|
|
2097
|
-
"Path to the apcore extensions directory. Overrides the default \\fI./extensions\\fR."
|
|
2098
|
-
);
|
|
2099
|
-
sections.push(".TP");
|
|
2100
|
-
sections.push("\\fBAPCORE_CLI_AUTO_APPROVE\\fR");
|
|
2101
|
-
sections.push(
|
|
2102
|
-
"Set to \\fB1\\fR to bypass approval prompts for modules that require human-in-the-loop confirmation."
|
|
2103
|
-
);
|
|
2104
|
-
sections.push(".TP");
|
|
2105
|
-
sections.push("\\fBAPCORE_CLI_LOGGING_LEVEL\\fR");
|
|
2106
|
-
sections.push(
|
|
2107
|
-
"CLI-specific logging verbosity. One of: DEBUG, INFO, WARNING, ERROR. Takes priority over \\fBAPCORE_LOGGING_LEVEL\\fR. Default: WARNING."
|
|
2108
|
-
);
|
|
2109
|
-
sections.push(".TP");
|
|
2110
|
-
sections.push("\\fBAPCORE_LOGGING_LEVEL\\fR");
|
|
2111
|
-
sections.push(
|
|
2112
|
-
"Global apcore logging verbosity. One of: DEBUG, INFO, WARNING, ERROR. Used as fallback when \\fBAPCORE_CLI_LOGGING_LEVEL\\fR is not set. Default: WARNING."
|
|
2113
|
-
);
|
|
2114
|
-
sections.push(".TP");
|
|
2115
|
-
sections.push("\\fBAPCORE_AUTH_API_KEY\\fR");
|
|
2116
|
-
sections.push(
|
|
2117
|
-
"API key for authenticating with the apcore registry."
|
|
2118
|
-
);
|
|
2119
|
-
sections.push(".SH EXIT CODES");
|
|
2120
|
-
const exitCodes = [
|
|
2121
|
-
["0", "Success."],
|
|
2122
|
-
["1", "Module execution error."],
|
|
2123
|
-
["2", "Invalid CLI input or missing argument."],
|
|
2124
|
-
["44", "Module not found, disabled, or failed to load."],
|
|
2125
|
-
["45", "Input failed JSON Schema validation."],
|
|
2126
|
-
[
|
|
2127
|
-
"46",
|
|
2128
|
-
"Approval denied, timed out, or no interactive terminal available."
|
|
2129
|
-
],
|
|
2130
|
-
[
|
|
2131
|
-
"47",
|
|
2132
|
-
"Configuration error (extensions directory not found or unreadable)."
|
|
2133
|
-
],
|
|
2134
|
-
["48", "Schema contains a circular \\fB$ref\\fR."],
|
|
2135
|
-
["77", "ACL denied \u2014 insufficient permissions for this module."],
|
|
2136
|
-
["130", "Execution cancelled by user (SIGINT / Ctrl\\-C)."]
|
|
2137
|
-
];
|
|
2138
|
-
for (const [code, meaning] of exitCodes) {
|
|
2139
|
-
sections.push(`.TP
|
|
2140
|
-
\\fB${code}\\fR
|
|
2141
|
-
${meaning}`);
|
|
2366
|
+
/** Expose groupMap for testing. */
|
|
2367
|
+
getGroupMap() {
|
|
2368
|
+
return this.groupMap;
|
|
2142
2369
|
}
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2370
|
+
/** Expose topLevelModules for testing. */
|
|
2371
|
+
getTopLevelModules() {
|
|
2372
|
+
return this.topLevelModules;
|
|
2373
|
+
}
|
|
2374
|
+
/** Expose groupMapBuilt for testing. */
|
|
2375
|
+
isGroupMapBuilt() {
|
|
2376
|
+
return this.groupMapBuilt;
|
|
2377
|
+
}
|
|
2378
|
+
};
|
|
2379
|
+
|
|
2380
|
+
// src/discovery.ts
|
|
2381
|
+
init_esm_shims();
|
|
2382
|
+
init_errors();
|
|
2383
|
+
import { Command as Command4 } from "commander";
|
|
2384
|
+
var TAG_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
2385
|
+
function validateTag(tag) {
|
|
2386
|
+
if (!TAG_PATTERN.test(tag)) {
|
|
2387
|
+
process.stderr.write(
|
|
2388
|
+
`Error: Invalid tag format: '${tag}'. Tags must match [a-z][a-z0-9_-]*.
|
|
2162
2389
|
`
|
|
2163
|
-
|
|
2164
|
-
|
|
2390
|
+
);
|
|
2391
|
+
process.exit(EXIT_CODES.INVALID_CLI_INPUT);
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
function collectTag(value, previous) {
|
|
2395
|
+
return previous.concat([value]);
|
|
2396
|
+
}
|
|
2397
|
+
function registerDiscoveryCommands(cli, registry) {
|
|
2398
|
+
const listCmd = new Command4("list").description("List available modules in the registry.").option("--tag <tag>", "Filter modules by tag (AND logic). Repeatable.", collectTag, []).option("--format <format>", "Output format.", void 0).action((opts) => {
|
|
2399
|
+
for (const t of opts.tag) {
|
|
2400
|
+
validateTag(t);
|
|
2165
2401
|
}
|
|
2166
|
-
const
|
|
2167
|
-
const
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2402
|
+
const modules = [];
|
|
2403
|
+
for (const m of registry.listModules()) {
|
|
2404
|
+
modules.push(m);
|
|
2405
|
+
}
|
|
2406
|
+
let filtered = modules;
|
|
2407
|
+
if (opts.tag.length > 0) {
|
|
2408
|
+
const filterTags = new Set(opts.tag);
|
|
2409
|
+
filtered = modules.filter((m) => {
|
|
2410
|
+
const mTags = m.tags ?? [];
|
|
2411
|
+
return [...filterTags].every((t) => mTags.includes(t));
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2414
|
+
const fmt = resolveFormat(opts.format);
|
|
2415
|
+
formatModuleList(filtered, fmt, opts.tag.length > 0 ? opts.tag : void 0);
|
|
2173
2416
|
});
|
|
2174
|
-
cli.addCommand(
|
|
2175
|
-
const
|
|
2176
|
-
|
|
2177
|
-
const
|
|
2178
|
-
if (!
|
|
2417
|
+
cli.addCommand(listCmd);
|
|
2418
|
+
const describeCmd = new Command4("describe").description("Show metadata, schema, and annotations for a module.").argument("<module-id>", "Module ID to describe").option("--format <format>", "Output format.", void 0).action((moduleId, opts) => {
|
|
2419
|
+
validateModuleId(moduleId);
|
|
2420
|
+
const moduleDef = registry.getModule(moduleId);
|
|
2421
|
+
if (!moduleDef) {
|
|
2179
2422
|
process.stderr.write(
|
|
2180
|
-
`Error:
|
|
2423
|
+
`Error: Module '${moduleId}' not found.
|
|
2181
2424
|
`
|
|
2182
2425
|
);
|
|
2183
|
-
process.exit(EXIT_CODES.
|
|
2426
|
+
process.exit(EXIT_CODES.MODULE_NOT_FOUND);
|
|
2184
2427
|
}
|
|
2185
|
-
const
|
|
2186
|
-
|
|
2187
|
-
process.stdout.write(roff);
|
|
2428
|
+
const fmt = resolveFormat(opts.format);
|
|
2429
|
+
formatModuleDetail(moduleDef, fmt);
|
|
2188
2430
|
});
|
|
2189
|
-
cli.addCommand(
|
|
2431
|
+
cli.addCommand(describeCmd);
|
|
2190
2432
|
}
|
|
2191
2433
|
|
|
2192
2434
|
// src/index.ts
|
|
@@ -2213,10 +2455,13 @@ export {
|
|
|
2213
2455
|
SchemaValidationError,
|
|
2214
2456
|
applyToolkitIntegration,
|
|
2215
2457
|
buildModuleCommand,
|
|
2458
|
+
buildProgramManPage,
|
|
2216
2459
|
checkApproval,
|
|
2217
2460
|
collectInput,
|
|
2461
|
+
configureManHelp,
|
|
2218
2462
|
createCli,
|
|
2219
2463
|
debug,
|
|
2464
|
+
docsUrl,
|
|
2220
2465
|
error,
|
|
2221
2466
|
exitCodeForError,
|
|
2222
2467
|
extractHelp,
|
|
@@ -2231,6 +2476,7 @@ export {
|
|
|
2231
2476
|
main,
|
|
2232
2477
|
mapType,
|
|
2233
2478
|
reconvertEnumValues,
|
|
2479
|
+
registerConfigNamespace,
|
|
2234
2480
|
registerDiscoveryCommands,
|
|
2235
2481
|
registerInitCommand,
|
|
2236
2482
|
registerShellCommands,
|
|
@@ -2238,9 +2484,12 @@ export {
|
|
|
2238
2484
|
resolveRefs,
|
|
2239
2485
|
schemaToCliOptions,
|
|
2240
2486
|
setAuditLogger,
|
|
2487
|
+
setDocsUrl,
|
|
2241
2488
|
setLogLevel,
|
|
2489
|
+
setVerboseHelp,
|
|
2242
2490
|
truncate,
|
|
2243
2491
|
validateModuleId,
|
|
2492
|
+
verboseHelp,
|
|
2244
2493
|
warn
|
|
2245
2494
|
};
|
|
2246
2495
|
//# sourceMappingURL=index.js.map
|