@seamapi/cli 0.10.0 → 0.12.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/README.md +118 -0
- package/bin/cli.js +78 -100
- package/bin/cli.js.map +1 -1
- package/completions/seam.bash +11 -0
- package/completions/seam.fish +11 -0
- package/completions/seam.zsh +13 -0
- package/lib/command-spec.d.ts +53 -0
- package/lib/command-spec.js +290 -0
- package/lib/command-spec.js.map +1 -0
- package/lib/completion/describe.d.ts +10 -0
- package/lib/completion/describe.js +16 -0
- package/lib/completion/describe.js.map +1 -0
- package/lib/completion/index.d.ts +20 -0
- package/lib/completion/index.js +65 -0
- package/lib/completion/index.js.map +1 -0
- package/lib/completion/render-bash.d.ts +2 -0
- package/lib/completion/render-bash.js +98 -0
- package/lib/completion/render-bash.js.map +1 -0
- package/lib/completion/render-fish.d.ts +2 -0
- package/lib/completion/render-fish.js +58 -0
- package/lib/completion/render-fish.js.map +1 -0
- package/lib/completion/render-zsh.d.ts +2 -0
- package/lib/completion/render-zsh.js +121 -0
- package/lib/completion/render-zsh.js.map +1 -0
- package/lib/get-response-key.d.ts +9 -0
- package/lib/get-response-key.js +21 -0
- package/lib/get-response-key.js.map +1 -0
- package/lib/interact-for-action-attempt-poll.js +4 -3
- package/lib/interact-for-action-attempt-poll.js.map +1 -1
- package/lib/interact-for-array.js +9 -7
- package/lib/interact-for-array.js.map +1 -1
- package/lib/interact-for-blueprint-object.js +9 -8
- package/lib/interact-for-blueprint-object.js.map +1 -1
- package/lib/interact-for-command-selection.js +2 -2
- package/lib/interact-for-command-selection.js.map +1 -1
- package/lib/interact-for-custom-metadata.js +10 -8
- package/lib/interact-for-custom-metadata.js.map +1 -1
- package/lib/interact-for-login.js +8 -6
- package/lib/interact-for-login.js.map +1 -1
- package/lib/interact-for-resource.js +2 -2
- package/lib/interact-for-resource.js.map +1 -1
- package/lib/interact-for-server-selection.js +7 -5
- package/lib/interact-for-server-selection.js.map +1 -1
- package/lib/interact-for-timestamp.js +2 -2
- package/lib/interact-for-timestamp.js.map +1 -1
- package/lib/interact-for-use-remote-api-defs.js +4 -3
- package/lib/interact-for-use-remote-api-defs.js.map +1 -1
- package/lib/interact-for-workspace-id.js +2 -2
- package/lib/interact-for-workspace-id.js.map +1 -1
- package/lib/output/create-memory-output.d.ts +13 -0
- package/lib/output/create-memory-output.js +22 -0
- package/lib/output/create-memory-output.js.map +1 -0
- package/lib/output/create-output.d.ts +50 -0
- package/lib/output/create-output.js +34 -0
- package/lib/output/create-output.js.map +1 -0
- package/lib/output/get-output.d.ts +12 -0
- package/lib/output/get-output.js +21 -0
- package/lib/output/get-output.js.map +1 -0
- package/lib/output/resolve-output-format.d.ts +16 -0
- package/lib/output/resolve-output-format.js +23 -0
- package/lib/output/resolve-output-format.js.map +1 -0
- package/lib/output/select-response-payload.d.ts +16 -0
- package/lib/output/select-response-payload.js +33 -0
- package/lib/output/select-response-payload.js.map +1 -0
- package/lib/render-help.d.ts +8 -0
- package/lib/render-help.js +150 -0
- package/lib/render-help.js.map +1 -0
- package/lib/util/cli-args.d.ts +16 -1
- package/lib/util/cli-args.js +18 -2
- package/lib/util/cli-args.js.map +1 -1
- package/lib/util/prompt.d.ts +17 -0
- package/lib/util/prompt.js +25 -0
- package/lib/util/prompt.js.map +1 -0
- package/lib/util/read-stdin-json.d.ts +22 -0
- package/lib/util/read-stdin-json.js +42 -0
- package/lib/util/read-stdin-json.js.map +1 -0
- package/lib/util/request-seam-api.d.ts +5 -2
- package/lib/util/request-seam-api.js +13 -15
- package/lib/util/request-seam-api.js.map +1 -1
- package/lib/util/with-loading.js +6 -1
- package/lib/util/with-loading.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +2 -1
- package/src/bin/cli.ts +100 -106
- package/src/lib/command-spec.ts +400 -0
- package/src/lib/completion/describe.ts +21 -0
- package/src/lib/completion/index.ts +82 -0
- package/src/lib/completion/render-bash.ts +125 -0
- package/src/lib/completion/render-fish.ts +80 -0
- package/src/lib/completion/render-zsh.ts +157 -0
- package/src/lib/get-response-key.ts +25 -0
- package/src/lib/interact-for-action-attempt-poll.ts +4 -3
- package/src/lib/interact-for-array.ts +9 -7
- package/src/lib/interact-for-blueprint-object.ts +9 -8
- package/src/lib/interact-for-command-selection.ts +2 -3
- package/src/lib/interact-for-custom-metadata.ts +10 -8
- package/src/lib/interact-for-login.ts +8 -6
- package/src/lib/interact-for-resource.ts +2 -3
- package/src/lib/interact-for-server-selection.ts +7 -6
- package/src/lib/interact-for-timestamp.ts +2 -2
- package/src/lib/interact-for-use-remote-api-defs.ts +4 -4
- package/src/lib/interact-for-workspace-id.ts +2 -2
- package/src/lib/output/create-memory-output.ts +39 -0
- package/src/lib/output/create-output.ts +104 -0
- package/src/lib/output/get-output.ts +24 -0
- package/src/lib/output/resolve-output-format.ts +33 -0
- package/src/lib/output/select-response-payload.ts +56 -0
- package/src/lib/render-help.ts +197 -0
- package/src/lib/util/cli-args.ts +32 -2
- package/src/lib/util/prompt.ts +38 -0
- package/src/lib/util/read-stdin-json.ts +59 -0
- package/src/lib/util/request-seam-api.ts +24 -20
- package/src/lib/util/with-loading.ts +9 -1
- package/src/lib/version.ts +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import prompts from 'prompts';
|
|
2
1
|
import { getConfigStore } from './config/index.js';
|
|
2
|
+
import { getOutput } from './output/get-output.js';
|
|
3
|
+
import { prompt } from './util/prompt.js';
|
|
3
4
|
export async function interactForUseRemoteApiDefs() {
|
|
4
|
-
const { use_remote_api_defs } = await
|
|
5
|
+
const { use_remote_api_defs } = await prompt([
|
|
5
6
|
{
|
|
6
7
|
type: 'select',
|
|
7
8
|
name: 'use_remote_api_defs',
|
|
@@ -20,6 +21,6 @@ export async function interactForUseRemoteApiDefs() {
|
|
|
20
21
|
]);
|
|
21
22
|
const config = getConfigStore();
|
|
22
23
|
config.set('use_remote_api_defs', use_remote_api_defs);
|
|
23
|
-
|
|
24
|
+
getOutput().info(`Use remote API Definitions: ${use_remote_api_defs}`);
|
|
24
25
|
}
|
|
25
26
|
//# sourceMappingURL=interact-for-use-remote-api-defs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interact-for-use-remote-api-defs.js","sourceRoot":"","sources":["../src/lib/interact-for-use-remote-api-defs.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"interact-for-use-remote-api-defs.js","sourceRoot":"","sources":["../src/lib/interact-for-use-remote-api-defs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAEzC,MAAM,CAAC,KAAK,UAAU,2BAA2B;IAC/C,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC;QAC3C;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,oCAAoC;YAC7C,OAAO,EAAE;gBACP;oBACE,KAAK,EAAE,KAAK;oBACZ,KAAK,EAAE,IAAI;iBACZ;gBACD;oBACE,KAAK,EAAE,IAAI;oBACX,KAAK,EAAE,KAAK;iBACb;aACF;SACF;KACF,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,cAAc,EAAE,CAAA;IAC/B,MAAM,CAAC,GAAG,CAAC,qBAAqB,EAAE,mBAAmB,CAAC,CAAA;IACtD,SAAS,EAAE,CAAC,IAAI,CAAC,+BAA+B,mBAAmB,EAAE,CAAC,CAAA;AACxE,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SeamHttpWithoutWorkspace } from '@seamapi/http/connect';
|
|
2
|
-
import prompts from 'prompts';
|
|
3
2
|
import { getConfigStore } from './config/index.js';
|
|
4
3
|
import { getSeamMultiWorkspace } from './get-seam.js';
|
|
5
4
|
import { getServer } from './get-server.js';
|
|
5
|
+
import { prompt } from './util/prompt.js';
|
|
6
6
|
import { withLoading } from './util/with-loading.js';
|
|
7
7
|
export const interactForWorkspaceId = async (personalAccessToken) => {
|
|
8
8
|
const config = getConfigStore();
|
|
@@ -12,7 +12,7 @@ export const interactForWorkspaceId = async (personalAccessToken) => {
|
|
|
12
12
|
})
|
|
13
13
|
: await getSeamMultiWorkspace();
|
|
14
14
|
const workspaces = await withLoading('Fetching workspaces...', () => seam.workspaces.list());
|
|
15
|
-
const { workspaceId } = await
|
|
15
|
+
const { workspaceId } = await prompt({
|
|
16
16
|
name: 'workspaceId',
|
|
17
17
|
type: 'select',
|
|
18
18
|
message: 'Select a workspace:',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interact-for-workspace-id.js","sourceRoot":"","sources":["../src/lib/interact-for-workspace-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"interact-for-workspace-id.js","sourceRoot":"","sources":["../src/lib/interact-for-workspace-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEpD,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAE,mBAA4B,EAAE,EAAE;IAC3E,MAAM,MAAM,GAAG,cAAc,EAAE,CAAA;IAC/B,MAAM,IAAI,GAAG,mBAAmB;QAC9B,CAAC,CAAC,wBAAwB,CAAC,uBAAuB,CAAC,mBAAmB,EAAE;YACpE,QAAQ,EAAE,SAAS,EAAE;SACtB,CAAC;QACJ,CAAC,CAAC,MAAM,qBAAqB,EAAE,CAAA;IAEjC,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAClE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CACvB,CAAA;IACD,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC;QACnC,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,qBAAqB;QAC9B,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,SAAc,EAAE,EAAE,CAAC,CAAC;YAC3C,KAAK,EAAE,SAAS,CAAC,IAAI;YACrB,KAAK,EAAE,SAAS,CAAC,YAAY;YAC7B,WAAW,EAAE,SAAS,CAAC,YAAY;SACpC,CAAC,CAAC;KACJ,CAAC,CAAA;IAEF,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,WAAW,CAAC,CAAA;QAC/C,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type CreateOutputOptions, type Output } from './create-output.js';
|
|
2
|
+
export interface MemoryOutput {
|
|
3
|
+
output: Output;
|
|
4
|
+
/** Everything written to stdout so far. */
|
|
5
|
+
stdout: () => string;
|
|
6
|
+
/** Everything written to stderr so far. */
|
|
7
|
+
stderr: () => string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* An {@link Output} that captures writes in memory instead of
|
|
11
|
+
* touching the process streams, for asserting on CLI output.
|
|
12
|
+
*/
|
|
13
|
+
export declare const createMemoryOutput: (options?: Omit<CreateOutputOptions, "stdout" | "stderr">) => MemoryOutput;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createOutput, } from './create-output.js';
|
|
2
|
+
const createMemoryStream = () => {
|
|
3
|
+
const chunks = [];
|
|
4
|
+
return {
|
|
5
|
+
write: (chunk) => chunks.push(chunk),
|
|
6
|
+
read: () => chunks.join(''),
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* An {@link Output} that captures writes in memory instead of
|
|
11
|
+
* touching the process streams, for asserting on CLI output.
|
|
12
|
+
*/
|
|
13
|
+
export const createMemoryOutput = (options = {}) => {
|
|
14
|
+
const stdout = createMemoryStream();
|
|
15
|
+
const stderr = createMemoryStream();
|
|
16
|
+
return {
|
|
17
|
+
output: createOutput({ ...options, stdout, stderr }),
|
|
18
|
+
stdout: stdout.read,
|
|
19
|
+
stderr: stderr.read,
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=create-memory-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-memory-output.js","sourceRoot":"","sources":["../../src/lib/output/create-memory-output.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,GAIb,MAAM,oBAAoB,CAAA;AAU3B,MAAM,kBAAkB,GAAG,GAA0C,EAAE;IACrE,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,OAAO;QACL,KAAK,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QAC5C,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;KAC5B,CAAA;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,UAA0D,EAAE,EAC9C,EAAE;IAChB,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAA;IACnC,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAA;IAEnC,OAAO;QACL,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACpD,MAAM,EAAE,MAAM,CAAC,IAAI;QACnB,MAAM,EAAE,MAAM,CAAC,IAAI;KACpB,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal writable surface needed by {@link Output}.
|
|
3
|
+
*
|
|
4
|
+
* Both `process.stdout` and an in-memory buffer satisfy this,
|
|
5
|
+
* which is what makes output testable.
|
|
6
|
+
*/
|
|
7
|
+
export interface OutputStream {
|
|
8
|
+
write: (chunk: string) => unknown;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* `json` is machine readable: only {@link Output.data} produces output.
|
|
12
|
+
* `text` is human readable: data is pretty printed and may be colorized.
|
|
13
|
+
*/
|
|
14
|
+
export type OutputFormat = 'json' | 'text';
|
|
15
|
+
export interface Output {
|
|
16
|
+
readonly format: OutputFormat;
|
|
17
|
+
/**
|
|
18
|
+
* The result of a command, e.g., an API response.
|
|
19
|
+
*
|
|
20
|
+
* This is the only thing ever written to stdout,
|
|
21
|
+
* so it is safe to pipe into another program.
|
|
22
|
+
*/
|
|
23
|
+
data: (value: unknown) => void;
|
|
24
|
+
/**
|
|
25
|
+
* A plain text command result, e.g., the version or the help guide.
|
|
26
|
+
*
|
|
27
|
+
* Written to stdout verbatim in every format: these results are already
|
|
28
|
+
* a single value, so encoding them as JSON would only make them harder
|
|
29
|
+
* to consume from a pipe.
|
|
30
|
+
*/
|
|
31
|
+
text: (value: string) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Human facing progress, context, and confirmations.
|
|
34
|
+
*
|
|
35
|
+
* Written to stderr and suppressed entirely in the json format.
|
|
36
|
+
*/
|
|
37
|
+
info: (message?: string) => void;
|
|
38
|
+
/** Human facing warning. Written to stderr in every format. */
|
|
39
|
+
warn: (message: string) => void;
|
|
40
|
+
/** Human facing error. Written to stderr in every format. */
|
|
41
|
+
error: (message: string) => void;
|
|
42
|
+
}
|
|
43
|
+
export interface CreateOutputOptions {
|
|
44
|
+
format?: OutputFormat;
|
|
45
|
+
stdout?: OutputStream;
|
|
46
|
+
stderr?: OutputStream;
|
|
47
|
+
/** Colorize pretty printed data. Never applied to the json format. */
|
|
48
|
+
colors?: boolean;
|
|
49
|
+
}
|
|
50
|
+
export declare const createOutput: ({ format, stdout, stderr, colors, }?: CreateOutputOptions) => Output;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { inspect } from 'node:util';
|
|
2
|
+
export const createOutput = ({ format = 'text', stdout = process.stdout, stderr = process.stderr, colors = false, } = {}) => {
|
|
3
|
+
const isJson = format === 'json';
|
|
4
|
+
return {
|
|
5
|
+
format,
|
|
6
|
+
data: (value) => {
|
|
7
|
+
if (value === undefined)
|
|
8
|
+
return;
|
|
9
|
+
stdout.write(`${formatData(value, format, colors)}\n`);
|
|
10
|
+
},
|
|
11
|
+
text: (value) => {
|
|
12
|
+
stdout.write(`${value}\n`);
|
|
13
|
+
},
|
|
14
|
+
info: (message = '') => {
|
|
15
|
+
if (isJson)
|
|
16
|
+
return;
|
|
17
|
+
stderr.write(`${message}\n`);
|
|
18
|
+
},
|
|
19
|
+
warn: (message) => {
|
|
20
|
+
stderr.write(`${message}\n`);
|
|
21
|
+
},
|
|
22
|
+
error: (message) => {
|
|
23
|
+
stderr.write(`${message}\n`);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
const formatData = (value, format, colors) => {
|
|
28
|
+
if (format === 'json')
|
|
29
|
+
return JSON.stringify(value, null, 2);
|
|
30
|
+
if (typeof value === 'string')
|
|
31
|
+
return value;
|
|
32
|
+
return inspect(value, { depth: null, colors });
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=create-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-output.js","sourceRoot":"","sources":["../../src/lib/output/create-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA4DnC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAC3B,MAAM,GAAG,MAAM,EACf,MAAM,GAAG,OAAO,CAAC,MAAM,EACvB,MAAM,GAAG,OAAO,CAAC,MAAM,EACvB,MAAM,GAAG,KAAK,MACS,EAAE,EAAU,EAAE;IACrC,MAAM,MAAM,GAAG,MAAM,KAAK,MAAM,CAAA;IAEhC,OAAO;QACL,MAAM;QAEN,IAAI,EAAE,CAAC,KAAc,EAAQ,EAAE;YAC7B,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAM;YAC/B,MAAM,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QACxD,CAAC;QAED,IAAI,EAAE,CAAC,KAAa,EAAQ,EAAE;YAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAAA;QAC5B,CAAC;QAED,IAAI,EAAE,CAAC,OAAO,GAAG,EAAE,EAAQ,EAAE;YAC3B,IAAI,MAAM;gBAAE,OAAM;YAClB,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAA;QAC9B,CAAC;QAED,IAAI,EAAE,CAAC,OAAe,EAAQ,EAAE;YAC9B,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAA;QAC9B,CAAC;QAED,KAAK,EAAE,CAAC,OAAe,EAAQ,EAAE;YAC/B,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAA;QAC9B,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAED,MAAM,UAAU,GAAG,CACjB,KAAc,EACd,MAAoB,EACpB,MAAe,EACP,EAAE;IACV,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3C,OAAO,OAAO,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;AAChD,CAAC,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Output } from './create-output.js';
|
|
2
|
+
/**
|
|
3
|
+
* The output used by the CLI.
|
|
4
|
+
*
|
|
5
|
+
* Defaults to a `text` output bound to the real process streams,
|
|
6
|
+
* so importing modules never write to stdout by accident.
|
|
7
|
+
*/
|
|
8
|
+
export declare const getOutput: () => Output;
|
|
9
|
+
/** Replace the output, e.g., once flags are parsed, or from a test. */
|
|
10
|
+
export declare const setOutput: (nextOutput: Output) => void;
|
|
11
|
+
/** Restore the default output. Intended for tests. */
|
|
12
|
+
export declare const resetOutput: () => void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createOutput } from './create-output.js';
|
|
2
|
+
let output = null;
|
|
3
|
+
/**
|
|
4
|
+
* The output used by the CLI.
|
|
5
|
+
*
|
|
6
|
+
* Defaults to a `text` output bound to the real process streams,
|
|
7
|
+
* so importing modules never write to stdout by accident.
|
|
8
|
+
*/
|
|
9
|
+
export const getOutput = () => {
|
|
10
|
+
output ??= createOutput();
|
|
11
|
+
return output;
|
|
12
|
+
};
|
|
13
|
+
/** Replace the output, e.g., once flags are parsed, or from a test. */
|
|
14
|
+
export const setOutput = (nextOutput) => {
|
|
15
|
+
output = nextOutput;
|
|
16
|
+
};
|
|
17
|
+
/** Restore the default output. Intended for tests. */
|
|
18
|
+
export const resetOutput = () => {
|
|
19
|
+
output = null;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=get-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-output.js","sourceRoot":"","sources":["../../src/lib/output/get-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAe,MAAM,oBAAoB,CAAA;AAE9D,IAAI,MAAM,GAAkB,IAAI,CAAA;AAEhC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAW,EAAE;IACpC,MAAM,KAAK,YAAY,EAAE,CAAA;IACzB,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,uEAAuE;AACvE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,UAAkB,EAAQ,EAAE;IACpD,MAAM,GAAG,UAAU,CAAA;AACrB,CAAC,CAAA;AAED,sDAAsD;AACtD,MAAM,CAAC,MAAM,WAAW,GAAG,GAAS,EAAE;IACpC,MAAM,GAAG,IAAI,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OutputFormat } from './create-output.js';
|
|
2
|
+
export interface ResolveOutputFormatOptions {
|
|
3
|
+
/** Whether stdout is a terminal. */
|
|
4
|
+
isTty?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Whether to write machine readable output.
|
|
8
|
+
*
|
|
9
|
+
* An explicit `--json` or `--no-json` wins, otherwise the CLI writes JSON
|
|
10
|
+
* whenever stdout is piped or redirected, and pretty output at a terminal.
|
|
11
|
+
*
|
|
12
|
+
* This reads the arguments rather than the parsed args because `--json` is
|
|
13
|
+
* declared as a boolean flag, so that it never consumes the argument after
|
|
14
|
+
* it, and a boolean cannot tell `--no-json` apart from not passing anything.
|
|
15
|
+
*/
|
|
16
|
+
export declare const resolveOutputFormat: (argv: string[], { isTty }?: ResolveOutputFormatOptions) => OutputFormat;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether to write machine readable output.
|
|
3
|
+
*
|
|
4
|
+
* An explicit `--json` or `--no-json` wins, otherwise the CLI writes JSON
|
|
5
|
+
* whenever stdout is piped or redirected, and pretty output at a terminal.
|
|
6
|
+
*
|
|
7
|
+
* This reads the arguments rather than the parsed args because `--json` is
|
|
8
|
+
* declared as a boolean flag, so that it never consumes the argument after
|
|
9
|
+
* it, and a boolean cannot tell `--no-json` apart from not passing anything.
|
|
10
|
+
*/
|
|
11
|
+
export const resolveOutputFormat = (argv, { isTty = false } = {}) => {
|
|
12
|
+
const flag = argv.filter((arg) => arg === '--json' || arg === '--no-json');
|
|
13
|
+
// The last one wins, matching how the argument parser resolves repeats.
|
|
14
|
+
switch (flag[flag.length - 1]) {
|
|
15
|
+
case '--json':
|
|
16
|
+
return 'json';
|
|
17
|
+
case '--no-json':
|
|
18
|
+
return 'text';
|
|
19
|
+
default:
|
|
20
|
+
return isTty ? 'text' : 'json';
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=resolve-output-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-output-format.js","sourceRoot":"","sources":["../../src/lib/output/resolve-output-format.ts"],"names":[],"mappings":"AAOA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,IAAc,EACd,EAAE,KAAK,GAAG,KAAK,KAAiC,EAAE,EACpC,EAAE;IAChB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,WAAW,CAAC,CAAA;IAE1E,wEAAwE;IACxE,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QAC9B,KAAK,QAAQ;YACX,OAAO,MAAM,CAAA;QACf,KAAK,WAAW;YACd,OAAO,MAAM,CAAA;QACf;YACE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;IAClC,CAAC;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface SelectResponsePayloadOptions {
|
|
2
|
+
/**
|
|
3
|
+
* The response key for the endpoint, e.g., `devices` for `/devices/list`,
|
|
4
|
+
* usually taken from the API blueprint.
|
|
5
|
+
*
|
|
6
|
+
* When omitted, every top level field except {@link metaKeys} is kept.
|
|
7
|
+
*/
|
|
8
|
+
responseKey?: string | null | undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Reduce an API response body to the response key and pagination.
|
|
12
|
+
*
|
|
13
|
+
* The CLI never reports other top level fields: they are details of the
|
|
14
|
+
* transport, so including them would leak into anything parsing stdout.
|
|
15
|
+
*/
|
|
16
|
+
export declare const selectResponsePayload: (data: unknown, { responseKey }?: SelectResponsePayloadOptions) => unknown;
|
|
@@ -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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type CommandSpec } from './command-spec.js';
|
|
2
|
+
/**
|
|
3
|
+
* Render the help guide for a command path, or `null` when no command or
|
|
4
|
+
* group goes by that path.
|
|
5
|
+
*
|
|
6
|
+
* An empty path is the guide for `seam` itself.
|
|
7
|
+
*/
|
|
8
|
+
export declare const renderHelp: (path: string[], spec: CommandSpec) => string | null;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import commandLineUsage, {} from 'command-line-usage';
|
|
2
|
+
import { findCommand, findGroup, } from './command-spec.js';
|
|
3
|
+
/**
|
|
4
|
+
* Render the help guide for a command path, or `null` when no command or
|
|
5
|
+
* group goes by that path.
|
|
6
|
+
*
|
|
7
|
+
* An empty path is the guide for `seam` itself.
|
|
8
|
+
*/
|
|
9
|
+
export const renderHelp = (path, spec) => {
|
|
10
|
+
const group = findGroup(spec, path);
|
|
11
|
+
if (group != null)
|
|
12
|
+
return commandLineUsage(groupSections(group, spec));
|
|
13
|
+
const command = findCommand(spec, path);
|
|
14
|
+
if (command != null)
|
|
15
|
+
return commandLineUsage(commandSections(command, spec));
|
|
16
|
+
return null;
|
|
17
|
+
};
|
|
18
|
+
const overview = 'Every seam command runs as soon as every required property is given, and otherwise prompts you for what is missing with helpful suggestions. Pass -i to always review properties first, or -y to never be prompted.';
|
|
19
|
+
const outputSection = {
|
|
20
|
+
header: 'Output',
|
|
21
|
+
content: [
|
|
22
|
+
'Only the response is written to stdout, so it is safe to pipe. Prompts, progress, and other information are written to stderr.',
|
|
23
|
+
'The response is trimmed to the response key and pagination.',
|
|
24
|
+
'Request params may be piped or redirected in as a JSON object. Params given as arguments win over params read from stdin.',
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
const examples = [
|
|
28
|
+
{ name: 'seam', summary: 'Interactively select commands to execute.' },
|
|
29
|
+
{ name: 'seam login', summary: 'Login to Seam.' },
|
|
30
|
+
{ name: 'seam wizard', summary: 'Set up Seam in the current project.' },
|
|
31
|
+
{ name: 'seam select workspace', summary: 'Select your workspace.' },
|
|
32
|
+
{
|
|
33
|
+
name: 'seam connect-webviews create',
|
|
34
|
+
summary: 'Create a connect webview to connect devices.',
|
|
35
|
+
},
|
|
36
|
+
{ name: 'seam devices list', summary: 'List devices in your workspace.' },
|
|
37
|
+
{
|
|
38
|
+
name: 'seam devices list {bold --interactive}',
|
|
39
|
+
summary: 'Review and edit filters before listing devices.',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'seam devices list {bold --non-interactive}',
|
|
43
|
+
summary: 'List devices, failing instead of prompting.',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'seam locks unlock-door {bold --device-id} $MY_DOOR',
|
|
47
|
+
summary: 'Unlock a lock.',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "seam access-codes create {bold --code} '1234' {bold --name} 'My Code'",
|
|
51
|
+
summary: 'Create an access code.',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'seam devices list > devices.json',
|
|
55
|
+
summary: 'Write the response to a file as JSON.',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'cat params.json | seam locks unlock-door',
|
|
59
|
+
summary: 'Pipe request params in as JSON.',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'seam completion bash',
|
|
63
|
+
summary: 'Print a shell completion script for bash, fish, or zsh.',
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
const groupSections = (group, spec) => {
|
|
67
|
+
const isRoot = group.path.length === 0;
|
|
68
|
+
const name = ['seam', ...group.path].join(' ');
|
|
69
|
+
return [
|
|
70
|
+
isRoot
|
|
71
|
+
? { header: 'Seam CLI', content: overview }
|
|
72
|
+
: { header: name, content: `Commands under ${name}.` },
|
|
73
|
+
{ header: 'Usage', content: `${name} <command> [options]` },
|
|
74
|
+
...commandSectionsForGroup(group, isRoot),
|
|
75
|
+
optionSection(spec.globalFlags),
|
|
76
|
+
...(isRoot
|
|
77
|
+
? [outputSection, { header: 'Command List Examples', content: examples }]
|
|
78
|
+
: []),
|
|
79
|
+
{ content: `Run '${name} <command> --help' to see a command in detail.` },
|
|
80
|
+
];
|
|
81
|
+
};
|
|
82
|
+
const commandSectionsForGroup = (group, isRoot) => {
|
|
83
|
+
const content = (subcommands) => subcommands.map(({ name, description }) => ({ name, summary: description }));
|
|
84
|
+
// The root guide separates the commands of the CLI itself from the commands
|
|
85
|
+
// that call the Seam API. Anywhere deeper the split adds nothing: a group
|
|
86
|
+
// holds commands of one kind.
|
|
87
|
+
if (!isRoot) {
|
|
88
|
+
return [{ header: 'Commands', content: content(group.subcommands) }];
|
|
89
|
+
}
|
|
90
|
+
const cli = group.subcommands.filter(({ kind }) => kind === 'cli');
|
|
91
|
+
const api = group.subcommands.filter(({ kind }) => kind === 'api');
|
|
92
|
+
return [
|
|
93
|
+
{ header: 'Commands', content: content(cli) },
|
|
94
|
+
{ header: 'API Commands', content: content(api) },
|
|
95
|
+
].filter((section) => section.content.length > 0);
|
|
96
|
+
};
|
|
97
|
+
const commandSections = (command, spec) => {
|
|
98
|
+
const name = ['seam', ...command.path].join(' ');
|
|
99
|
+
const hasFlags = command.flags.length > 0;
|
|
100
|
+
return [
|
|
101
|
+
{
|
|
102
|
+
header: name,
|
|
103
|
+
content: [command.title, command.description].filter((line) => line !== ''),
|
|
104
|
+
},
|
|
105
|
+
{ header: 'Usage', content: `${name} [options]` },
|
|
106
|
+
// The command's own parameters are what the request is made of, so keep
|
|
107
|
+
// them apart from the options every seam command takes.
|
|
108
|
+
...(hasFlags ? [optionSection(command.flags, 'Parameters')] : []),
|
|
109
|
+
optionSection(spec.globalFlags),
|
|
110
|
+
...(hasFlags
|
|
111
|
+
? [
|
|
112
|
+
{
|
|
113
|
+
content: 'Any required parameter left out is prompted for interactively.',
|
|
114
|
+
},
|
|
115
|
+
]
|
|
116
|
+
: []),
|
|
117
|
+
];
|
|
118
|
+
};
|
|
119
|
+
const optionSection = (flags, header = 'Options') => ({
|
|
120
|
+
header,
|
|
121
|
+
optionList: flags.map(toOptionDefinition),
|
|
122
|
+
});
|
|
123
|
+
const maxDocumentedValues = 8;
|
|
124
|
+
const toOptionDefinition = (flag) => {
|
|
125
|
+
const description = [
|
|
126
|
+
flag.isRequired ? '{bold [required]}' : '',
|
|
127
|
+
flag.description,
|
|
128
|
+
describeValues(flag),
|
|
129
|
+
]
|
|
130
|
+
.filter((part) => part !== '')
|
|
131
|
+
.join(' ');
|
|
132
|
+
return {
|
|
133
|
+
// command-line-usage renders a nameless option as the short form alone.
|
|
134
|
+
name: flag.long ?? '',
|
|
135
|
+
...(flag.short == null ? {} : { alias: flag.short }),
|
|
136
|
+
// A flag with no value must be typed as a boolean, or the guide labels it
|
|
137
|
+
// as taking a string.
|
|
138
|
+
type: flag.takesValue ? String : Boolean,
|
|
139
|
+
...(flag.takesValue ? { typeLabel: '{underline value}' } : {}),
|
|
140
|
+
description,
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
const describeValues = (flag) => {
|
|
144
|
+
if (flag.values.length === 0)
|
|
145
|
+
return '';
|
|
146
|
+
const shown = flag.values.slice(0, maxDocumentedValues).join(', ');
|
|
147
|
+
const rest = flag.values.length - maxDocumentedValues;
|
|
148
|
+
return rest > 0 ? `One of: ${shown}, and ${rest} more.` : `One of: ${shown}.`;
|
|
149
|
+
};
|
|
150
|
+
//# sourceMappingURL=render-help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-help.js","sourceRoot":"","sources":["../src/lib/render-help.ts"],"names":[],"mappings":"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"}
|
package/lib/util/cli-args.d.ts
CHANGED
|
@@ -15,6 +15,11 @@ export type Interactivity = 'auto' | 'interactive' | 'non-interactive';
|
|
|
15
15
|
* and are therefore not command parameters.
|
|
16
16
|
*/
|
|
17
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[];
|
|
18
23
|
/**
|
|
19
24
|
* Thrown when the CLI needs input it cannot prompt for.
|
|
20
25
|
*/
|
|
@@ -22,7 +27,17 @@ export declare class NonInteractiveError extends Error {
|
|
|
22
27
|
name: string;
|
|
23
28
|
}
|
|
24
29
|
export declare const parseCliArgs: (argv: string[]) => ParsedArgs;
|
|
25
|
-
export
|
|
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;
|
|
26
41
|
/**
|
|
27
42
|
* Render a parameter name as the argument used to set it,
|
|
28
43
|
* e.g., `device_id` as `--device-id`.
|
package/lib/util/cli-args.js
CHANGED
|
@@ -9,6 +9,19 @@ export const interactivityFlags = [
|
|
|
9
9
|
'interactive',
|
|
10
10
|
'i',
|
|
11
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
|
+
];
|
|
12
25
|
/**
|
|
13
26
|
* Thrown when the CLI needs input it cannot prompt for.
|
|
14
27
|
*/
|
|
@@ -17,12 +30,12 @@ export class NonInteractiveError extends Error {
|
|
|
17
30
|
}
|
|
18
31
|
export const parseCliArgs = (argv) => parseArgs(argv, {
|
|
19
32
|
string: ['code'],
|
|
20
|
-
boolean: ['non-interactive', 'interactive'],
|
|
33
|
+
boolean: ['non-interactive', 'interactive', 'json'],
|
|
21
34
|
// Deliberately not aliased to -n, which is reserved for a future
|
|
22
35
|
// --dry-run flag.
|
|
23
36
|
alias: { 'non-interactive': 'y', interactive: 'i' },
|
|
24
37
|
});
|
|
25
|
-
export const getInteractivity = (args) => {
|
|
38
|
+
export const getInteractivity = (args, { canPrompt = true } = {}) => {
|
|
26
39
|
const isNonInteractive = args['non_interactive'] === true || args['y'] === true;
|
|
27
40
|
const isInteractive = args['interactive'] === true || args['i'] === true;
|
|
28
41
|
if (isNonInteractive && isInteractive) {
|
|
@@ -30,8 +43,11 @@ export const getInteractivity = (args) => {
|
|
|
30
43
|
}
|
|
31
44
|
if (isNonInteractive)
|
|
32
45
|
return 'non-interactive';
|
|
46
|
+
// An explicit --interactive still asks, and fails loudly if it cannot.
|
|
33
47
|
if (isInteractive)
|
|
34
48
|
return 'interactive';
|
|
49
|
+
if (!canPrompt)
|
|
50
|
+
return 'non-interactive';
|
|
35
51
|
return 'auto';
|
|
36
52
|
};
|
|
37
53
|
/**
|
package/lib/util/cli-args.js.map
CHANGED
|
@@ -1 +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;;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,CAAC;
|
|
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"}
|