@zuplo/cli 7.5.1 → 7.5.3

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 (47) hide show
  1. package/node_modules/@inquirer/checkbox/dist/index.d.ts +12 -1
  2. package/node_modules/@inquirer/checkbox/package.json +4 -4
  3. package/node_modules/@inquirer/confirm/README.md +23 -0
  4. package/node_modules/@inquirer/confirm/dist/index.d.ts +26 -2
  5. package/node_modules/@inquirer/confirm/dist/index.js +40 -14
  6. package/node_modules/@inquirer/confirm/package.json +4 -4
  7. package/node_modules/@inquirer/core/dist/lib/create-prompt.d.ts +10 -3
  8. package/node_modules/@inquirer/core/dist/lib/make-theme.js +1 -0
  9. package/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.d.ts +2 -3
  10. package/node_modules/@inquirer/core/dist/lib/theme.d.ts +1 -1
  11. package/node_modules/@inquirer/core/package.json +3 -3
  12. package/node_modules/@inquirer/editor/dist/index.d.ts +9 -1
  13. package/node_modules/@inquirer/editor/package.json +4 -4
  14. package/node_modules/@inquirer/expand/dist/index.d.ts +12 -1
  15. package/node_modules/@inquirer/expand/package.json +4 -4
  16. package/node_modules/@inquirer/input/dist/index.d.ts +13 -1
  17. package/node_modules/@inquirer/input/package.json +4 -4
  18. package/node_modules/@inquirer/number/dist/index.d.ts +11 -1
  19. package/node_modules/@inquirer/number/package.json +4 -4
  20. package/node_modules/@inquirer/password/README.md +24 -6
  21. package/node_modules/@inquirer/password/dist/index.d.ts +9 -1
  22. package/node_modules/@inquirer/password/dist/index.js +27 -8
  23. package/node_modules/@inquirer/password/package.json +4 -4
  24. package/node_modules/@inquirer/rawlist/dist/index.d.ts +8 -1
  25. package/node_modules/@inquirer/rawlist/package.json +4 -4
  26. package/node_modules/@inquirer/search/dist/index.d.ts +12 -1
  27. package/node_modules/@inquirer/search/package.json +4 -4
  28. package/node_modules/@inquirer/select/dist/index.d.ts +9 -1
  29. package/node_modules/@inquirer/select/package.json +4 -4
  30. package/node_modules/@inquirer/type/dist/utils.d.ts +8 -3
  31. package/node_modules/@inquirer/type/package.json +3 -2
  32. package/node_modules/@posthog/types/dist/posthog-config.d.ts +14 -2
  33. package/node_modules/@posthog/types/dist/posthog-config.d.ts.map +1 -1
  34. package/node_modules/@posthog/types/package.json +1 -1
  35. package/node_modules/@posthog/types/src/posthog-config.ts +15 -1
  36. package/node_modules/@zuplo/core/package.json +1 -1
  37. package/node_modules/@zuplo/graphql/package.json +1 -1
  38. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  39. package/node_modules/@zuplo/otel/package.json +1 -1
  40. package/node_modules/@zuplo/runtime/out/esm/{chunk-LVTBALLF.js → chunk-HEFHZ2HU.js} +92 -92
  41. package/node_modules/@zuplo/runtime/out/esm/chunk-HEFHZ2HU.js.map +1 -0
  42. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  43. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
  44. package/node_modules/@zuplo/runtime/package.json +1 -1
  45. package/package.json +11 -11
  46. package/node_modules/@zuplo/runtime/out/esm/chunk-LVTBALLF.js.map +0 -1
  47. /package/node_modules/@zuplo/runtime/out/esm/{chunk-LVTBALLF.js.LEGAL.txt → chunk-HEFHZ2HU.js.LEGAL.txt} +0 -0
@@ -41,6 +41,17 @@ type NormalizedChoice<Value> = {
41
41
  disabled: boolean | string;
42
42
  checked: boolean;
43
43
  };
