()
| 36 | // Each prompt should get its own context so the closure-captured `lastSearch` |
| 37 | // doesn't bleed between prompts. |
| 38 | export function createSearchSelectContext() { |
| 39 | let lastSearch = ''; |
| 40 | let isLoading = false; |
| 41 | return { |
| 42 | trackSearch: (search: string | undefined): void => { |
| 43 | lastSearch = search ?? ''; |
| 44 | }, |
| 45 | setLoading: (loading: boolean): void => { |
| 46 | isLoading = loading; |
| 47 | }, |
| 48 | theme: { |
| 49 | style: { |
| 50 | renderSelectedOptions: <T>( |
| 51 | selectedOptions: ReadonlyArray<{ focused?: boolean; name?: string; value: T }>, |
| 52 | ): string => { |
| 53 | if (selectedOptions.length === 0) { |
| 54 | return ''; |
| 55 | } |
| 56 | const items = selectedOptions.map((option) => |
| 57 | option.focused |
| 58 | ? chalk.inverse(option.name || String(option.value)) |
| 59 | : (option.name || String(option.value)) |
| 60 | ); |
| 61 | return items.join(', ') + ','; |
| 62 | }, |
| 63 | emptyText: (text: string) => |
| 64 | (lastSearch && !isLoading) ? `${chalk.blue('ℹ')} ${chalk.bold(text)}` : '', |
| 65 | }, |
| 66 | }, |
| 67 | }; |
| 68 | } |
| 69 | |
| 70 | export function generateSecret(bytes: number): string { |
| 71 | return randomBytes(bytes).toString('base64'); |
no outgoing calls
no test coverage detected