@seamapi/cli 0.9.0 → 0.11.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 (87) hide show
  1. package/README.md +83 -6
  2. package/bin/cli.js +106 -31
  3. package/bin/cli.js.map +1 -1
  4. package/lib/get-response-key.d.ts +9 -0
  5. package/lib/get-response-key.js +21 -0
  6. package/lib/get-response-key.js.map +1 -0
  7. package/lib/interact-for-action-attempt-poll.js +4 -3
  8. package/lib/interact-for-action-attempt-poll.js.map +1 -1
  9. package/lib/interact-for-array.js +9 -7
  10. package/lib/interact-for-array.js.map +1 -1
  11. package/lib/interact-for-blueprint-object.js +21 -10
  12. package/lib/interact-for-blueprint-object.js.map +1 -1
  13. package/lib/interact-for-command-selection.js +17 -2
  14. package/lib/interact-for-command-selection.js.map +1 -1
  15. package/lib/interact-for-custom-metadata.js +10 -8
  16. package/lib/interact-for-custom-metadata.js.map +1 -1
  17. package/lib/interact-for-login.js +8 -6
  18. package/lib/interact-for-login.js.map +1 -1
  19. package/lib/interact-for-resource.js +2 -2
  20. package/lib/interact-for-resource.js.map +1 -1
  21. package/lib/interact-for-server-selection.js +7 -5
  22. package/lib/interact-for-server-selection.js.map +1 -1
  23. package/lib/interact-for-timestamp.js +2 -2
  24. package/lib/interact-for-timestamp.js.map +1 -1
  25. package/lib/interact-for-use-remote-api-defs.js +4 -3
  26. package/lib/interact-for-use-remote-api-defs.js.map +1 -1
  27. package/lib/interact-for-workspace-id.js +2 -2
  28. package/lib/interact-for-workspace-id.js.map +1 -1
  29. package/lib/output/create-memory-output.d.ts +13 -0
  30. package/lib/output/create-memory-output.js +22 -0
  31. package/lib/output/create-memory-output.js.map +1 -0
  32. package/lib/output/create-output.d.ts +50 -0
  33. package/lib/output/create-output.js +34 -0
  34. package/lib/output/create-output.js.map +1 -0
  35. package/lib/output/get-output.d.ts +12 -0
  36. package/lib/output/get-output.js +21 -0
  37. package/lib/output/get-output.js.map +1 -0
  38. package/lib/output/resolve-output-format.d.ts +16 -0
  39. package/lib/output/resolve-output-format.js +23 -0
  40. package/lib/output/resolve-output-format.js.map +1 -0
  41. package/lib/output/select-response-payload.d.ts +16 -0
  42. package/lib/output/select-response-payload.js +33 -0
  43. package/lib/output/select-response-payload.js.map +1 -0
  44. package/lib/types.d.ts +2 -1
  45. package/lib/util/cli-args.d.ts +45 -0
  46. package/lib/util/cli-args.js +58 -0
  47. package/lib/util/cli-args.js.map +1 -0
  48. package/lib/util/prompt.d.ts +17 -0
  49. package/lib/util/prompt.js +25 -0
  50. package/lib/util/prompt.js.map +1 -0
  51. package/lib/util/read-stdin-json.d.ts +22 -0
  52. package/lib/util/read-stdin-json.js +42 -0
  53. package/lib/util/read-stdin-json.js.map +1 -0
  54. package/lib/util/request-seam-api.d.ts +5 -2
  55. package/lib/util/request-seam-api.js +13 -15
  56. package/lib/util/request-seam-api.js.map +1 -1
  57. package/lib/util/with-loading.js +6 -1
  58. package/lib/util/with-loading.js.map +1 -1
  59. package/lib/version.d.ts +1 -1
  60. package/lib/version.js +1 -1
  61. package/lib/version.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/bin/cli.ts +139 -33
  64. package/src/lib/get-response-key.ts +25 -0
  65. package/src/lib/interact-for-action-attempt-poll.ts +4 -3
  66. package/src/lib/interact-for-array.ts +9 -7
  67. package/src/lib/interact-for-blueprint-object.ts +27 -10
  68. package/src/lib/interact-for-command-selection.ts +23 -3
  69. package/src/lib/interact-for-custom-metadata.ts +10 -8
  70. package/src/lib/interact-for-login.ts +8 -6
  71. package/src/lib/interact-for-resource.ts +2 -3
  72. package/src/lib/interact-for-server-selection.ts +7 -6
  73. package/src/lib/interact-for-timestamp.ts +2 -2
  74. package/src/lib/interact-for-use-remote-api-defs.ts +4 -4
  75. package/src/lib/interact-for-workspace-id.ts +2 -2
  76. package/src/lib/output/create-memory-output.ts +39 -0
  77. package/src/lib/output/create-output.ts +104 -0
  78. package/src/lib/output/get-output.ts +24 -0
  79. package/src/lib/output/resolve-output-format.ts +33 -0
  80. package/src/lib/output/select-response-payload.ts +56 -0
  81. package/src/lib/types.ts +2 -1
  82. package/src/lib/util/cli-args.ts +92 -0
  83. package/src/lib/util/prompt.ts +38 -0
  84. package/src/lib/util/read-stdin-json.ts +59 -0
  85. package/src/lib/util/request-seam-api.ts +24 -20
  86. package/src/lib/util/with-loading.ts +9 -1
  87. package/src/lib/version.ts +1 -1
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Top level response fields that are transport details,
3
+ * not part of the result the CLI reports.
4
+ */
5
+ const metaKeys = new Set(['ok']);
6
+ const paginationKey = 'pagination';
7
+ const errorKey = 'error';
8
+ /**
9
+ * Reduce an API response body to the response key and pagination.
10
+ *
11
+ * The CLI never reports other top level fields: they are details of the
12
+ * transport, so including them would leak into anything parsing stdout.
13
+ */
14
+ export const selectResponsePayload = (data, { responseKey } = {}) => {
15
+ if (!isRecord(data))
16
+ return data;
17
+ if (errorKey in data) {
18
+ return { [errorKey]: data[errorKey] };
19
+ }
20
+ const keys = responseKey != null && responseKey in data
21
+ ? [responseKey]
22
+ : Object.keys(data).filter((key) => !metaKeys.has(key) && key !== paginationKey);
23
+ const payload = {};
24
+ for (const key of keys) {
25
+ payload[key] = data[key];
26
+ }
27
+ if (paginationKey in data) {
28
+ payload[paginationKey] = data[paginationKey];
29
+ }
30
+ return payload;
31
+ };
32
+ const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
33
+ //# sourceMappingURL=select-response-payload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-response-payload.js","sourceRoot":"","sources":["../../src/lib/output/select-response-payload.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AAEhC,MAAM,aAAa,GAAG,YAAY,CAAA;AAClC,MAAM,QAAQ,GAAG,OAAO,CAAA;AAYxB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,IAAa,EACb,EAAE,WAAW,KAAmC,EAAE,EACzC,EAAE;IACX,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAEhC,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAA;IACvC,CAAC;IAED,MAAM,IAAI,GACR,WAAW,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI;QACxC,CAAC,CAAC,CAAC,WAAW,CAAC;QACf,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CACtB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,aAAa,CACrD,CAAA;IAEP,MAAM,OAAO,GAA4B,EAAE,CAAA;IAC3C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAED,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;QAC1B,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAA;IAC9C,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA"}
package/lib/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ApiBlueprint } from './get-api-blueprint.js';
2
+ import type { Interactivity } from './util/cli-args.js';
2
3
  export interface ContextHelpers {
3
4
  blueprint: ApiBlueprint;
4
- is_interactive: boolean;
5
+ interactivity: Interactivity;
5
6
  }