44
+ type CheckboxConfig<Value = string> = {
45
+ message: string;
46
+ prefix?: string;
47
+ pageSize?: number;
48
+ choices: ReadonlyArray<Value | Choice<Value> | Separator>;
49
+ loop?: boolean;
50
+ required?: boolean;
51
+ validate?: (choices: readonly NormalizedChoice<Value>[]) => boolean | string | Promise<string | boolean>;
52
+ theme?: PartialDeep<Theme<CheckboxTheme>>;
53
+ shortcuts?: CheckboxShortcuts;
54
+ };
44
55
  declare const _default: <const Value>(config: {
45
56
  message: string;
46
57
  prefix?: string | undefined;
@@ -51,6 +62,6 @@ declare const _default: <const Value>(config: {
51
62
  validate?: ((choices: readonly NormalizedChoice<Value>[]) => boolean | string | Promise<string | boolean>) | undefined;
52
63
  theme?: PartialDeep<Theme<CheckboxTheme>> | undefined;
53
64
  shortcuts?: CheckboxShortcuts | undefined;
54
- }, context?: import("@inquirer/type").Context) => Promise<Value[]>;
65
+ } & CheckboxConfig<Value>, context?: import("@inquirer/type").Context) => Promise<Value[]>;
55
66
  export default _default;
56
67
  export { Separator } from '@inquirer/core';
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inquirer/checkbox",
3
- "version": "5.2.2",
3
+ "version": "5.2.3",
4
4
  "description": "Inquirer checkbox prompt",
5
5
  "keywords": [
6
6
  "answer",
@@ -68,9 +68,9 @@
68
68
  },
69
69
  "dependencies": {
70
70
  "@inquirer/ansi": "^2.0.7",
71
- "@inquirer/core": "^12.0.0",
71
+ "@inquirer/core": "^12.0.1",
72
72
  "@inquirer/figures": "^2.0.8",
73
- "@inquirer/type": "^4.0.7"
73
+ "@inquirer/type": "^4.1.0"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@repo/tsconfig": "0.0.0",
@@ -89,5 +89,5 @@
89
89
  },
90
90
  "main": "./dist/index.js",
91
91
  "types": "./dist/index.d.ts",
92
- "gitHead": "999706755afbdcae271f62decbd9bcd05560905b"
92
+ "gitHead": "51ac389603405e8f9f315ce49416153d95c5fefe"
93
93
  }
@@ -78,14 +78,37 @@ type Theme = {
78
78
  interval: number;
79
79
  frames: string[];
80
80
  };
81
+ keywords: {
82
+ yes: string;
83
+ no: string;
84
+ };
81
85
  style: {
82
86
  answer: (text: string) => string;
83
87
  message: (text: string, status: 'idle' | 'done' | 'loading') => string;
84
88
  defaultAnswer: (text: string) => string;
89
+ confirmDefault: (text: string) => string;
85
90
  };
86
91
  };
