@roarkanalytics/cli 0.1.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.
Files changed (99) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +225 -0
  3. package/bin.d.ts +2 -0
  4. package/bin.js +14 -0
  5. package/commands.d.ts +5 -0
  6. package/commands.js +3553 -0
  7. package/completions.d.ts +1 -0
  8. package/completions.js +13 -0
  9. package/index.d.ts +6 -0
  10. package/index.js +26 -0
  11. package/man/roark-agent-create.1 +99 -0
  12. package/man/roark-agent-endpoint-create.1 +108 -0
  13. package/man/roark-agent-endpoint-get.1 +93 -0
  14. package/man/roark-agent-endpoint-list.1 +102 -0
  15. package/man/roark-agent-endpoint-update.1 +103 -0
  16. package/man/roark-agent-get.1 +93 -0
  17. package/man/roark-agent-list.1 +99 -0
  18. package/man/roark-agent-update.1 +100 -0
  19. package/man/roark-call-create.1 +150 -0
  20. package/man/roark-call-get.1 +93 -0
  21. package/man/roark-call-list.1 +111 -0
  22. package/man/roark-call-metric-list.1 +100 -0
  23. package/man/roark-call-sentiment-run-list.1 +93 -0
  24. package/man/roark-call-transcript-get.1 +97 -0
  25. package/man/roark-config-apply.1 +96 -0
  26. package/man/roark-config-diff.1 +96 -0
  27. package/man/roark-customer-flow-create.1 +97 -0
  28. package/man/roark-customer-flow-delete.1 +93 -0
  29. package/man/roark-customer-flow-edge-case-create.1 +112 -0
  30. package/man/roark-customer-flow-edge-case-delete.1 +96 -0
  31. package/man/roark-customer-flow-edge-case-promote.1 +96 -0
  32. package/man/roark-customer-flow-edge-case-update.1 +118 -0
  33. package/man/roark-customer-flow-get.1 +93 -0
  34. package/man/roark-customer-flow-graph-replace.1 +100 -0
  35. package/man/roark-customer-flow-happy-path-update.1 +115 -0
  36. package/man/roark-customer-flow-list.1 +105 -0
  37. package/man/roark-customer-flow-update.1 +109 -0
  38. package/man/roark-health.1 +89 -0
  39. package/man/roark-http-request-definition-create.1 +108 -0
  40. package/man/roark-http-request-definition-get.1 +93 -0
  41. package/man/roark-http-request-definition-list.1 +96 -0
  42. package/man/roark-http-request-definition-update.1 +109 -0
  43. package/man/roark-metric-collection-job-create.1 +99 -0
  44. package/man/roark-metric-collection-job-get.1 +93 -0
  45. package/man/roark-metric-collection-job-list.1 +99 -0
  46. package/man/roark-metric-definition-create.1 +100 -0
  47. package/man/roark-metric-definition-list.1 +89 -0
  48. package/man/roark-metric-policy-create.1 +105 -0
  49. package/man/roark-metric-policy-delete.1 +93 -0
  50. package/man/roark-metric-policy-get.1 +93 -0
  51. package/man/roark-metric-policy-list.1 +99 -0
  52. package/man/roark-metric-policy-update.1 +106 -0
  53. package/man/roark-simulation-environment-get.1 +93 -0
  54. package/man/roark-simulation-environment-list.1 +96 -0
  55. package/man/roark-simulation-job-get.1 +93 -0
  56. package/man/roark-simulation-job-lookup.1 +96 -0
  57. package/man/roark-simulation-persona-create.1 +156 -0
  58. package/man/roark-simulation-persona-get.1 +93 -0
  59. package/man/roark-simulation-persona-list.1 +99 -0
  60. package/man/roark-simulation-persona-update.1 +160 -0
  61. package/man/roark-simulation-plan-create.1 +138 -0
  62. package/man/roark-simulation-plan-delete.1 +93 -0
  63. package/man/roark-simulation-plan-get.1 +93 -0
  64. package/man/roark-simulation-plan-job-get.1 +93 -0
  65. package/man/roark-simulation-plan-job-list.1 +108 -0
  66. package/man/roark-simulation-plan-job-start.1 +97 -0
  67. package/man/roark-simulation-plan-list.1 +102 -0
  68. package/man/roark-simulation-plan-update.1 +142 -0
  69. package/man/roark-simulation-run.1 +97 -0
  70. package/man/roark-webhook-create.1 +102 -0
  71. package/man/roark-webhook-delete.1 +93 -0
  72. package/man/roark-webhook-get.1 +93 -0
  73. package/man/roark-webhook-list.1 +96 -0
  74. package/man/roark.1 +287 -0
  75. package/package.json +102 -0
  76. package/runtime/commands/api.d.ts +26 -0
  77. package/runtime/commands/api.js +85 -0
  78. package/runtime/commands/auth.d.ts +9 -0
  79. package/runtime/commands/auth.js +111 -0
  80. package/runtime/commands/completion.d.ts +9 -0
  81. package/runtime/commands/completion.js +42 -0
  82. package/runtime/commands/config.d.ts +15 -0
  83. package/runtime/commands/config.js +125 -0
  84. package/runtime/config.d.ts +65 -0
  85. package/runtime/config.js +163 -0
  86. package/runtime/confirm.d.ts +16 -0
  87. package/runtime/confirm.js +34 -0
  88. package/runtime/errors.d.ts +45 -0
  89. package/runtime/errors.js +91 -0
  90. package/runtime/input.d.ts +52 -0
  91. package/runtime/input.js +211 -0
  92. package/runtime/output.d.ts +41 -0
  93. package/runtime/output.js +90 -0
  94. package/runtime/program.d.ts +45 -0
  95. package/runtime/program.js +305 -0
  96. package/runtime/types.d.ts +53 -0
  97. package/runtime/types.js +10 -0
  98. package/version.d.ts +1 -0
  99. package/version.js +8 -0
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ /**
3
+ * Builds the whole command tree from the generated table.
4
+ *
5
+ * Nothing here names an endpoint. Every command, positional and flag comes from
6
+ * `commands.ts`, so a new API operation reaches the CLI as a data change.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.run = exports.createProgram = exports.resolveOutput = exports.assertBaseUrlIsTrusted = void 0;
13
+ const commander_1 = require("commander");
14
+ const sdk_1 = __importDefault(require("@roarkanalytics/sdk"));
15
+ const api_1 = require("./commands/api");
16
+ const auth_1 = require("./commands/auth");
17
+ const config_1 = require("./commands/config");
18
+ const completion_1 = require("./commands/completion");
19
+ const confirm_1 = require("./confirm");
20
+ const config_2 = require("./config");
21
+ const errors_1 = require("./errors");
22
+ const input_1 = require("./input");
23
+ const output_1 = require("./output");
24
+ /** Verbs whose effect a user cannot undo, so they get a confirmation prompt. */
25
+ const DESTRUCTIVE_VERBS = new Set(['delete']);
26
+ const isDestructive = (command) => DESTRUCTIVE_VERBS.has(command.commandPath.at(-1) ?? '');
27
+ /**
28
+ * Global flags are declared on every leaf as well as the root so they can be
29
+ * written on either side of the verb. Commander does not inherit options down
30
+ * the tree, and `roark call list --json` is what a user will type.
31
+ *
32
+ * The execution flags are added per command rather than everywhere: a `--data`
33
+ * on a GET with no body, or a `--yes` on a command that never prompts, is help
34
+ * text that describes something the command will not do.
35
+ */
36
+ const addGlobalOptions = (command, extra) => {
37
+ command
38
+ .option('--base-url <url>', 'API base URL')
39
+ .option('--token <token>', 'bearer token (prefer ROARK_API_BEARER_TOKEN or `auth login`)')
40
+ .option('--timeout <ms>', 'request timeout in milliseconds')
41
+ .option('--max-retries <count>', 'retries for retryable failures')
42
+ .addOption(new commander_1.Option('--format <format>', 'output format').choices(output_1.OUTPUT_FORMATS).default('auto'))
43
+ .option('--json', 'shorthand for --format json')
44
+ .option('--no-color', 'disable colour')
45
+ .option('-q, --quiet', 'suppress non-essential output')
46
+ .option('--allow-project-base-url', `send your credential to a base URL set by a ${config_2.PROJECT_FILE}`);
47
+ if (extra.body) {
48
+ command.option('--data <json>', 'request body as JSON, or @file to read one (@- for stdin)');
49
+ }
50
+ if (extra.confirmation) {
51
+ command
52
+ .option('-y, --yes', 'skip confirmation prompts')
53
+ .option('--no-input', 'never prompt; fail instead');
54
+ }
55
+ return command;
56
+ };
57
+ /**
58
+ * Refuses the one combination that would post a secret to a host the caller did
59
+ * not choose. Nothing is sent first: this throws before the client exists.
60
+ */
61
+ const assertBaseUrlIsTrusted = (options, resolved) => {
62
+ if (options.allowProjectBaseUrl === true || (0, config_2.allowProjectBaseUrlFromEnvironment)())
63
+ return;
64
+ const redirect = (0, config_2.unsafeBaseUrlRedirect)(resolved);
65
+ if (redirect === undefined)
66
+ return;
67
+ const origin = redirect.credentialFrom === 'environment' ? 'ROARK_API_BEARER_TOKEN' : (0, config_2.userConfigPath)();
68
+ throw new errors_1.UsageError([
69
+ `Refusing to send your credential to ${redirect.baseURL}.`,
70
+ '',
71
+ `${redirect.projectFile} sets baseURL, and a ${config_2.PROJECT_FILE} is not necessarily yours: it`,
72
+ `arrives with a clone. The credential that would be sent came from ${origin}.`,
73
+ '',
74
+ 'Pass --allow-project-base-url if you trust that file, or --token to send a',
75
+ 'different credential.',
76
+ ].join('\n'));
77
+ };
78
+ exports.assertBaseUrlIsTrusted = assertBaseUrlIsTrusted;
79
+ const clientFor = (options, requiresAuth = true) => {
80
+ const overrides = {
81
+ ...(options.token === undefined ? {} : { bearerToken: options.token }),
82
+ ...(options.baseUrl === undefined ? {} : { baseURL: options.baseUrl }),
83
+ ...(options.timeout === undefined ? {} : { timeout: Number(options.timeout) }),
84
+ ...(options.maxRetries === undefined ? {} : { maxRetries: Number(options.maxRetries) }),
85
+ };
86
+ const resolved = (0, config_2.resolveConfig)(overrides);
87
+ (0, exports.assertBaseUrlIsTrusted)(options, resolved);
88
+ const config = resolved.config;
89
+ if (config.bearerToken === undefined && requiresAuth) {
90
+ throw new errors_1.AuthRequiredError('No credential found. Run `roark auth login`, set ROARK_API_BEARER_TOKEN, or pass --token.');
91
+ }
92
+ return new sdk_1.default({
93
+ // The SDK constructor rejects an absent token, so a public endpoint is given
94
+ // an empty one rather than being made to demand a credential it never sends.
95
+ bearerToken: config.bearerToken ?? '',
96
+ ...(config.baseURL === undefined ? {} : { baseURL: config.baseURL }),
97
+ ...(config.timeout === undefined ? {} : { timeout: config.timeout }),
98
+ ...(config.maxRetries === undefined ? {} : { maxRetries: config.maxRetries }),
99
+ });
100
+ };
101
+ const resolveOutput = (options) => ({
102
+ format: options.json ? 'json' : options.format ?? 'auto',
103
+ // `--no-color` sets color to false; otherwise defer to the environment.
104
+ color: options.color === false ? false : (0, output_1.supportsColor)(),
105
+ });
106
+ exports.resolveOutput = resolveOutput;
107
+ const flagSpec = (flag) => {
108
+ if (flag.valueKind === 'boolean')
109
+ return `--${flag.name}`;
110
+ return `--${flag.name} <value>`;
111
+ };
112
+ const flagDescription = (flag) => {
113
+ const parts = [];
114
+ if (flag.description)
115
+ parts.push(flag.description.replace(/\s+/g, ' ').trim());
116
+ if (flag.enumValues && flag.enumValues.length > 0) {
117
+ parts.push(`(one of: ${flag.enumValues.join(', ')})`);
118
+ }
119
+ if (flag.repeatable)
120
+ parts.push('(repeatable)');
121
+ if (flag.required)
122
+ parts.push('(required)');
123
+ return parts.join(' ');
124
+ };
125
+ /** Explains a union body, which has no flags to document. */
126
+ const variantHelp = (command, binaryName) => {
127
+ if (!command.bodyOpaque)
128
+ return '';
129
+ const name = command.commandPath.join(' ');
130
+ const lines = [
131
+ '',
132
+ 'This endpoint takes one of several request shapes, so it is supplied as JSON:',
133
+ '',
134
+ ` ${binaryName} ${name} --data '{ ... }'`,
135
+ ` ${binaryName} ${name} --data @request.json`,
136
+ ` cat request.json | ${binaryName} ${name}`,
137
+ '',
138
+ ];
139
+ if (command.bodyVariants.length > 0) {
140
+ lines.push('Accepted shapes:');
141
+ for (const variant of command.bodyVariants) {
142
+ const required = variant.required.length > 0 ? variant.required.join(', ') : 'no required fields';
143
+ lines.push(` ${variant.name} - requires ${required}`);
144
+ }
145
+ }
146
+ return lines.join('\n');
147
+ };
148
+ /** Finds or creates the parent command for a path, so groups are built once. */
149
+ const ensureGroup = (root, path, groups) => {
150
+ let parent = root;
151
+ const walked = [];
152
+ for (const segment of path) {
153
+ walked.push(segment);
154
+ const existing = parent.commands.find((child) => child.name() === segment);
155
+ if (existing) {
156
+ parent = existing;
157
+ continue;
158
+ }
159
+ const key = walked.join(' ');
160
+ const group = new commander_1.Command(segment)
161
+ .description(Object.prototype.hasOwnProperty.call(groups, key) ? groups[key] : `Commands for ${key}`)
162
+ .showHelpAfterError();
163
+ // A group with no action prints its own help rather than exiting silently.
164
+ group.action(() => {
165
+ group.outputHelp();
166
+ process.exitCode = errors_1.EXIT.usage;
167
+ });
168
+ parent.addCommand(group);
169
+ parent = group;
170
+ }
171
+ return parent;
172
+ };
173
+ const addApiCommand = (root, options, definition) => {
174
+ const parent = ensureGroup(root, definition.commandPath.slice(0, -1), options.groups);
175
+ const name = definition.commandPath.at(-1);
176
+ const command = new commander_1.Command(name)
177
+ .description(definition.summary ?? definition.description ?? '')
178
+ .showHelpAfterError();
179
+ if (definition.description && definition.description !== definition.summary) {
180
+ command.addHelpText('after', `\n${definition.description.replace(/\s+/g, ' ').trim()}`);
181
+ }
182
+ command.addHelpText('after', variantHelp(definition, options.binaryName));
183
+ command.addHelpText('after', `\n${definition.httpMethod.toUpperCase()} ${definition.httpPath}`);
184
+ for (const positional of definition.positionals) {
185
+ command.argument(`<${positional.name}>`, positional.description ?? '');
186
+ }
187
+ for (const flag of definition.flags) {
188
+ const option = new commander_1.Option(flagSpec(flag), flagDescription(flag));
189
+ if (flag.repeatable) {
190
+ option.argParser((value, previous) => [...(previous ?? []), value]);
191
+ }
192
+ command.addOption(option);
193
+ }
194
+ addGlobalOptions(command, {
195
+ body: definition.acceptsBody,
196
+ confirmation: isDestructive(definition),
197
+ });
198
+ command.action(async (...actionArgs) => {
199
+ // Commander passes positionals, then the options object, then the Command.
200
+ const positionals = actionArgs.slice(0, definition.positionals.length);
201
+ const options_ = actionArgs[definition.positionals.length];
202
+ await runApiCommand(definition, positionals, options_, options);
203
+ });
204
+ parent.addCommand(command);
205
+ };
206
+ const runApiCommand = async (definition, positionals, options, program) => {
207
+ const output = (0, exports.resolveOutput)(options);
208
+ if (isDestructive(definition)) {
209
+ await (0, confirm_1.confirm)(`Permanently delete ${positionals.join(' ') || definition.commandPath.join(' ')}?`, {
210
+ assumeYes: options.yes === true,
211
+ noInput: options.input === false,
212
+ });
213
+ }
214
+ // stdin is only consulted when the command can actually take a body and no
215
+ // explicit --data was given, so piping into a read command is never silently
216
+ // swallowed.
217
+ const explicitData = options.data === undefined ? undefined : (0, input_1.readData)(options.data);
218
+ const piped = definition.acceptsBody && explicitData === undefined && (0, input_1.stdinIsPiped)() ?
219
+ (() => {
220
+ const raw = (0, input_1.readStdin)().trim();
221
+ return raw.length === 0 ? undefined : JSON.parse(raw);
222
+ })()
223
+ : undefined;
224
+ const args = (0, input_1.buildArgs)({
225
+ command: definition,
226
+ positionals,
227
+ options,
228
+ ...(explicitData === undefined ? {} : { data: explicitData }),
229
+ ...(piped === undefined ? {} : { stdin: piped }),
230
+ });
231
+ const client = clientFor(options, definition.requiresAuth);
232
+ const resource = client[definition.clientProperty];
233
+ const method = resource?.[definition.methodName];
234
+ if (typeof method !== 'function') {
235
+ // Only reachable if the table and the installed SDK disagree, which means
236
+ // the two packages were published out of step.
237
+ throw new Error(`${program.binaryName}: ${definition.clientProperty}.${definition.methodName} is missing from @roarkanalytics/sdk`);
238
+ }
239
+ const result = await method.apply(resource, args);
240
+ if (options.quiet === true)
241
+ return;
242
+ (0, output_1.write)((0, output_1.render)(result, output));
243
+ };
244
+ const createProgram = (options) => {
245
+ const root = new commander_1.Command()
246
+ .name(options.binaryName)
247
+ .description(options.description)
248
+ .version(options.version, '-v, --version')
249
+ .showHelpAfterError()
250
+ .enablePositionalOptions();
251
+ addGlobalOptions(root, { body: false, confirmation: false });
252
+ for (const definition of options.commands)
253
+ addApiCommand(root, options, definition);
254
+ (0, auth_1.registerAuthCommands)(root, options.binaryName);
255
+ (0, config_1.registerConfigCommands)(root, options.binaryName);
256
+ (0, api_1.registerApiCommand)(root, options.binaryName, clientFor, exports.resolveOutput);
257
+ (0, completion_1.registerCompletionCommand)(root, options.binaryName, options.completions);
258
+ root.addHelpText('after', [
259
+ '',
260
+ 'Environment:',
261
+ ' ROARK_API_BEARER_TOKEN bearer token used when --token is not given',
262
+ ' ROARK_BASE_URL API base URL',
263
+ ` ROARK_ALLOW_PROJECT_BASE_URL trust a base URL set by a ${config_2.PROJECT_FILE}`,
264
+ ' NO_COLOR disable colour',
265
+ '',
266
+ `Run \`${options.binaryName} <command> --help\` for the flags of a single command.`,
267
+ ].join('\n'));
268
+ return root;
269
+ };
270
+ exports.createProgram = createProgram;
271
+ /**
272
+ * `exitOverride` is per command, not inherited. Without walking the tree, a
273
+ * subcommand's parse error calls `process.exit` itself and never reaches the
274
+ * handler below, so `roark call retrieve` exited 1 instead of 2.
275
+ */
276
+ const overrideExitEverywhere = (command) => {
277
+ command.exitOverride();
278
+ for (const child of command.commands)
279
+ overrideExitEverywhere(child);
280
+ };
281
+ const run = async (options, argv) => {
282
+ const program = (0, exports.createProgram)(options);
283
+ overrideExitEverywhere(program);
284
+ try {
285
+ await program.parseAsync(argv);
286
+ return process.exitCode === undefined ? errors_1.EXIT.ok : Number(process.exitCode);
287
+ }
288
+ catch (error) {
289
+ // Commander throws for --help and --version too; those are successful exits.
290
+ const code = error.code;
291
+ if (code === 'commander.helpDisplayed' || code === 'commander.help')
292
+ return errors_1.EXIT.ok;
293
+ if (code === 'commander.version')
294
+ return errors_1.EXIT.ok;
295
+ if (typeof code === 'string' && code.startsWith('commander.')) {
296
+ const message = error.message;
297
+ if (message)
298
+ (0, output_1.write)((0, output_1.paint)(`error: ${message}`, 'red', (0, output_1.supportsColor)(process.stderr)), process.stderr);
299
+ return errors_1.EXIT.usage;
300
+ }
301
+ (0, errors_1.reportError)(error, { ...(0, exports.resolveOutput)({}), binaryName: options.binaryName });
302
+ return (0, errors_1.exitCodeFor)(error);
303
+ }
304
+ };
305
+ exports.run = run;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The contract between the generated command table and this runtime.
3
+ *
4
+ * `src/commands.ts` is generated from the OpenAPI spec by app-agent-codegen and
5
+ * contains nothing but data in these shapes. Everything in `src/runtime/` is
6
+ * hand-maintained and holds no per-endpoint knowledge, so adding an endpoint is
7
+ * a data change and never a code change.
8
+ */
9
+ export type CliValueKind = 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array';
10
+ export interface CliPositional {
11
+ /** As shown in usage, e.g. `call-id`. */
12
+ name: string;
13
+ /** Wire name of the path parameter, e.g. `callId`. */
14
+ paramKey: string;
15
+ description?: string;
16
+ }
17
+ export interface CliFlag {
18
+ /** As typed, without the leading dashes. Dotted for a nested leaf. */
19
+ name: string;
20
+ /** Where the value lands in the params object, e.g. `['metadata', 'source']`. */
21
+ path: string[];
22
+ location: 'query' | 'body' | 'path';
23
+ required: boolean;
24
+ description?: string;
25
+ valueKind: CliValueKind;
26
+ enumValues?: string[];
27
+ /** `--tag a --tag b` accumulates into an array. */
28
+ repeatable?: boolean;
29
+ }
30
+ export interface CliBodyVariant {
31
+ name: string;
32
+ required: string[];
33
+ }
34
+ export interface CliCommand {
35
+ commandPath: string[];
36
+ clientProperty: string;
37
+ methodName: string;
38
+ httpMethod: string;
39
+ httpPath: string;
40
+ summary?: string;
41
+ description?: string;
42
+ /** All path params in path order. The last is the SDK's positional argument. */
43
+ positionals: CliPositional[];
44
+ flags: CliFlag[];
45
+ hasParams: boolean;
46
+ paramsAllOptional: boolean;
47
+ /** The body is a union: reachable only through `--data` or stdin. */
48
+ bodyOpaque: boolean;
49
+ bodyVariants: CliBodyVariant[];
50
+ acceptsBody: boolean;
51
+ /** False where the operation declares `security: []`, e.g. the health check. */
52
+ requiresAuth: boolean;
53
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * The contract between the generated command table and this runtime.
4
+ *
5
+ * `src/commands.ts` is generated from the OpenAPI spec by app-agent-codegen and
6
+ * contains nothing but data in these shapes. Everything in `src/runtime/` is
7
+ * hand-maintained and holds no per-endpoint knowledge, so adding an endpoint is
8
+ * a data change and never a code change.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
package/version.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare const version = "2.31.0";
package/version.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.version = void 0;
4
+ // Bumped by hand, together with `version` in package.json. This package is not
5
+ // in release-please-config.json's `extra-files`: the CLI ships from
6
+ // publish-cli.yml rather than the vendor's release train, so no tooling rewrites
7
+ // this line.
8
+ exports.version = '2.31.0';