@@ -0,0 +1,45 @@
1
+ import { type ParsedArgs } from 'minimist';
2
+ /**
3
+ * How the CLI should behave when properties are not given as arguments.
4
+ *
5
+ * - `auto`: make the request as soon as every required property is given,
6
+ * otherwise prompt for what is missing. This is the default.
7
+ * - `interactive`: always prompt to review and edit properties, prefilled
8
+ * with the given arguments. Selected with `--interactive` or `-i`.
9
+ * - `non-interactive`: never prompt: anything missing is an error.
10
+ * Selected with `--non-interactive` or `-y`.
11
+ */
12
+ export type Interactivity = 'auto' | 'interactive' | 'non-interactive';
13
+ /**
14
+ * Argument keys that select the interactivity
15
+ * and are therefore not command parameters.
16
+ */
17
+ export declare const interactivityFlags: string[];
18
+ /**
19
+ * Argument keys that configure the CLI itself
20
+ * and are therefore never sent as command parameters.
21
+ */
22
+ export declare const cliFlags: string[];
23
+ /**
24
+ * Thrown when the CLI needs input it cannot prompt for.
25
+ */
26
+ export declare class NonInteractiveError extends Error {
27
+ name: string;
28
+ }
29
+ export declare const parseCliArgs: (argv: string[]) => ParsedArgs;
30
+ export interface GetInteractivityOptions {
31
+ /**
32
+ * Whether there is a terminal to prompt on.
33
+ *
34
+ * When there is not, the CLI cannot ask for anything, so it behaves as
35
+ * though `--non-interactive` was given rather than waiting on a prompt
36
+ * nobody can answer.
37
+ */
38
+ canPrompt?: boolean;
39
+ }
40
+ export declare const getInteractivity: (args: ParsedArgs, { canPrompt }?: GetInteractivityOptions) => Interactivity;
41
+ /**
42
+ * Render a parameter name as the argument used to set it,
43
+ * e.g., `device_id` as `--device-id`.
44
+ */
45
+ export declare const toArgName: (parameterName: string) => string;
@@ -0,0 +1,58 @@
1
+ import parseArgs, {} from 'minimist';
2
+ /**
3
+ * Argument keys that select the interactivity
4
+ * and are therefore not command parameters.
5
+ */
6
+ export const interactivityFlags = [
7
+ 'non_interactive',
8
+ 'y',
9
+ 'interactive',
10
+ 'i',
11
+ ];
12
+ /**
13
+ * Argument keys that configure the CLI itself
14
+ * and are therefore never sent as command parameters.
15
+ */
16
+ export const cliFlags = [
17
+ ...interactivityFlags,
18
+ 'h',
19
+ 'help',
20
+ 'json',
21
+ 'remote_api_defs',
22
+ 'update',
23
+ 'version',
24
+ ];
25
+ /**
26
+ * Thrown when the CLI needs input it cannot prompt for.
27
+ */
28
+ export class NonInteractiveError extends Error {
29
+ name = 'NonInteractiveError';
30
+ }
31
+ export const parseCliArgs = (argv) => parseArgs(argv, {
32
+ string: ['code'],
33
+ boolean: ['non-interactive', 'interactive', 'json'],
34
+ // Deliberately not aliased to -n, which is reserved for a future
35
+ // --dry-run flag.
36
+ alias: { 'non-interactive': 'y', interactive: 'i' },
37
+ });
38
+ export const getInteractivity = (args, { canPrompt = true } = {}) => {
39
+ const isNonInteractive = args['non_interactive'] === true || args['y'] === true;
40
+ const isInteractive = args['interactive'] === true || args['i'] === true;
41
+ if (isNonInteractive && isInteractive) {
42
+ throw new Error('The --interactive and --non-interactive flags cannot be used together');
43
+ }
44
+ if (isNonInteractive)
45
+ return 'non-interactive';
46
+ // An explicit --interactive still asks, and fails loudly if it cannot.
47
+ if (isInteractive)
48
+ return 'interactive';
49
+ if (!canPrompt)
50
+ return 'non-interactive';
51
+ return 'auto';
52
+ };
53
+ /**
54
+ * Render a parameter name as the argument used to set it,
55
+ * e.g., `device_id` as `--device-id`.
56
+ */
57
+ export const toArgName = (parameterName) => `--${parameterName.replace(/_/g, '-')}`;
58
+ //# sourceMappingURL=cli-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../../src/lib/util/cli-args.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAAmB,MAAM,UAAU,CAAA;AAcrD;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAa;IAC1C,iBAAiB;IACjB,GAAG;IACH,aAAa;IACb,GAAG;CACJ,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAa;IAChC,GAAG,kBAAkB;IACrB,GAAG;IACH,MAAM;IACN,MAAM;IACN,iBAAiB;IACjB,QAAQ;IACR,SAAS;CACV,CAAA;AAED;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,GAAG,qBAAqB,CAAA;CACtC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAc,EAAc,EAAE,CACzD,SAAS,CAAC,IAAI,EAAE;IACd,MAAM,EAAE,CAAC,MAAM,CAAC;IAChB,OAAO,EAAE,CAAC,iBAAiB,EAAE,aAAa,EAAE,MAAM,CAAC;IACnD,iEAAiE;IACjE,kBAAkB;IAClB,KAAK,EAAE,EAAE,iBAAiB,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE;CACpD,CAAC,CAAA;AAaJ,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,IAAgB,EAChB,EAAE,SAAS,GAAG,IAAI,KAA8B,EAAE,EACnC,EAAE;IACjB,MAAM,gBAAgB,GACpB,IAAI,CAAC,iBAAiB,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;IACxD,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;IAExE,IAAI,gBAAgB,IAAI,aAAa,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,uEAAuE,CACxE,CAAA;IACH,CAAC;IACD,IAAI,gBAAgB;QAAE,OAAO,iBAAiB,CAAA;IAC9C,uEAAuE;IACvE,IAAI,aAAa;QAAE,OAAO,aAAa,CAAA;IACvC,IAAI,CAAC,SAAS;QAAE,OAAO,iBAAiB,CAAA;IACxC,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,aAAqB,EAAU,EAAE,CACzD,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { type Answers, type Options, type PromptObject } from 'prompts';
2
+ /**
3
+ * Whether the CLI can ask the user a question.
4
+ *
5
+ * Prompts read raw keypresses and render an interface, so they need a
6
+ * terminal on both ends: when stdin is a pipe or a file it holds request
7
+ * params, not answers, and when stderr is redirected nobody sees the
8
+ * question.
9
+ */
10
+ export declare const canPrompt: () => boolean;
11
+ /**
12
+ * Ask the user a question.
13
+ *
14
+ * Prompts are rendered to stderr: a selection is not a command result,
15
+ * so it must not end up in stdout when the CLI is piped.
16
+ */
17
+ export declare const prompt: <T extends string = string>(questions: PromptObject<T> | Array<PromptObject<T>>, options?: Options) => Promise<Answers<T>>;
@@ -0,0 +1,25 @@
1
+ import prompts, {} from 'prompts';
2
+ import { NonInteractiveError } from './cli-args.js';
3
+ /**
4
+ * Whether the CLI can ask the user a question.
5
+ *
6
+ * Prompts read raw keypresses and render an interface, so they need a
7
+ * terminal on both ends: when stdin is a pipe or a file it holds request
8
+ * params, not answers, and when stderr is redirected nobody sees the
9
+ * question.
10
+ */
11
+ export const canPrompt = () => process.stdin.isTTY === true && process.stderr.isTTY === true;
12
+ /**
13
+ * Ask the user a question.
14
+ *
15
+ * Prompts are rendered to stderr: a selection is not a command result,
16
+ * so it must not end up in stdout when the CLI is piped.
17
+ */
18
+ export const prompt = async (questions, options) => {
19
+ if (!canPrompt()) {
20
+ throw new NonInteractiveError('Cannot prompt without a terminal: pass the missing arguments, or pipe them in as JSON');
21
+ }
22
+ const questionList = Array.isArray(questions) ? questions : [questions];
23
+ return await prompts(questionList.map((question) => ({ ...question, stdout: process.stderr })), options);
24
+ };
25
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/lib/util/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAiD,MAAM,SAAS,CAAA;AAEhF,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAEnD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAY,EAAE,CACrC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EACzB,SAAmD,EACnD,OAAiB,EACI,EAAE;IACvB,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,mBAAmB,CAC3B,uFAAuF,CACxF,CAAA;IACH,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAEvE,OAAO,MAAM,OAAO,CAClB,YAAY,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,EACzE,OAAO,CACR,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,22 @@
1
+ import type { Readable } from 'node:stream';
2
+ export interface StdinLike extends AsyncIterable<string | Buffer> {
3
+ isTTY?: boolean | undefined;
4
+ }
5
+ /**
6
+ * Read request params piped into the CLI, e.g.,
7
+ *
8
+ * ```
9
+ * $ echo '{"device_id": "..."}' | seam locks unlock-door --json
10
+ * $ seam locks unlock-door --json < params.json
11
+ * ```
12
+ *
13
+ * Returns null when stdin is a terminal or is empty,
14
+ * so an interactive session is never blocked waiting for input.
15
+ */
16
+ export declare const readStdinJson: (stdin?: StdinLike | Readable) => Promise<Record<string, unknown> | null>;
17
+ /**
18
+ * Parse JSON request params, e.g., from stdin or `--json '{"limit": 2}'`.
19
+ *
20
+ * Returns null when there is nothing to parse.
21
+ */
22
+ export declare const parseJsonParams: (raw: string, source: string) => Record<string, unknown> | null;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Read request params piped into the CLI, e.g.,
3
+ *
4
+ * ```
5
+ * $ echo '{"device_id": "..."}' | seam locks unlock-door --json
6
+ * $ seam locks unlock-door --json < params.json
7
+ * ```
8
+ *
9
+ * Returns null when stdin is a terminal or is empty,
10
+ * so an interactive session is never blocked waiting for input.
11
+ */
12
+ export const readStdinJson = async (stdin = process.stdin) => {
13
+ if (stdin.isTTY ?? false)
14
+ return null;
15
+ let raw = '';
16
+ for await (const chunk of stdin) {
17
+ raw += typeof chunk === 'string' ? chunk : chunk.toString('utf8');
18
+ }
19
+ return parseJsonParams(raw, 'stdin');
20
+ };
21
+ /**
22
+ * Parse JSON request params, e.g., from stdin or `--json '{"limit": 2}'`.
23
+ *
24
+ * Returns null when there is nothing to parse.
25
+ */
26
+ export const parseJsonParams = (raw, source) => {
27
+ const trimmed = raw.trim();
28
+ if (trimmed === '')
29
+ return null;
30
+ let parsed;
31
+ try {
32
+ parsed = JSON.parse(trimmed);
33
+ }
34
+ catch (error) {
35
+ throw new Error(`Could not parse JSON from ${source}: ${error.message}`);
36
+ }
37
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
38
+ throw new Error(`Expected a JSON object of request params from ${source}, got ${Array.isArray(parsed) ? 'an array' : typeof parsed}`);
39
+ }
40
+ return parsed;
41
+ };
42
+ //# sourceMappingURL=read-stdin-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-stdin-json.js","sourceRoot":"","sources":["../../src/lib/util/read-stdin-json.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,QAA8B,OAAO,CAAC,KAAK,EACF,EAAE;IAC3C,IAAK,KAAmB,CAAC,KAAK,IAAI,KAAK;QAAE,OAAO,IAAI,CAAA;IAEpD,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAChC,GAAG,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACnE,CAAC;IAED,OAAO,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;AACtC,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,GAAW,EACX,MAAc,EACkB,EAAE;IAClC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IAC1B,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,IAAI,CAAA;IAE/B,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,6BAA6B,MAAM,KAAM,KAAe,CAAC,OAAO,EAAE,CACnE,CAAA;IACH,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CACb,iDAAiD,MAAM,SAAS,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CACrH,CAAA;IACH,CAAC;IAED,OAAO,MAAiC,CAAA;AAC1C,CAAC,CAAA"}
@@ -1,4 +1,7 @@
1
- export declare const RequestSeamApi: ({ path, params, }: {
1
+ export interface RequestSeamApiOptions {
2
2
  path: string;
3
3
  params: Record<string, any>;
4
- }) => Promise<import("axios").AxiosResponse<any, any, {}>>;
4
+ /** Response key for the endpoint, used to trim the reported payload. */
5
+ responseKey?: string | null | undefined;
6
+ }
7
+ export declare const RequestSeamApi: ({ path, params, responseKey, }: RequestSeamApiOptions) => Promise<import("axios").AxiosResponse<any, any, {}>>;
@@ -1,28 +1,26 @@
1
1
  import chalk from 'chalk';