87
92
  ```
88
93
 
94
+ The `keywords` property defines the words accepted as "yes" and "no". Matching is
95
+ prefix-based and case-insensitive, and the first character of each word is shown in
96
+ the hint (e.g. `Y/n`). The matched word is also displayed once the prompt is answered.
97
+ Overriding `keywords` is how `@inquirer/i18n` localizes the prompt:
98
+
99
+ ```ts
100
+ confirm({
101
+ message: '¿Continuar?',
102
+ theme: {
103
+ keywords: { yes: 'Sí', no: 'No' },
104
+ },
105
+ });
106
+ ```
107
+
108
+ The `confirmDefault` style marks the character representing the default answer in the
109
+ hint. By default it uppercases the character (`Y/n`); for scripts without case
110
+ (e.g. Chinese) it highlights the character with a color instead.
111
+
89
112
  # License
90
113
 
91
114
  Copyright (c) 2023 Simon Boudrias (twitter: [@vaxilart](https://twitter.com/Vaxilart))<br/>
@@ -4,7 +4,31 @@ type ConfirmConfig = {
4
4
  message: string;
5
5
  default?: boolean | undefined;
6
6
  transformer?: (value: boolean) => string;
7
- theme?: PartialDeep<Theme>;
7
+ theme?: PartialDeep<Theme<ConfirmTheme>>;
8
8
  };
9
- declare const _default: import("@inquirer/type").Prompt<boolean, ConfirmConfig>;
9
+ type ConfirmTheme = {
10
+ /**
11
+ * Words accepted as "yes" and "no" answers. Matching is prefix-based and
12
+ * case-insensitive, and the first character of each word is shown in the
13
+ * hint. These words are also displayed once the prompt is answered.
14
+ */
15
+ keywords: {
16
+ yes: string;
17
+ no: string;
18
+ };
19
+ style: {
20
+ /**
21
+ * Style the character representing the default answer in the hint (e.g.
22
+ * "Y/n"). Uppercases it by default; scripts without case (e.g. Chinese)
23
+ * are highlighted with a color instead.
24
+ */
25
+ confirmDefault: (text: string) => string;
26
+ };
27
+ };
28
+ declare const _default: import("@inquirer/type").Prompt<boolean, {
29
+ message: string;
30
+ default?: boolean | undefined | undefined;
31
+ transformer?: ((value: boolean) => string) | undefined;
32
+ theme?: PartialDeep<Theme<ConfirmTheme>> | undefined;
33
+ } & ConfirmConfig>;
10
34
  export default _default;
@@ -1,21 +1,47 @@
1
1
  import { createPrompt, useState, useKeypress, isEnterKey, isTabKey, usePrefix, makeTheme, } from '@inquirer/core';
2
- function getBooleanValue(value, defaultValue) {
3
- let answer = defaultValue !== false;
4
- if (/^(y|yes)/i.test(value))
5
- answer = true;
6
- else if (/^(n|no)/i.test(value))
7
- answer = false;
8
- return answer;
9
- }
10
- function boolToString(value) {
11
- return value ? 'Yes' : 'No';
12
- }
2
+ import { styleText } from 'node:util';
3
+ const confirmTheme = {
4
+ keywords: {
5
+ yes: 'Yes',
6
+ no: 'No',
7
+ },
8
+ style: {
9
+ confirmDefault: (text) => {
10
+ const first = text[0] ?? '';
11
+ if (first.toLowerCase() === first.toUpperCase()) {
12
+ return styleText('cyan', text);
13
+ }
14
+ return first.toUpperCase() + text.slice(1);
15
+ },
16
+ },
17
+ };
13
18
  export default createPrompt((config, done) => {
14
- const { transformer = boolToString } = config;
15
19
  const [status, setStatus] = useState('idle');
16
20
  const [value, setValue] = useState('');
17
- const theme = makeTheme(config.theme);
21
+ const theme = makeTheme(confirmTheme, config.theme);
18
22
  const prefix = usePrefix({ status, theme });
23
+ const { yes, no } = theme.keywords;
24
+ // The hint shows the first character of each label, lowercased; the default
25
+ // side is then uppercased (or colored) by `confirmDefault`.
26
+ const yesHint = (yes[0] ?? '').toLowerCase();
27
+ const noHint = (no[0] ?? '').toLowerCase();
28
+ const hint = config.default === false
29
+ ? `${yesHint}/${theme.style.confirmDefault(noHint)}`
30
+ : `${theme.style.confirmDefault(yesHint)}/${noHint}`;
31
+ function boolToString(value) {
32
+ return value ? yes : no;
33
+ }
34
+ const { transformer = boolToString } = config;
35
+ function getBooleanValue(value, defaultValue) {
36
+ const v = value.toLowerCase();
37
+ if (v === '')
38
+ return defaultValue !== false;
39
+ if (yes.toLowerCase().startsWith(v))
40
+ return true;
41
+ if (no.toLowerCase().startsWith(v))
42
+ return false;
43
+ return defaultValue !== false;
44
+ }
19
45
  useKeypress((key, rl) => {
20
46
  if (status !== 'idle')
21
47
  return;
@@ -41,7 +67,7 @@ export default createPrompt((config, done) => {
41
67
  formattedValue = theme.style.answer(value);
42
68
  }
43
69
  else {
44
- defaultValue = ` ${theme.style.defaultAnswer(config.default === false ? 'y/N' : 'Y/n')}`;
70
+ defaultValue = ` ${theme.style.defaultAnswer(hint)}`;
45
71
  }
46
72
  const message = theme.style.message(config.message, status);
47
73
  return `${prefix} ${message}${defaultValue} ${formattedValue}`;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inquirer/confirm",
3
- "version": "6.2.0",
3
+ "version": "6.3.0",
4
4
  "description": "Inquirer confirm prompt",
5
5
  "keywords": [
6
6
  "answer",
@@ -67,8 +67,8 @@
67
67
  "tsc": "tsc"
68
68
  },
69
69
  "dependencies": {
70
- "@inquirer/core": "^12.0.0",
71
- "@inquirer/type": "^4.0.7"
70
+ "@inquirer/core": "^12.0.1",
71
+ "@inquirer/type": "^4.1.0"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@repo/tsconfig": "0.0.0",
@@ -87,5 +87,5 @@
87
87
  },
88
88
  "main": "./dist/index.js",
89
89
  "types": "./dist/index.d.ts",
90
- "gitHead": "999706755afbdcae271f62decbd9bcd05560905b"
90
+ "gitHead": "51ac389603405e8f9f315ce49416153d95c5fefe"
91
91
  }
@@ -1,4 +1,11 @@
1
- import { type Prompt, type Prettify } from '@inquirer/type';
2
- type ViewFunction<Value, Config> = (config: Prettify<Config>, done: (value: Value) => void) => string | [string, string | undefined];
3
- export declare function createPrompt<Value, Config>(view: ViewFunction<Value, Config>): Prompt<Value, Config>;
1
+ import { type Prompt } from '@inquirer/type';
2
+ type ViewFunction<Value, Config> = (config: Config, done: (value: Value) => void) => string | [string, string | undefined];
3
+ /**
4
+ * Expand the top-level keys of a type for better IDE display, without
5
+ * recursing into nested fields (so generic values stay compatible).
6
+ */
7
+ type ShallowPrettify<T> = {
8
+ [K in keyof T]: T[K];
9
+ } & {};
10
+ export declare function createPrompt<Value, Config>(view: ViewFunction<Value, Config>): Prompt<Value, ShallowPrettify<Config> & Config>;
4
11
  export {};
@@ -28,5 +28,6 @@ export function makeTheme(...themes) {
28
28
  getDefaultTheme(),
29
29
  ...themes.filter((theme) => theme != null),
30
30
  ];
31
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
31
32
  return deepMerge(...themesToMerge);
32
33
  }
@@ -1,14 +1,13 @@
1
- import type { Prettify } from '@inquirer/type';
2
1
  export declare function usePagination<T>({ items, active, renderItem, pageSize, loop, }: {
3
2
  items: ReadonlyArray<T>;
4
3
  /** The index of the active item. */
5
4
  active: number;
6
5
  /** Renders an item as part of a page. */
7
- renderItem: (layout: Prettify<{
6
+ renderItem: (layout: {
8
7
  item: T;
9
8
  index: number;
10
9
  isActive: boolean;
11
- }>) => string;
10
+ }) => string;
12
11
  /** The size of the page. */
13
12
  pageSize: number;
14
13
  /** Allows creating an infinitely looping list. `true` if unspecified. */
@@ -160,7 +160,7 @@ type DefaultTheme = {
160
160
  key: (text: string) => string;
161
161
  };
162
162
  };
163
- export type Theme<Extension extends object = object> = Prettify<Extension & DefaultTheme>;
163
+ export type Theme<Extension extends object = object> = Extension & DefaultTheme;
164
164
  export declare const defaultTheme: DefaultTheme;
165
165
  export declare function getDefaultTheme(): DefaultTheme;
166
166
  export {};
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inquirer/core",
3
- "version": "12.0.0",
3
+ "version": "12.0.1",
4
4
  "description": "Core Inquirer prompt API",
5
5
  "keywords": [
6
6
  "answer",
@@ -69,7 +69,7 @@
69
69
  "dependencies": {
70
70
  "@inquirer/ansi": "^2.0.7",
71
71
  "@inquirer/figures": "^2.0.8",
72
- "@inquirer/type": "^4.0.7",
72
+ "@inquirer/type": "^4.1.0",
73
73
  "cli-width": "^4.1.0",
74
74
  "fast-wrap-ansi": "^0.2.0",
75
75
  "mute-stream": "^3.0.0",
@@ -94,5 +94,5 @@
94
94
  },
95
95
  "main": "./dist/index.js",
96
96
  "types": "./dist/index.d.ts",
97
- "gitHead": "999706755afbdcae271f62decbd9bcd05560905b"
97
+ "gitHead": "51ac389603405e8f9f315ce49416153d95c5fefe"
98
98
  }
@@ -17,5 +17,13 @@ type EditorConfig = {
17
17
  file?: FileOptions;
18
18
  theme?: PartialDeep<Theme<EditorTheme>>;
19
19
  };
20
- declare const _default: import("@inquirer/type").Prompt<string, EditorConfig>;
20
+ declare const _default: import("@inquirer/type").Prompt<string, {
21
+ message: string;
22
+ default?: string | undefined | undefined;
23
+ postfix?: string | undefined;
24
+ waitForUserInput?: boolean | undefined;
25
+ validate?: ((value: string) => boolean | string | Promise<string | boolean>) | undefined;
26
+ file?: FileOptions | undefined;
27
+ theme?: PartialDeep<Theme<EditorTheme>> | undefined;
28
+ } & EditorConfig>;
21
29
  export default _default;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inquirer/editor",
3
- "version": "5.3.0",
3
+ "version": "5.3.1",
4
4
  "description": "Inquirer multiline editor prompt",
5
5
  "keywords": [
6
6
  "answer",
@@ -67,9 +67,9 @@
67
67
  "tsc": "tsc"
68
68
  },
69
69
  "dependencies": {
70
- "@inquirer/core": "^12.0.0",
70
+ "@inquirer/core": "^12.0.1",
71
71
  "@inquirer/external-editor": "^3.0.4",
72
- "@inquirer/type": "^4.0.7"
72
+ "@inquirer/type": "^4.1.0"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@repo/tsconfig": "0.0.0",
@@ -88,5 +88,5 @@
88
88
  },
89
89
  "main": "./dist/index.js",
90
90
  "types": "./dist/index.d.ts",
91
- "gitHead": "999706755afbdcae271f62decbd9bcd05560905b"
91
+ "gitHead": "51ac389603405e8f9f315ce49416153d95c5fefe"
92
92
  }
@@ -9,6 +9,17 @@ type Choice<Value> = {
9
9
  name: string;
10
10
  value: Value;
11
11
  };
12
+ type ExpandConfig<Value = string> = {
13
+ message: string;
14
+ choices: readonly (Separator | {
15
+ key: Key;
16
+ name: Value & string;
17
+ value?: never;
18
+ } | Choice<Value>)[];
19
+ default?: Key | 'h';
20
+ expanded?: boolean;
21
+ theme?: PartialDeep<Theme>;
22
+ };
12
23
  declare const expand: <const Value>(config: {
13
24
  message: string;
14
25
  choices: readonly (Separator | {
@@ -19,6 +30,6 @@ declare const expand: <const Value>(config: {
19
30
  default?: (Key | "h") | undefined;
20
31
  expanded?: boolean | undefined;
21
32
  theme?: PartialDeep<Theme> | undefined;
22
- }, context?: import("@inquirer/type").Context) => Promise<Value>;
33
+ } & ExpandConfig<Value>, context?: import("@inquirer/type").Context) => Promise<Value>;
23
34
  export default expand;
24
35
  export { Separator } from '@inquirer/core';
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inquirer/expand",
3
- "version": "5.1.2",
3
+ "version": "5.1.3",
4
4
  "description": "Inquirer checkbox prompt",
5
5
  "keywords": [
6
6
  "answer",
@@ -67,8 +67,8 @@
67
67
  "tsc": "tsc"
68
68
  },
69
69
  "dependencies": {
70
- "@inquirer/core": "^12.0.0",
71
- "@inquirer/type": "^4.0.7"
70
+ "@inquirer/core": "^12.0.1",
71
+ "@inquirer/type": "^4.1.0"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@repo/tsconfig": "0.0.0",
@@ -87,5 +87,5 @@
87
87
  },
88
88
  "main": "./dist/index.js",
89
89
  "types": "./dist/index.d.ts",
90
- "gitHead": "999706755afbdcae271f62decbd9bcd05560905b"
90
+ "gitHead": "51ac389603405e8f9f315ce49416153d95c5fefe"
91
91
  }
@@ -16,5 +16,17 @@ type InputConfig = {
16
16
  pattern?: RegExp;
17
17
  patternError?: string;
18
18
  };
19
- declare const _default: import("@inquirer/type").Prompt<string, InputConfig>;
19
+ declare const _default: import("@inquirer/type").Prompt<string, {
20
+ message: string;
21
+ default?: string | undefined | undefined;
22
+ prefill?: "tab" | "editable" | undefined;
23
+ required?: boolean | undefined;
24
+ transformer?: ((value: string, { isFinal }: {
25
+ isFinal: boolean;
26
+ }) => string) | undefined;
27
+ validate?: ((value: string) => boolean | string | Promise<string | boolean>) | undefined;
28
+ theme?: PartialDeep<Theme<InputTheme>> | undefined;
29
+ pattern?: RegExp | undefined;
30
+ patternError?: string | undefined;
31
+ } & InputConfig>;
20
32
  export default _default;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inquirer/input",
3
- "version": "5.1.3",
3
+ "version": "5.1.4",
4
4
  "description": "Inquirer input text prompt",
5
5
  "keywords": [
6
6
  "answer",
@@ -67,8 +67,8 @@
67
67
  "tsc": "tsc"
68
68
  },
69
69
  "dependencies": {
70
- "@inquirer/core": "^12.0.0",
71
- "@inquirer/type": "^4.0.7"
70
+ "@inquirer/core": "^12.0.1",
71
+ "@inquirer/type": "^4.1.0"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@repo/tsconfig": "0.0.0",
@@ -87,5 +87,5 @@
87
87
  },
88
88
  "main": "./dist/index.js",
89
89
  "types": "./dist/index.d.ts",
90
- "gitHead": "999706755afbdcae271f62decbd9bcd05560905b"
90
+ "gitHead": "51ac389603405e8f9f315ce49416153d95c5fefe"
91
91
  }
@@ -1,5 +1,15 @@
1
1
  import { type Theme } from '@inquirer/core';
2
2
  import type { PartialDeep } from '@inquirer/type';
3
+ type NumberConfig<Required extends boolean = boolean> = {
4
+ message: string;
5
+ default?: number | undefined;
6
+ min?: number;
7
+ max?: number;
8
+ step?: number | 'any';
9
+ required?: Required;
10
+ validate?: (value: Required extends true ? number : number | undefined) => boolean | string | Promise<string | boolean>;
11
+ theme?: PartialDeep<Theme>;
12
+ };
3
13
  declare const _default: <Required extends boolean>(config: {
4
14
  message: string;
5
15
  default?: number | undefined | undefined;
@@ -9,5 +19,5 @@ declare const _default: <Required extends boolean>(config: {
9
19
  required?: Required | undefined;
10
20
  validate?: ((value: Required extends true ? number : number | undefined) => boolean | string | Promise<string | boolean>) | undefined;
11
21
  theme?: PartialDeep<Theme> | undefined;
12
- }, context?: import("@inquirer/type").Context) => Promise<Required extends true ? number : number | undefined>;
22
+ } & NumberConfig<Required>, context?: import("@inquirer/type").Context) => Promise<Required extends true ? number : number | undefined>;
13
23
  export default _default;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inquirer/number",
3
- "version": "4.2.0",
3
+ "version": "4.2.1",
4
4
  "description": "Inquirer number prompt",
5
5
  "keywords": [
6
6
  "answer",
@@ -67,8 +67,8 @@
67
67
  "tsc": "tsc"
68
68
  },
69
69
  "dependencies": {
70
- "@inquirer/core": "^12.0.0",
71
- "@inquirer/type": "^4.0.7"
70
+ "@inquirer/core": "^12.0.1",
71
+ "@inquirer/type": "^4.1.0"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@repo/tsconfig": "0.0.0",
@@ -87,5 +87,5 @@
87
87
  },
88
88
  "main": "./dist/index.js",
89
89
  "types": "./dist/index.d.ts",
90
- "gitHead": "999706755afbdcae271f62decbd9bcd05560905b"
90
+ "gitHead": "51ac389603405e8f9f315ce49416153d95c5fefe"
91
91
  }
@@ -60,12 +60,13 @@ const answer = await password({ message: 'Enter your name' });
60
60
 
61
61
  ## Options
62
62
 
63
- | Property | Type | Required | Description |
64
- | -------- | ----------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
65
- | message | `string` | yes | The question to ask |
66
- | mask | `boolean` | no | Show a `*` mask over the input or keep it transparent |
67
- | validate | `string => boolean \| string \| Promise<boolean \| string>` | no | On submit, validate the filtered answered content. When returning a string, it'll be used as the error message displayed to the user. Note: returning a rejected promise, we'll assume a code error happened and crash. |
68
- | theme | [See Theming](#Theming) | no | Customize look of the prompt. |
63
+ | Property | Type | Required | Description |
64
+ | ---------- | ----------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
65
+ | message | `string` | yes | The question to ask |
66
+ | mask | `boolean \| string` | no | Show a `*` mask over the input, use a custom mask character, or keep it transparent. |
67
+ | toggleMask | `boolean` | no | Allow the user to press `ctrl+t` to temporarily reveal the typed value. Defaults to `true`; set to `false` to disable both the shortcut and its help line. |
68
+ | validate | `string => boolean \| string \| Promise<boolean \| string>` | no | On submit, validate the filtered answered content. When returning a string, it'll be used as the error message displayed to the user. Note: returning a rejected promise, we'll assume a code error happened and crash. |
69
+ | theme | [See Theming](#Theming) | no | Customize look of the prompt. |
69
70
 
70
71
  ## Theming
71
72
 
@@ -83,10 +84,27 @@ type Theme = {
83
84
  message: (text: string, status: 'idle' | 'done' | 'loading') => string;
84
85
  error: (text: string) => string;
85
86
  help: (text: string) => string;
87
+ maskedText: string;
88
+ keysHelpTip: (keys: [key: string, action: string][]) => string | undefined;
86
89
  };
87
90
  };
88
91
  ```