2
2
  import { getSeam } from '../get-seam.js';
3
+ import { getOutput } from '../output/get-output.js';
4
+ import { selectResponsePayload } from '../output/select-response-payload.js';
3
5
  import { withLoading } from './with-loading.js';
4
- export const RequestSeamApi = async ({ path, params, }) => {
6
+ export const RequestSeamApi = async ({ path, params, responseKey, }) => {
5
7
  const seam = await getSeam();
6
- logRequest(path, params);
8
+ const output = getOutput();
9
+ output.info(`\n${chalk.green(path)}`);
10
+ output.info(`Request Params:`);
11
+ output.info(formatParams(params));
7
12
  const response = await withLoading('Making request...', () => seam.client.post(path, params, {
8
13
  validateStatus: () => true,
9
14
  }));
10
- logResponse(response);
11
- return response;
12
- };
13
- const logResponse = (response) => {
14
15
  if (response.status >= 400) {
15
- console.log(chalk.red(`\n\n[${response.status}]\n`));
16
+ output.warn(chalk.red(`[${response.status}]`));
17
+ process.exitCode = 1;
16
18
  }
17
19
  else {
18
- console.log(chalk.green(`\n\n[${response.status}]`));
20
+ output.info(chalk.green(`[${response.status}]`));
19
21
  }
20
- console.dir(response.data, { depth: null });
21
- console.log('\n');
22
- };
23
- const logRequest = (apiPath, params) => {
24
- console.log(`\n\n${chalk.green(apiPath)}`);
25
- console.log(`Request Params:`);
26
- console.log(params);
22
+ output.data(selectResponsePayload(response.data, { responseKey }));
23
+ return response;
27
24
  };
25
+ const formatParams = (params) => JSON.stringify(params, null, 2);
28
26
  //# sourceMappingURL=request-seam-api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-seam-api.js","sourceRoot":"","sources":["../../src/lib/util/request-seam-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,EACnC,IAAI,EACJ,MAAM,GAIP,EAAE,EAAE;IACH,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAA;IAE5B,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAExB,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAC3D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE;QAC7B,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;KAC3B,CAAC,CACH,CAAA;IAED,WAAW,CAAC,QAAQ,CAAC,CAAA;IAErB,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,CAAC,QAA2C,EAAE,EAAE;IAClE,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAA;IACtD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AACnB,CAAC,CAAA;AAED,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,MAA2B,EAAE,EAAE;IAClE,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC1C,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAC9B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AACrB,CAAC,CAAA"}
1
+ {"version":3,"file":"request-seam-api.js","sourceRoot":"","sources":["../../src/lib/util/request-seam-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAA;AAE7E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAS/C,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,EACnC,IAAI,EACJ,MAAM,EACN,WAAW,GACW,EAAE,EAAE;IAC1B,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAA;IAC5B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,MAAM,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACrC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC9B,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAA;IAEjC,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAC3D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE;QAC7B,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;KAC3B,CAAC,CACH,CAAA;IAED,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAC9C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;IACtB,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAClD,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;IAElE,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,YAAY,GAAG,CAAC,MAA2B,EAAU,EAAE,CAC3D,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA"}
@@ -1,6 +1,10 @@
1
1
  import { createSpinner } from 'nanospinner';
2
+ import { getOutput } from '../output/get-output.js';
2
3
  export const withLoading = async (message, fn) => {
3
- const spinner = createSpinner(message).start();
4
+ if (!shouldSpin())
5
+ return await fn();
6
+ // Progress is not a command result, so it is rendered to stderr.
7
+ const spinner = createSpinner(message, { stream: process.stderr }).start();
4
8
  try {
5
9
  const result = await fn();
6
10
  spinner.success();
@@ -11,4 +15,5 @@ export const withLoading = async (message, fn) => {
11
15
  throw error;
12
16
  }
13
17
  };
18
+ const shouldSpin = () => getOutput().format === 'text' && process.stderr.isTTY === true;
14
19
  //# sourceMappingURL=with-loading.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"with-loading.js","sourceRoot":"","sources":["../../src/lib/util/with-loading.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,OAAe,EACf,EAAoB,EACR,EAAE;IACd,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAA;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAA;QACzB,OAAO,CAAC,OAAO,EAAE,CAAA;QACjB,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,EAAE,CAAA;QACf,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"with-loading.js","sourceRoot":"","sources":["../../src/lib/util/with-loading.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEpD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,OAAe,EACf,EAAoB,EACR,EAAE;IACd,IAAI,CAAC,UAAU,EAAE;QAAE,OAAO,MAAM,EAAE,EAAE,CAAA;IAEpC,iEAAiE;IACjE,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA;IAC1E,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAA;QACzB,OAAO,CAAC,OAAO,EAAE,CAAA;QACjB,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,EAAE,CAAA;QACf,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED,MAAM,UAAU,GAAG,GAAY,EAAE,CAC/B,SAAS,EAAE,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAA"}
package/lib/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- declare const seamapiCliVersion = "0.9.0";
1
+ declare const seamapiCliVersion = "0.11.0";
2
2
  declare const seamapiBlueprintVersion = "1.2.0";
3
3
  export { seamapiBlueprintVersion };
4
4
  export default seamapiCliVersion;
package/lib/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Versions are replaced with generated values when the package is packed.
2
- const seamapiCliVersion = '0.9.0';
2
+ const seamapiCliVersion = '0.11.0';
3
3
  const seamapiBlueprintVersion = '1.2.0';
4
4
  export { seamapiBlueprintVersion };
5
5
  export default seamapiCliVersion;
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/lib/version.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,MAAM,iBAAiB,GAAG,OAAO,CAAA;AACjC,MAAM,uBAAuB,GAAG,OAAO,CAAA;AAEvC,OAAO,EAAE,uBAAuB,EAAE,CAAA;AAClC,eAAe,iBAAiB,CAAA"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/lib/version.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,MAAM,iBAAiB,GAAG,QAAQ,CAAA;AAClC,MAAM,uBAAuB,GAAG,OAAO,CAAA;AAEvC,OAAO,EAAE,uBAAuB,EAAE,CAAA;AAClC,eAAe,iBAAiB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamapi/cli",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "A command line interface (CLI) for interacting with the Seam API.",
5
5
  "type": "module",
6
6
  "main": "index.js",