89
92
 
93
+ `maskedText` is the inline tip shown when `mask` is off and the value is hidden (default: `[input is masked]`).
94
+
95
+ ### `theme.style.keysHelpTip`
96
+
97
+ This function customizes the keyboard shortcut help displayed on the line below the prompt. It receives `[['ctrl+t', 'toggle visibility']]` while the value is hidden. Use it to change the formatting or localize the action, or return `undefined` to hide the help line entirely.
98
+
99
+ ```js
100
+ theme: {
101
+ style: {
102
+ keysHelpTip: (keys) =>
103
+ keys.map(([key, action]) => `${key}: ${action}`).join(' | '),
104
+ },
105
+ }
106
+ ```
107
+
90
108
  # License
91
109
 
92
110
  Copyright (c) 2023 Simon Boudrias (twitter: [@vaxilart](https://twitter.com/Vaxilart))<br/>
@@ -3,13 +3,21 @@ import type { PartialDeep } from '@inquirer/type';
3
3
  type PasswordTheme = {
4
4
  style: {
5
5
  maskedText: string;
6
+ keysHelpTip: (keys: [key: string, action: string][]) => string | undefined;
6
7
  };
7
8
  };
8
9
  type PasswordConfig = {
9
10
  message: string;
10
11
  mask?: boolean | string;
12
+ toggleMask?: boolean;
11
13
  validate?: (value: string) => boolean | string | Promise<string | boolean>;
12
14
  theme?: PartialDeep<Theme<PasswordTheme>>;
13
15
  };
14
- declare const _default: import("@inquirer/type").Prompt<string, PasswordConfig>;
16
+ declare const _default: import("@inquirer/type").Prompt<string, {
17
+ message: string;
18
+ mask?: boolean | string | undefined;
19
+ toggleMask?: boolean | undefined;
20
+ validate?: ((value: string) => boolean | string | Promise<string | boolean>) | undefined;
21
+ theme?: PartialDeep<Theme<PasswordTheme>> | undefined;
22
+ } & PasswordConfig>;
15
23
  export default _default;
@@ -1,16 +1,21 @@
1
1
  import { createPrompt, useState, useKeypress, usePrefix, isEnterKey, makeTheme, } from '@inquirer/core';
2
2
  import { cursorHide } from '@inquirer/ansi';
3
+ import { styleText } from 'node:util';
3
4
  const passwordTheme = {
4
5
  style: {
5
6
  maskedText: '[input is masked]',
7
+ keysHelpTip: (keys) => keys
8
+ .map(([key, action]) => `${styleText('bold', key)} ${styleText('dim', action)}`)
9
+ .join(styleText('dim', ' • ')),
6
10
  },
7
11
  };
8
12
  export default createPrompt((config, done) => {
9
- const { validate = () => true } = config;
13
+ const { toggleMask = true, validate = () => true } = config;
10
14
  const theme = makeTheme(passwordTheme, config.theme);
11
15
  const [status, setStatus] = useState('idle');
12
16
  const [errorMsg, setError] = useState();
13
17
  const [value, setValue] = useState('');
18
+ const [revealed, setRevealed] = useState(false);
14
19
  const prefix = usePrefix({ status, theme });
15
20
  useKeypress(async (key, rl) => {
16
21
  // Ignore keypress while our prompt is doing other processing.
@@ -34,27 +39,41 @@ export default createPrompt((config, done) => {
34
39
  setStatus('idle');
35
40
  }
36
41
  }
42
+ else if (toggleMask && key.ctrl && key.name === 't') {
43
+ setRevealed((prev) => !prev);
44
+ }
37
45
  else {
38
46
  setValue(rl.line);
39
47
  setError(undefined);
40
48
  }
41
49
  });
42
50
  const message = theme.style.message(config.message, status);
51
+ const showPlaintext = toggleMask && revealed && status === 'idle';
43
52
  let formattedValue = '';
44
- let helpTip;
45
- if (config.mask) {
53
+ if (showPlaintext) {
54
+ formattedValue = value;
55
+ }
56
+ else if (config.mask) {
46
57
  const maskChar = typeof config.mask === 'string' ? config.mask : '*';
47
58
  formattedValue = maskChar.repeat(value.length);
48
59
  }
49
60
  else if (status !== 'done') {
50
- helpTip = `${theme.style.help(theme.style.maskedText)}${cursorHide}`;
61
+ formattedValue = theme.style.help(theme.style.maskedText);
51
62
  }
52
63
  if (status === 'done') {
53
64
  formattedValue = theme.style.answer(formattedValue);
54
65
  }
55
- let error = '';
56
- if (errorMsg) {
57
- error = theme.style.error(errorMsg);
66
+ else if (!config.mask) {
67
+ formattedValue += cursorHide;
58
68
  }
59
- return [[prefix, message, config.mask ? formattedValue : helpTip].join(' '), error];
69
+ const content = [prefix, message, formattedValue].filter(Boolean).join(' ');
70
+ const bottomContent = [
71
+ errorMsg ? theme.style.error(errorMsg) : '',
72
+ toggleMask && status === 'idle'
73
+ ? theme.style.keysHelpTip([['ctrl+t', 'toggle visibility']])
74
+ : '',
75
+ ]
76
+ .filter(Boolean)
77
+ .join('\n');
78
+ return [content, bottomContent];
60
79
  });