@shopify/cli-kit 4.7.0 → 4.8.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.
@@ -12,7 +12,7 @@ function AutocompletePrompt({ message, choices, infoTable, onSubmit, search, has
12
12
  const complete = useComplete();
13
13
  const [searchTerm, setSearchTerm] = useState('');
14
14
  const [searchResults, setSearchResults] = useState(choices);
15
- const canSearch = choices.length > MIN_NUMBER_OF_ITEMS_FOR_SEARCH;
15
+ const canSearch = initialHasMorePages || choices.length > MIN_NUMBER_OF_ITEMS_FOR_SEARCH;
16
16
  const [hasMorePages, setHasMorePages] = useState(initialHasMorePages);
17
17
  const { promptState, setPromptState, answer, setAnswer } = usePrompt({
18
18
  initialAnswer: undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"AutocompletePrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["import {SelectInput, SelectInputProps, Item as SelectItem} from './SelectInput.js'\nimport {InfoTableProps} from './Prompts/InfoTable.js'\nimport {TextInput} from './TextInput.js'\nimport {InfoMessageProps} from './Prompts/InfoMessage.js'\nimport {Message, PromptLayout} from './Prompts/PromptLayout.js'\nimport {throttle} from '../../../../public/common/function.js'\nimport {AbortSignal} from '../../../../public/node/abort.js'\nimport {useComplete} from '../../ui.js'\nimport usePrompt, {PromptState} from '../hooks/use-prompt.js'\n\nimport React, {ReactElement, useCallback, useEffect, useRef, useState} from 'react'\nimport {Box} from 'ink'\n\nexport interface SearchResults<T> {\n data: SelectItem<T>[]\n meta?: {\n hasNextPage: boolean\n }\n}\n\nexport interface AutocompletePromptProps<T> {\n message: Message\n choices: SelectInputProps<T>['items']\n onSubmit: (value: T) => void\n infoTable?: InfoTableProps['table']\n hasMorePages?: boolean\n search: (term: string) => Promise<SearchResults<T>>\n abortSignal?: AbortSignal\n infoMessage?: InfoMessageProps['message']\n groupOrder?: string[]\n /**\n * Throttle window in milliseconds applied to the search callback. Defaults to 400ms,\n * which is appropriate for remote/paginated backends. In-memory consumers (where the\n * search callback resolves synchronously) can pass 0 for instant filtering on every\n * keystroke.\n */\n searchDebounceMs?: number\n}\n\nconst MIN_NUMBER_OF_ITEMS_FOR_SEARCH = 5\nconst DEFAULT_SEARCH_DEBOUNCE_MS = 400\n\nfunction AutocompletePrompt<T>({\n message,\n choices,\n infoTable,\n onSubmit,\n search,\n hasMorePages: initialHasMorePages = false,\n abortSignal,\n infoMessage,\n groupOrder,\n searchDebounceMs = DEFAULT_SEARCH_DEBOUNCE_MS,\n}: React.PropsWithChildren<AutocompletePromptProps<T>>): ReactElement | null {\n const complete = useComplete()\n const [searchTerm, setSearchTerm] = useState('')\n const [searchResults, setSearchResults] = useState<SelectItem<T>[]>(choices)\n const canSearch = choices.length > MIN_NUMBER_OF_ITEMS_FOR_SEARCH\n const [hasMorePages, setHasMorePages] = useState(initialHasMorePages)\n const {promptState, setPromptState, answer, setAnswer} = usePrompt<SelectItem<T> | undefined>({\n initialAnswer: undefined,\n })\n\n const paginatedSearch = useCallback(\n async (term: string) => {\n const results = await search(term)\n return results\n },\n [search],\n )\n\n const submitAnswer = useCallback(\n (answer: SelectItem<T>) => {\n if (promptState === PromptState.Idle) {\n setAnswer(answer)\n setPromptState(PromptState.Submitted)\n }\n },\n [promptState, setAnswer, setPromptState],\n )\n\n useEffect(() => {\n if (promptState === PromptState.Submitted && answer) {\n setSearchTerm('')\n onSubmit(answer.value)\n complete()\n }\n }, [answer, onSubmit, promptState, complete])\n\n const setLoadingWhenSlow = useRef<NodeJS.Timeout>()\n\n // we want to set it each time so that searchTermRef always tracks searchTerm,\n // this is NOT the same as writing useRef(searchTerm)\n const searchTermRef = useRef('')\n searchTermRef.current = searchTerm\n\n // Keep current values in refs to avoid stale closures\n const choicesRef = useRef(choices)\n choicesRef.current = choices\n const initialHasPagesRef = useRef(initialHasMorePages)\n initialHasPagesRef.current = initialHasMorePages\n\n // useMemo ensures debounceSearch is not recreated on every render\n const debounceSearch = React.useMemo(\n () =>\n throttle(\n (term: string) => {\n setLoadingWhenSlow.current = setTimeout(() => {\n setPromptState(PromptState.Loading)\n }, 100)\n paginatedSearch(term)\n .then((result) => {\n // while we were waiting for the promise to resolve, the user\n // has emptied the search term, so we want to show the default\n // choices instead\n if (searchTermRef.current.length === 0) {\n setSearchResults(choicesRef.current)\n setHasMorePages(initialHasPagesRef.current)\n } else {\n setSearchResults(result.data)\n setHasMorePages(result.meta?.hasNextPage ?? false)\n }\n\n setPromptState(PromptState.Idle)\n })\n .catch(() => {\n setPromptState(PromptState.Error)\n })\n .finally(() => {\n clearTimeout(setLoadingWhenSlow.current)\n })\n },\n searchDebounceMs,\n {leading: true, trailing: true},\n ),\n [paginatedSearch, setPromptState, searchDebounceMs],\n )\n\n return (\n <PromptLayout\n message={message}\n state={promptState}\n infoTable={infoTable}\n infoMessage={infoMessage}\n abortSignal={abortSignal}\n header={\n promptState !== PromptState.Submitted && canSearch ? (\n <Box marginLeft={3}>\n <TextInput\n value={searchTerm}\n onChange={(term) => {\n setSearchTerm(term)\n // Update ref immediately so that the debounceSearch's .then()\n // callback sees the current term. With React 19's automatic\n // batching, the render (which normally updates the ref) is\n // deferred, so without this the ref would be stale when the\n // search Promise resolves.\n searchTermRef.current = term\n\n if (term.length > 0) {\n debounceSearch(term)\n } else {\n debounceSearch.cancel()\n setPromptState(PromptState.Idle)\n setSearchResults(choices)\n }\n }}\n placeholder=\"Type to search...\"\n />\n </Box>\n ) : null\n }\n submittedAnswerLabel={answer?.label}\n input={\n <SelectInput\n items={searchResults}\n initialItems={choices}\n enableShortcuts={false}\n emptyMessage=\"No results found.\"\n highlightedTerm={searchTerm}\n loading={promptState === PromptState.Loading}\n errorMessage={\n promptState === PromptState.Error\n ? 'There has been an error while searching. Please try again later.'\n : undefined\n }\n hasMorePages={hasMorePages}\n morePagesMessage=\"Find what you're looking for by typing its name.\"\n onSubmit={submitAnswer}\n groupOrder={groupOrder}\n />\n }\n />\n )\n}\n\nexport {AutocompletePrompt}\n"]}
1
+ {"version":3,"file":"AutocompletePrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["import {SelectInput, SelectInputProps, Item as SelectItem} from './SelectInput.js'\nimport {InfoTableProps} from './Prompts/InfoTable.js'\nimport {TextInput} from './TextInput.js'\nimport {InfoMessageProps} from './Prompts/InfoMessage.js'\nimport {Message, PromptLayout} from './Prompts/PromptLayout.js'\nimport {throttle} from '../../../../public/common/function.js'\nimport {AbortSignal} from '../../../../public/node/abort.js'\nimport {useComplete} from '../../ui.js'\nimport usePrompt, {PromptState} from '../hooks/use-prompt.js'\n\nimport React, {ReactElement, useCallback, useEffect, useRef, useState} from 'react'\nimport {Box} from 'ink'\n\nexport interface SearchResults<T> {\n data: SelectItem<T>[]\n meta?: {\n hasNextPage: boolean\n }\n}\n\nexport interface AutocompletePromptProps<T> {\n message: Message\n choices: SelectInputProps<T>['items']\n onSubmit: (value: T) => void\n infoTable?: InfoTableProps['table']\n hasMorePages?: boolean\n search: (term: string) => Promise<SearchResults<T>>\n abortSignal?: AbortSignal\n infoMessage?: InfoMessageProps['message']\n groupOrder?: string[]\n /**\n * Throttle window in milliseconds applied to the search callback. Defaults to 400ms,\n * which is appropriate for remote/paginated backends. In-memory consumers (where the\n * search callback resolves synchronously) can pass 0 for instant filtering on every\n * keystroke.\n */\n searchDebounceMs?: number\n}\n\nconst MIN_NUMBER_OF_ITEMS_FOR_SEARCH = 5\nconst DEFAULT_SEARCH_DEBOUNCE_MS = 400\n\nfunction AutocompletePrompt<T>({\n message,\n choices,\n infoTable,\n onSubmit,\n search,\n hasMorePages: initialHasMorePages = false,\n abortSignal,\n infoMessage,\n groupOrder,\n searchDebounceMs = DEFAULT_SEARCH_DEBOUNCE_MS,\n}: React.PropsWithChildren<AutocompletePromptProps<T>>): ReactElement | null {\n const complete = useComplete()\n const [searchTerm, setSearchTerm] = useState('')\n const [searchResults, setSearchResults] = useState<SelectItem<T>[]>(choices)\n const canSearch = initialHasMorePages || choices.length > MIN_NUMBER_OF_ITEMS_FOR_SEARCH\n const [hasMorePages, setHasMorePages] = useState(initialHasMorePages)\n const {promptState, setPromptState, answer, setAnswer} = usePrompt<SelectItem<T> | undefined>({\n initialAnswer: undefined,\n })\n\n const paginatedSearch = useCallback(\n async (term: string) => {\n const results = await search(term)\n return results\n },\n [search],\n )\n\n const submitAnswer = useCallback(\n (answer: SelectItem<T>) => {\n if (promptState === PromptState.Idle) {\n setAnswer(answer)\n setPromptState(PromptState.Submitted)\n }\n },\n [promptState, setAnswer, setPromptState],\n )\n\n useEffect(() => {\n if (promptState === PromptState.Submitted && answer) {\n setSearchTerm('')\n onSubmit(answer.value)\n complete()\n }\n }, [answer, onSubmit, promptState, complete])\n\n const setLoadingWhenSlow = useRef<NodeJS.Timeout>()\n\n // we want to set it each time so that searchTermRef always tracks searchTerm,\n // this is NOT the same as writing useRef(searchTerm)\n const searchTermRef = useRef('')\n searchTermRef.current = searchTerm\n\n // Keep current values in refs to avoid stale closures\n const choicesRef = useRef(choices)\n choicesRef.current = choices\n const initialHasPagesRef = useRef(initialHasMorePages)\n initialHasPagesRef.current = initialHasMorePages\n\n // useMemo ensures debounceSearch is not recreated on every render\n const debounceSearch = React.useMemo(\n () =>\n throttle(\n (term: string) => {\n setLoadingWhenSlow.current = setTimeout(() => {\n setPromptState(PromptState.Loading)\n }, 100)\n paginatedSearch(term)\n .then((result) => {\n // while we were waiting for the promise to resolve, the user\n // has emptied the search term, so we want to show the default\n // choices instead\n if (searchTermRef.current.length === 0) {\n setSearchResults(choicesRef.current)\n setHasMorePages(initialHasPagesRef.current)\n } else {\n setSearchResults(result.data)\n setHasMorePages(result.meta?.hasNextPage ?? false)\n }\n\n setPromptState(PromptState.Idle)\n })\n .catch(() => {\n setPromptState(PromptState.Error)\n })\n .finally(() => {\n clearTimeout(setLoadingWhenSlow.current)\n })\n },\n searchDebounceMs,\n {leading: true, trailing: true},\n ),\n [paginatedSearch, setPromptState, searchDebounceMs],\n )\n\n return (\n <PromptLayout\n message={message}\n state={promptState}\n infoTable={infoTable}\n infoMessage={infoMessage}\n abortSignal={abortSignal}\n header={\n promptState !== PromptState.Submitted && canSearch ? (\n <Box marginLeft={3}>\n <TextInput\n value={searchTerm}\n onChange={(term) => {\n setSearchTerm(term)\n // Update ref immediately so that the debounceSearch's .then()\n // callback sees the current term. With React 19's automatic\n // batching, the render (which normally updates the ref) is\n // deferred, so without this the ref would be stale when the\n // search Promise resolves.\n searchTermRef.current = term\n\n if (term.length > 0) {\n debounceSearch(term)\n } else {\n debounceSearch.cancel()\n setPromptState(PromptState.Idle)\n setSearchResults(choices)\n }\n }}\n placeholder=\"Type to search...\"\n />\n </Box>\n ) : null\n }\n submittedAnswerLabel={answer?.label}\n input={\n <SelectInput\n items={searchResults}\n initialItems={choices}\n enableShortcuts={false}\n emptyMessage=\"No results found.\"\n highlightedTerm={searchTerm}\n loading={promptState === PromptState.Loading}\n errorMessage={\n promptState === PromptState.Error\n ? 'There has been an error while searching. Please try again later.'\n : undefined\n }\n hasMorePages={hasMorePages}\n morePagesMessage=\"Find what you're looking for by typing its name.\"\n onSubmit={submitAnswer}\n groupOrder={groupOrder}\n />\n }\n />\n )\n}\n\nexport {AutocompletePrompt}\n"]}
@@ -98,6 +98,20 @@ describe('AutocompletePrompt', async () => {
98
98
  `);
99
99
  expect(onEnter).toHaveBeenCalledWith(items[1].value);
100
100
  });
101
+ test('searches and selects later-page items from a short paginated list', async () => {
102
+ const onSubmit = vi.fn();
103
+ const search = vi.fn(async (term) => ({
104
+ data: term === 'l' ? [{ label: 'later-page-store', value: 'later-page-store' }] : [],
105
+ }));
106
+ const renderInstance = render(React.createElement(AutocompletePrompt, { message: "Select a store", choices: [{ label: 'first-page-store', value: 'first-page-store' }], onSubmit: onSubmit, hasMorePages: true, search: search, searchDebounceMs: 0 }));
107
+ expect(renderInstance.lastFrame()).toContain('ype to search...');
108
+ await waitForInputsToBeReady();
109
+ await sendInputAndWaitForContent(renderInstance, 'ater-page-store', 'l');
110
+ await sendInputAndWait(renderInstance, 10, ARROW_DOWN);
111
+ await sendInputAndWaitForChange(renderInstance, ENTER);
112
+ expect(search).toHaveBeenCalledWith('l');
113
+ expect(onSubmit).toHaveBeenCalledWith('later-page-store');
114
+ });
101
115
  test('renders groups', async () => {
102
116
  const items = [
103
117
  { label: 'first', value: 'first', group: 'Automations' },
@@ -1 +1 @@
1
- {"version":3,"file":"AutocompletePrompt.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {AutocompletePrompt, SearchResults} from './AutocompletePrompt.js'\nimport {\n getLastFrameAfterUnmount,\n sendInputAndWait,\n sendInputAndWaitForChange,\n sendInputAndWaitForContent,\n waitForInputsToBeReady,\n render,\n} from '../../testing/ui.js'\nimport {Stdout} from '../../ui.js'\nimport {AbortController} from '../../../../public/node/abort.js'\nimport {beforeEach, describe, expect, test, vi} from 'vitest'\n\nimport React from 'react'\nimport {useStdout} from 'ink'\n\nvi.mock('ink', async () => {\n const original: any = await vi.importActual('ink')\n return {\n ...original,\n useStdout: vi.fn(),\n }\n})\n\nconst ARROW_DOWN = '\\u001B[B'\nconst ENTER = '\\r'\nconst DELETE = '\\u007F'\n\nconst DATABASE = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n {label: 'eleventh', value: 'eleventh'},\n {label: 'twelfth', value: 'twelfth'},\n {label: 'thirteenth', value: 'thirteenth'},\n {label: 'fourteenth', value: 'fourteenth'},\n {label: 'fifteenth', value: 'fifteenth'},\n {label: 'sixteenth', value: 'sixteenth'},\n {label: 'seventeenth', value: 'seventeenth'},\n {label: 'eighteenth', value: 'eighteenth'},\n {label: 'nineteenth', value: 'nineteenth'},\n {label: 'twentieth', value: 'twentieth'},\n {label: 'twenty-first', value: 'twenty-first'},\n {label: 'twenty-second', value: 'twenty-second'},\n {label: 'twenty-third', value: 'twenty-third'},\n {label: 'twenty-fourth', value: 'twenty-fourth'},\n {label: 'twenty-fifth', value: 'twenty-fifth'},\n {label: 'twenty-sixth', value: 'twenty-sixth'},\n {label: 'twenty-seventh', value: 'twenty-seventh'},\n {label: 'twenty-eighth', value: 'twenty-eighth'},\n {label: 'twenty-ninth', value: 'twenty-ninth'},\n {label: 'thirtieth', value: 'thirtieth'},\n {label: 'thirty-first', value: 'thirty-first'},\n {label: 'thirty-second', value: 'thirty-second'},\n {label: 'thirty-third', value: 'thirty-third'},\n {label: 'thirty-fourth', value: 'thirty-fourth'},\n {label: 'thirty-fifth', value: 'thirty-fifth'},\n {label: 'thirty-sixth', value: 'thirty-sixth'},\n {label: 'thirty-seventh', value: 'thirty-seventh'},\n {label: 'thirty-eighth', value: 'thirty-eighth'},\n {label: 'thirty-ninth', value: 'thirty-ninth'},\n {label: 'fortieth', value: 'fortieth'},\n {label: 'forty-first', value: 'forty-first'},\n {label: 'forty-second', value: 'forty-second'},\n {label: 'forty-third', value: 'forty-third'},\n {label: 'forty-fourth', value: 'forty-fourth'},\n {label: 'forty-fifth', value: 'forty-fifth'},\n {label: 'forty-sixth', value: 'forty-sixth'},\n {label: 'forty-seventh', value: 'forty-seventh'},\n {label: 'forty-eighth', value: 'forty-eighth'},\n {label: 'forty-ninth', value: 'forty-ninth'},\n {label: 'fiftieth', value: 'fiftieth'},\n]\n\nbeforeEach(() => {\n vi.mocked(useStdout).mockReturnValue({\n stdout: new Stdout({\n columns: 80,\n rows: 80,\n }) as any,\n write: () => {},\n })\n})\n\ndescribe('AutocompletePrompt', async () => {\n test('choose an answer', async () => {\n const onEnter = vi.fn()\n\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n ]\n\n const infoTable = {Add: ['new-ext'], Remove: ['integrated-demand-ext', 'order-discount']}\n\n const renderInstance = render(\n <AutocompletePrompt\n message={['Associate your project with the org', {userInput: 'Castile Ventures'}, {char: '?'}]}\n choices={items}\n infoTable={infoTable}\n onSubmit={onEnter}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`\n \"? Associate your project with the org \u001b[36mCastile Ventures\u001b[39m?\n \u001b[36m✔\u001b[39m \u001b[36msecond\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith(items[1]!.value)\n })\n\n test('renders groups', async () => {\n const items = [\n {label: 'first', value: 'first', group: 'Automations'},\n {label: 'second', value: 'second', group: 'Automations'},\n {label: 'third', value: 'third', group: 'Merchant Admin'},\n {label: 'fourth', value: 'fourth', group: 'Merchant Admin'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[1mAutomations\u001b[22m\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n\n \u001b[1mMerchant Admin\u001b[22m\n third\n fourth\n\n \u001b[1mOther\u001b[22m\n fifth\n sixth\n seventh\n eighth\n ninth\n tenth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('supports an info table', async () => {\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n ]\n\n const infoTable = {\n Add: ['new-ext'],\n Remove: ['integrated-demand-ext', 'order-discount'],\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n infoTable={infoTable}\n onSubmit={() => {}}\n search={() => Promise.resolve({data: []} as SearchResults<string>)}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n ┃ \\u001b[1mAdd\\u001b[22m\n ┃ • new-ext\n ┃\n ┃ \\u001b[1mRemove\\u001b[22m\n ┃ • integrated-demand-ext\n ┃ • order-discount\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('supports an info message', async () => {\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n ]\n\n const infoMessage = {\n title: {\n color: 'red',\n text: 'Info message title',\n },\n body: 'Info message body',\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n infoMessage={infoMessage}\n onSubmit={() => {}}\n search={() => Promise.resolve({data: []} as SearchResults<string>)}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n ┃ \u001b[31mInfo message title\u001b[39m\n ┃\n ┃ Info message body\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test(\"doesn't submit if there are no choices\", async () => {\n const onEnter = vi.fn()\n const searchPromise = Promise.resolve({\n data: [],\n } as SearchResults<string>)\n const search = () => {\n return searchPromise\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n\n await sendInputAndWaitForContent(renderInstance, 'No results found', 'a')\n // prompt doesn't change when enter is pressed\n await sendInputAndWait(renderInstance, 10, ENTER)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36ma\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[2mNo results found.\u001b[22m\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \u001b[2mTry again with a different keyword.\u001b[22m\n \"\n `)\n\n expect(onEnter).not.toHaveBeenCalled()\n })\n\n test('has a loading state', async () => {\n const onEnter = vi.fn()\n\n const search = () => {\n return new Promise<SearchResults<string>>((resolve) => {\n setTimeout(() => {\n resolve({data: [{label: 'a', value: 'b'}]})\n }, 2000)\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'Loading...', 'a')\n // prompt doesn't change when enter is pressed\n await new Promise((resolve) => setTimeout(resolve, 10))\n await sendInputAndWait(renderInstance, 10, ENTER)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36ma\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[2mLoading...\u001b[22m\n \"\n `)\n\n expect(onEnter).not.toHaveBeenCalled()\n })\n\n test('allows searching with pagination', async () => {\n const onEnter = vi.fn()\n\n const search = async (term: string) => {\n return {\n data: DATABASE.filter((item) => item.label.includes(term)),\n }\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mrst\u001b[39m \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrteenth \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfteenth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxteenth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghteenth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mneteenth \u001b[46m \u001b[49m\n twent\u001b[1mi\u001b[22meth \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n twenty-th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n twenty-s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n twenty-e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n twenty-n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrtieth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-first \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-second \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-third \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fourth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fifth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-sixth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForContent(renderInstance, 'ype to search', DELETE)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mfth\u001b[39m \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrteenth \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfteenth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxteenth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghteenth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mneteenth \u001b[46m \u001b[49m\n twent\u001b[1mi\u001b[22meth \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n twenty-th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n twenty-s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n twenty-e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n twenty-n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrtieth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-first \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-second \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-third \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fourth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fifth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-sixth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n \u001b[36m✔\u001b[39m \u001b[36mfifth\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith('fifth')\n })\n\n test('allows searching with malformed regex', async () => {\n const onEnter = vi.fn()\n const db = [...DATABASE, {label: 'with\\\\slash', value: 'with\\\\slash'}]\n\n const search = async (term: string) => {\n return {\n data: db.filter((item) => item.label.includes(term)),\n }\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={db}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'slash', '\\\\')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\\\\\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mwith\\\\slash\u001b[39m\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('searchDebounceMs: 0 invokes search on every keystroke without throttling', async () => {\n const search = vi.fn(async (term: string) => ({\n data: DATABASE.filter((item) => item.label.includes(term)),\n }))\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n searchDebounceMs={0}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'f')\n await sendInputAndWaitForChange(renderInstance, 'i')\n await sendInputAndWaitForChange(renderInstance, 'r')\n\n // With the default 400ms throttle, three rapid keystrokes coalesce to ~2 calls\n // (leading + trailing edge). With searchDebounceMs=0, each keystroke fires.\n expect(search).toHaveBeenCalledTimes(3)\n expect(search).toHaveBeenNthCalledWith(1, 'f')\n expect(search).toHaveBeenNthCalledWith(2, 'fi')\n expect(search).toHaveBeenNthCalledWith(3, 'fir')\n })\n\n test('displays an error message if the search fails', async () => {\n const search = (_term: string) => {\n return Promise.reject(new Error('Something went wrong'))\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'There has been an error', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[31mThere has been an error while searching. Please try again later.\u001b[39m\n \"\n `)\n })\n\n test('immediately shows the initial items if the search is empty', async () => {\n const search = (term: string) => {\n return Promise.resolve({\n data: DATABASE.filter((item) => item.label.includes(term)),\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mrst\u001b[39m \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrteenth \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfteenth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxteenth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghteenth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mneteenth \u001b[46m \u001b[49m\n twent\u001b[1mi\u001b[22meth \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n twenty-th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n twenty-s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n twenty-e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n twenty-n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrtieth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-first \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-second \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-third \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fourth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fifth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-sixth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForContent(renderInstance, 'ype to search', DELETE)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('shows a message that indicates there are more results than shown', async () => {\n const search = (_term: string) => {\n return Promise.resolve({\n data: DATABASE,\n meta: {hasNextPage: true},\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n hasMorePages\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \u001b[1m1-50 of many\u001b[22m Find what you're looking for by typing its name.\n \"\n `)\n })\n\n test('adapts to the height of the container', async () => {\n vi.mocked(useStdout).mockReturnValue({\n stdout: new Stdout({rows: 10}) as any,\n write: () => {},\n })\n\n const items = [\n {label: 'first', value: 'first', group: 'Automations'},\n {label: 'second', value: 'second', group: 'Automations'},\n {label: 'third', value: 'third', group: 'Merchant Admin'},\n {label: 'fourth', value: 'fourth', group: 'Merchant Admin'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n hasMorePages\n search={() =>\n Promise.resolve({\n data: items,\n } as SearchResults<string>)\n }\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[1mAutomations\u001b[22m \\u001b[46m \\u001b[49m\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \\u001b[100m \\u001b[49m\n second \\u001b[100m \\u001b[49m\n \\u001b[100m \\u001b[49m\n \u001b[1mMerchant Admin\u001b[22m \\u001b[100m \\u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \u001b[1m1-10 of many\u001b[22m Find what you're looking for by typing its name.\n \"\n `)\n })\n\n test('abortController can be used to exit the prompt from outside', async () => {\n const items = [\n {label: 'a', value: 'a'},\n {label: 'b', value: 'b'},\n ]\n\n const abortController = new AbortController()\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n abortSignal={abortController.signal}\n />,\n )\n const promise = renderInstance.waitUntilExit()\n\n abortController.abort()\n\n // wait for the onAbort promise to resolve\n await new Promise((resolve) => setTimeout(resolve, 0))\n\n await expect(promise).resolves.toEqual(undefined)\n })\n})\n"]}
1
+ {"version":3,"file":"AutocompletePrompt.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {AutocompletePrompt, SearchResults} from './AutocompletePrompt.js'\nimport {\n getLastFrameAfterUnmount,\n sendInputAndWait,\n sendInputAndWaitForChange,\n sendInputAndWaitForContent,\n waitForInputsToBeReady,\n render,\n} from '../../testing/ui.js'\nimport {Stdout} from '../../ui.js'\nimport {AbortController} from '../../../../public/node/abort.js'\nimport {beforeEach, describe, expect, test, vi} from 'vitest'\n\nimport React from 'react'\nimport {useStdout} from 'ink'\n\nvi.mock('ink', async () => {\n const original: any = await vi.importActual('ink')\n return {\n ...original,\n useStdout: vi.fn(),\n }\n})\n\nconst ARROW_DOWN = '\\u001B[B'\nconst ENTER = '\\r'\nconst DELETE = '\\u007F'\n\nconst DATABASE = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n {label: 'eleventh', value: 'eleventh'},\n {label: 'twelfth', value: 'twelfth'},\n {label: 'thirteenth', value: 'thirteenth'},\n {label: 'fourteenth', value: 'fourteenth'},\n {label: 'fifteenth', value: 'fifteenth'},\n {label: 'sixteenth', value: 'sixteenth'},\n {label: 'seventeenth', value: 'seventeenth'},\n {label: 'eighteenth', value: 'eighteenth'},\n {label: 'nineteenth', value: 'nineteenth'},\n {label: 'twentieth', value: 'twentieth'},\n {label: 'twenty-first', value: 'twenty-first'},\n {label: 'twenty-second', value: 'twenty-second'},\n {label: 'twenty-third', value: 'twenty-third'},\n {label: 'twenty-fourth', value: 'twenty-fourth'},\n {label: 'twenty-fifth', value: 'twenty-fifth'},\n {label: 'twenty-sixth', value: 'twenty-sixth'},\n {label: 'twenty-seventh', value: 'twenty-seventh'},\n {label: 'twenty-eighth', value: 'twenty-eighth'},\n {label: 'twenty-ninth', value: 'twenty-ninth'},\n {label: 'thirtieth', value: 'thirtieth'},\n {label: 'thirty-first', value: 'thirty-first'},\n {label: 'thirty-second', value: 'thirty-second'},\n {label: 'thirty-third', value: 'thirty-third'},\n {label: 'thirty-fourth', value: 'thirty-fourth'},\n {label: 'thirty-fifth', value: 'thirty-fifth'},\n {label: 'thirty-sixth', value: 'thirty-sixth'},\n {label: 'thirty-seventh', value: 'thirty-seventh'},\n {label: 'thirty-eighth', value: 'thirty-eighth'},\n {label: 'thirty-ninth', value: 'thirty-ninth'},\n {label: 'fortieth', value: 'fortieth'},\n {label: 'forty-first', value: 'forty-first'},\n {label: 'forty-second', value: 'forty-second'},\n {label: 'forty-third', value: 'forty-third'},\n {label: 'forty-fourth', value: 'forty-fourth'},\n {label: 'forty-fifth', value: 'forty-fifth'},\n {label: 'forty-sixth', value: 'forty-sixth'},\n {label: 'forty-seventh', value: 'forty-seventh'},\n {label: 'forty-eighth', value: 'forty-eighth'},\n {label: 'forty-ninth', value: 'forty-ninth'},\n {label: 'fiftieth', value: 'fiftieth'},\n]\n\nbeforeEach(() => {\n vi.mocked(useStdout).mockReturnValue({\n stdout: new Stdout({\n columns: 80,\n rows: 80,\n }) as any,\n write: () => {},\n })\n})\n\ndescribe('AutocompletePrompt', async () => {\n test('choose an answer', async () => {\n const onEnter = vi.fn()\n\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n ]\n\n const infoTable = {Add: ['new-ext'], Remove: ['integrated-demand-ext', 'order-discount']}\n\n const renderInstance = render(\n <AutocompletePrompt\n message={['Associate your project with the org', {userInput: 'Castile Ventures'}, {char: '?'}]}\n choices={items}\n infoTable={infoTable}\n onSubmit={onEnter}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`\n \"? Associate your project with the org \u001b[36mCastile Ventures\u001b[39m?\n \u001b[36m✔\u001b[39m \u001b[36msecond\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith(items[1]!.value)\n })\n\n test('searches and selects later-page items from a short paginated list', async () => {\n const onSubmit = vi.fn()\n const search = vi.fn(async (term: string) => ({\n data: term === 'l' ? [{label: 'later-page-store', value: 'later-page-store'}] : [],\n }))\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Select a store\"\n choices={[{label: 'first-page-store', value: 'first-page-store'}]}\n onSubmit={onSubmit}\n hasMorePages\n search={search}\n searchDebounceMs={0}\n />,\n )\n\n expect(renderInstance.lastFrame()).toContain('ype to search...')\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'ater-page-store', 'l')\n await sendInputAndWait(renderInstance, 10, ARROW_DOWN)\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(search).toHaveBeenCalledWith('l')\n expect(onSubmit).toHaveBeenCalledWith('later-page-store')\n })\n\n test('renders groups', async () => {\n const items = [\n {label: 'first', value: 'first', group: 'Automations'},\n {label: 'second', value: 'second', group: 'Automations'},\n {label: 'third', value: 'third', group: 'Merchant Admin'},\n {label: 'fourth', value: 'fourth', group: 'Merchant Admin'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[1mAutomations\u001b[22m\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n\n \u001b[1mMerchant Admin\u001b[22m\n third\n fourth\n\n \u001b[1mOther\u001b[22m\n fifth\n sixth\n seventh\n eighth\n ninth\n tenth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('supports an info table', async () => {\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n ]\n\n const infoTable = {\n Add: ['new-ext'],\n Remove: ['integrated-demand-ext', 'order-discount'],\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n infoTable={infoTable}\n onSubmit={() => {}}\n search={() => Promise.resolve({data: []} as SearchResults<string>)}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n ┃ \\u001b[1mAdd\\u001b[22m\n ┃ • new-ext\n ┃\n ┃ \\u001b[1mRemove\\u001b[22m\n ┃ • integrated-demand-ext\n ┃ • order-discount\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('supports an info message', async () => {\n const items = [\n {label: 'first', value: 'first'},\n {label: 'second', value: 'second'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n ]\n\n const infoMessage = {\n title: {\n color: 'red',\n text: 'Info message title',\n },\n body: 'Info message body',\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n infoMessage={infoMessage}\n onSubmit={() => {}}\n search={() => Promise.resolve({data: []} as SearchResults<string>)}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n\n ┃ \u001b[31mInfo message title\u001b[39m\n ┃\n ┃ Info message body\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m\n second\n third\n fourth\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test(\"doesn't submit if there are no choices\", async () => {\n const onEnter = vi.fn()\n const searchPromise = Promise.resolve({\n data: [],\n } as SearchResults<string>)\n const search = () => {\n return searchPromise\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n\n await sendInputAndWaitForContent(renderInstance, 'No results found', 'a')\n // prompt doesn't change when enter is pressed\n await sendInputAndWait(renderInstance, 10, ENTER)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36ma\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[2mNo results found.\u001b[22m\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \u001b[2mTry again with a different keyword.\u001b[22m\n \"\n `)\n\n expect(onEnter).not.toHaveBeenCalled()\n })\n\n test('has a loading state', async () => {\n const onEnter = vi.fn()\n\n const search = () => {\n return new Promise<SearchResults<string>>((resolve) => {\n setTimeout(() => {\n resolve({data: [{label: 'a', value: 'b'}]})\n }, 2000)\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'Loading...', 'a')\n // prompt doesn't change when enter is pressed\n await new Promise((resolve) => setTimeout(resolve, 10))\n await sendInputAndWait(renderInstance, 10, ENTER)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36ma\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[2mLoading...\u001b[22m\n \"\n `)\n\n expect(onEnter).not.toHaveBeenCalled()\n })\n\n test('allows searching with pagination', async () => {\n const onEnter = vi.fn()\n\n const search = async (term: string) => {\n return {\n data: DATABASE.filter((item) => item.label.includes(term)),\n }\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mrst\u001b[39m \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrteenth \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfteenth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxteenth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghteenth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mneteenth \u001b[46m \u001b[49m\n twent\u001b[1mi\u001b[22meth \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n twenty-th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n twenty-s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n twenty-e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n twenty-n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrtieth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-first \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-second \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-third \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fourth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fifth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-sixth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForContent(renderInstance, 'ype to search', DELETE)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n await sendInputAndWaitForChange(renderInstance, ARROW_DOWN)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mfth\u001b[39m \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrteenth \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfteenth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxteenth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghteenth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mneteenth \u001b[46m \u001b[49m\n twent\u001b[1mi\u001b[22meth \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n twenty-th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n twenty-s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n twenty-e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n twenty-n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrtieth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-first \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-second \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-third \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fourth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fifth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-sixth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(getLastFrameAfterUnmount(renderInstance)).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures?\n \u001b[36m✔\u001b[39m \u001b[36mfifth\u001b[39m\n \"\n `)\n\n expect(onEnter).toHaveBeenCalledWith('fifth')\n })\n\n test('allows searching with malformed regex', async () => {\n const onEnter = vi.fn()\n const db = [...DATABASE, {label: 'with\\\\slash', value: 'with\\\\slash'}]\n\n const search = async (term: string) => {\n return {\n data: db.filter((item) => item.label.includes(term)),\n }\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={db}\n onSubmit={onEnter}\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'slash', '\\\\')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\\\\\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mwith\\\\slash\u001b[39m\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('searchDebounceMs: 0 invokes search on every keystroke without throttling', async () => {\n const search = vi.fn(async (term: string) => ({\n data: DATABASE.filter((item) => item.label.includes(term)),\n }))\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n searchDebounceMs={0}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'f')\n await sendInputAndWaitForChange(renderInstance, 'i')\n await sendInputAndWaitForChange(renderInstance, 'r')\n\n // With the default 400ms throttle, three rapid keystrokes coalesce to ~2 calls\n // (leading + trailing edge). With searchDebounceMs=0, each keystroke fires.\n expect(search).toHaveBeenCalledTimes(3)\n expect(search).toHaveBeenNthCalledWith(1, 'f')\n expect(search).toHaveBeenNthCalledWith(2, 'fi')\n expect(search).toHaveBeenNthCalledWith(3, 'fir')\n })\n\n test('displays an error message if the search fails', async () => {\n const search = (_term: string) => {\n return Promise.reject(new Error('Something went wrong'))\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'There has been an error', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[31mThere has been an error while searching. Please try again later.\u001b[39m\n \"\n `)\n })\n\n test('immediately shows the initial items if the search is empty', async () => {\n const search = (term: string) => {\n return Promise.resolve({\n data: DATABASE.filter((item) => item.label.includes(term)),\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n search={search}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForContent(renderInstance, 'th\u001b[1mi\u001b[22mrty-sixth', 'i')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36mi\u001b[46m█\u001b[49m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mf\u001b[1mi\u001b[22mrst\u001b[39m \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrteenth \u001b[46m \u001b[49m\n f\u001b[1mi\u001b[22mfteenth \u001b[46m \u001b[49m\n s\u001b[1mi\u001b[22mxteenth \u001b[46m \u001b[49m\n e\u001b[1mi\u001b[22mghteenth \u001b[46m \u001b[49m\n n\u001b[1mi\u001b[22mneteenth \u001b[46m \u001b[49m\n twent\u001b[1mi\u001b[22meth \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mrst \u001b[46m \u001b[49m\n twenty-th\u001b[1mi\u001b[22mrd \u001b[46m \u001b[49m\n twenty-f\u001b[1mi\u001b[22mfth \u001b[46m \u001b[49m\n twenty-s\u001b[1mi\u001b[22mxth \u001b[46m \u001b[49m\n twenty-e\u001b[1mi\u001b[22mghth \u001b[46m \u001b[49m\n twenty-n\u001b[1mi\u001b[22mnth \u001b[46m \u001b[49m\n th\u001b[1mi\u001b[22mrtieth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-first \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-second \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-third \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fourth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-fifth \u001b[100m \u001b[49m\n th\u001b[1mi\u001b[22mrty-sixth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n\n await sendInputAndWaitForContent(renderInstance, 'ype to search', DELETE)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \"\n `)\n })\n\n test('shows a message that indicates there are more results than shown', async () => {\n const search = (_term: string) => {\n return Promise.resolve({\n data: DATABASE,\n meta: {hasNextPage: true},\n })\n }\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={DATABASE}\n onSubmit={() => {}}\n hasMorePages\n search={search}\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \u001b[46m \u001b[49m\n second \u001b[46m \u001b[49m\n third \u001b[46m \u001b[49m\n fourth \u001b[46m \u001b[49m\n fifth \u001b[46m \u001b[49m\n sixth \u001b[46m \u001b[49m\n seventh \u001b[46m \u001b[49m\n eighth \u001b[46m \u001b[49m\n ninth \u001b[46m \u001b[49m\n tenth \u001b[46m \u001b[49m\n eleventh \u001b[46m \u001b[49m\n twelfth \u001b[46m \u001b[49m\n thirteenth \u001b[46m \u001b[49m\n fourteenth \u001b[100m \u001b[49m\n fifteenth \u001b[100m \u001b[49m\n sixteenth \u001b[100m \u001b[49m\n seventeenth \u001b[100m \u001b[49m\n eighteenth \u001b[100m \u001b[49m\n nineteenth \u001b[100m \u001b[49m\n twentieth \u001b[100m \u001b[49m\n twenty-first \u001b[100m \u001b[49m\n twenty-second \u001b[100m \u001b[49m\n twenty-third \u001b[100m \u001b[49m\n twenty-fourth \u001b[100m \u001b[49m\n twenty-fifth \u001b[100m \u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \u001b[1m1-50 of many\u001b[22m Find what you're looking for by typing its name.\n \"\n `)\n })\n\n test('adapts to the height of the container', async () => {\n vi.mocked(useStdout).mockReturnValue({\n stdout: new Stdout({rows: 10}) as any,\n write: () => {},\n })\n\n const items = [\n {label: 'first', value: 'first', group: 'Automations'},\n {label: 'second', value: 'second', group: 'Automations'},\n {label: 'third', value: 'third', group: 'Merchant Admin'},\n {label: 'fourth', value: 'fourth', group: 'Merchant Admin'},\n {label: 'fifth', value: 'fifth'},\n {label: 'sixth', value: 'sixth'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth'},\n {label: 'ninth', value: 'ninth'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n hasMorePages\n search={() =>\n Promise.resolve({\n data: items,\n } as SearchResults<string>)\n }\n />,\n )\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Associate your project with the org Castile Ventures? \u001b[36m\u001b[7mT\u001b[27m\u001b[2mype to search...\u001b[22m\u001b[39m\n\n \u001b[1mAutomations\u001b[22m \\u001b[46m \\u001b[49m\n \u001b[36m>\u001b[39m \u001b[36mfirst\u001b[39m \\u001b[100m \\u001b[49m\n second \\u001b[100m \\u001b[49m\n \\u001b[100m \\u001b[49m\n \u001b[1mMerchant Admin\u001b[22m \\u001b[100m \\u001b[49m\n\n \u001b[2mPress ↑↓ arrows to select, enter to confirm.\u001b[22m\n \u001b[1m1-10 of many\u001b[22m Find what you're looking for by typing its name.\n \"\n `)\n })\n\n test('abortController can be used to exit the prompt from outside', async () => {\n const items = [\n {label: 'a', value: 'a'},\n {label: 'b', value: 'b'},\n ]\n\n const abortController = new AbortController()\n\n const renderInstance = render(\n <AutocompletePrompt\n message=\"Associate your project with the org Castile Ventures?\"\n choices={items}\n onSubmit={() => {}}\n search={() =>\n Promise.resolve({\n data: [],\n } as SearchResults<string>)\n }\n abortSignal={abortController.signal}\n />,\n )\n const promise = renderInstance.waitUntilExit()\n\n abortController.abort()\n\n // wait for the onAbort promise to resolve\n await new Promise((resolve) => setTimeout(resolve, 0))\n\n await expect(promise).resolves.toEqual(undefined)\n })\n})\n"]}
@@ -1 +1 @@
1
- export declare const CLI_KIT_VERSION = "4.7.0";
1
+ export declare const CLI_KIT_VERSION = "4.8.0";
@@ -1,2 +1,2 @@
1
- export const CLI_KIT_VERSION = '4.7.0';
1
+ export const CLI_KIT_VERSION = '4.8.0';
2
2
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '4.7.0'\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '4.8.0'\n"]}
@@ -197,11 +197,17 @@ async function buildPayload({ config, errorMessage, exitMode, }) {
197
197
  }
198
198
  function sanitizePayload(payload) {
199
199
  const payloadString = JSON.stringify(payload);
200
- // Remove Theme Access passwords from the payload
200
+ // Redaction runs on the serialized payload, so a flag value that was quoted arrives with its quotes
201
+ // escaped. Every flag rule below matches that escaped form first, and its bare-value alternative
202
+ // treats a JSON escape as part of the value, so a value can never be redacted only halfway or leave
203
+ // behind a string that no longer parses.
201
204
  const sanitizedPayloadString = payloadString
202
205
  .replace(/shptka_\w*/g, '*****')
203
- .replace(/(--store-password(?:=|\s+))(?:"[^"]*"|'[^']*'|[^\s"]+)/g, '$1*****')
204
- .replace(/((?:store-password|SHOPIFY_FLAG_STORE_PASSWORD)\\?":\\?")[^"\\]*/g, '$1*****');
206
+ .replace(/(--store-password(?:=|\s+))(?:\\"[^"\\]*\\"|'[^']*'|(?:\\.|[^\s"\\])+)/g, '$1*****')
207
+ .replace(/((?:store-password|SHOPIFY_FLAG_STORE_PASSWORD)\\?":\\?")[^"\\]*/g, '$1*****')
208
+ .replace(/(--signup(?:=|\s+))(?:\\"[^"\\]*\\"|'[^']*'|(?:\\.|[^\s"\\])+)/g, '$1*****')
209
+ .replace(/((?:signup|SHOPIFY_FLAG_SIGNUP)\\?":\\?")[^"\\]*/g, '$1*****')
210
+ .replace(/(?<![\w-])(signup=)[^&\s"'\\]+/g, '$1*****');
205
211
  return JSON.parse(sanitizedPayloadString);
206
212
  }
207
213
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/public/node/analytics.ts"],"names":[],"mappings":"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","sourcesContent":["import {alwaysLogAnalytics, alwaysLogMetrics, analyticsDisabled, ciPlatform, isShopify} from './context/local.js'\nimport * as metadata from './metadata.js'\nimport {publishMonorailEvent, MONORAIL_COMMAND_TOPIC, type Schemas} from './monorail.js'\nimport {fanoutHooks} from './plugins.js'\nimport {sendErrorToBugsnag} from './error-handler.js'\nimport {outputContent, outputDebug, outputToken} from './output.js'\nimport {\n recordTiming as storageRecordTiming,\n recordError as storageRecordError,\n recordRetry as storageRecordRetry,\n recordEvent as storageRecordEvent,\n compileData as storageCompileData,\n RuntimeData,\n} from '../../private/node/analytics/storage.js'\nimport {getEnvironmentData, getSensitiveEnvironmentData} from '../../private/node/analytics.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {recordMetrics} from '../../private/node/otel-metrics.js'\nimport {runWithRateLimit} from '../../private/node/conf-store.js'\nimport {reportingRateLimit} from '../../private/node/constants.js'\nimport {getLastSeenUserIdAfterAuth} from '../../private/node/session.js'\nimport {requestIdsCollection} from '../../private/node/request-ids.js'\n\nimport {Interfaces} from '@oclif/core'\n\nexport type CommandExitMode =\n // The command completed successfully\n | 'ok'\n // The command exited for some unexpected reason -- i.e. a bug\n | 'unexpected_error'\n // The command exited with an error, but its one we expect and doesn't point to a bug -- i.e. malformed config files\n | 'expected_error'\n\ninterface ReportAnalyticsEventOptions {\n config: Interfaces.Config\n errorMessage?: string\n exitMode: CommandExitMode\n}\n\ntype MonorailCommandPayload = Schemas[typeof MONORAIL_COMMAND_TOPIC]\ninterface AnalyticsPayload {\n public: MonorailCommandPayload['public'] & {cmd_all_exit: CommandExitMode}\n sensitive: MonorailCommandPayload['sensitive']\n}\n\nasync function sendAnalyticsEvent(\n payload: AnalyticsPayload,\n skipMonorailAnalytics: boolean,\n skipMetricAnalytics: boolean,\n): Promise<void> {\n const doMonorail = async () => {\n if (skipMonorailAnalytics) return\n const response = await publishMonorailEvent(MONORAIL_COMMAND_TOPIC, payload.public, payload.sensitive)\n if (response.type === 'error') {\n outputDebug(response.message)\n }\n }\n\n const doOpenTelemetry = async () => {\n const active = payload.public.cmd_all_timing_active_ms ?? 0\n const network = payload.public.cmd_all_timing_network_ms ?? 0\n const prompt = payload.public.cmd_all_timing_prompts_ms ?? 0\n\n return recordMetrics(\n {\n skipMetricAnalytics,\n cliVersion: payload.public.cli_version,\n owningPlugin: payload.public.cmd_all_plugin ?? '@shopify/cli',\n command: payload.public.command,\n exitMode: payload.public.cmd_all_exit,\n },\n {\n active,\n network,\n prompt,\n },\n )\n }\n\n await Promise.all([doMonorail(), doOpenTelemetry()])\n}\n\nexport async function sendAnalyticsEventFromStdin(): Promise<void> {\n try {\n const {readStdinString} = await import('./system.js')\n const payloadStr = await readStdinString()\n if (payloadStr === undefined) throw new Error('No analytics payload received from stdin')\n\n const {payload, skipMonorailAnalytics, skipMetricAnalytics} = JSON.parse(payloadStr) as {\n payload: AnalyticsPayload\n skipMonorailAnalytics: boolean\n skipMetricAnalytics: boolean\n }\n\n await sendAnalyticsEvent(payload, skipMonorailAnalytics, skipMetricAnalytics)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n outputDebug(`Failed to send analytics in background: ${message}`)\n await sendErrorToBugsnag(error, 'expected_error')\n }\n}\n\n/**\n * Report an analytics event, sending it off to Monorail -- Shopify's internal analytics service.\n *\n * The payload for an event includes both generic data, and data gathered from installed plug-ins.\n *\n */\nexport async function reportAnalyticsEvent(options: ReportAnalyticsEventOptions): Promise<void> {\n try {\n const commandStartOptions = metadata.getAllSensitiveMetadata().commandStartOptions\n if (commandStartOptions?.startCommand === 'send-analytics') return\n\n const payload = await buildPayload(options)\n if (payload === undefined) return\n\n let withinRateLimit = false\n await runWithRateLimit({\n key: 'report-analytics-event',\n ...reportingRateLimit,\n task: async () => {\n withinRateLimit = true\n },\n })\n if (!withinRateLimit) {\n outputDebug(outputContent`Skipping command analytics due to rate limiting, payload: ${outputToken.json(payload)}`)\n return\n }\n\n const skipMonorailAnalytics = !alwaysLogAnalytics() && analyticsDisabled()\n const skipMetricAnalytics = !alwaysLogMetrics() && analyticsDisabled()\n if (skipMonorailAnalytics && skipMetricAnalytics) {\n outputDebug(outputContent`Skipping command analytics, payload: ${outputToken.json(payload)}`)\n return\n }\n\n const [{platformAndArch}, {isInsideContainer}] = await Promise.all([import('./os.js'), import('./system.js')])\n const sendInBackground =\n !commandStartOptions?.requiresSyncAnalytics &&\n platformAndArch().platform !== 'windows' &&\n !ciPlatform().isCI &&\n !isInsideContainer()\n const deliveryDescription = sendInBackground ? ' in background' : ''\n outputDebug(outputContent`Sending command analytics${deliveryDescription}, payload: ${outputToken.json(payload)}`)\n\n if (!sendInBackground) {\n await sendAnalyticsEvent(payload, skipMonorailAnalytics, skipMetricAnalytics)\n return\n }\n\n const {exec} = await import('./system.js')\n const argv = process.argv\n if (!argv[1]) return\n const nodeBinary = process.execPath\n const shopifyBinary = argv[1]\n const args = [shopifyBinary, 'send-analytics']\n\n const analyticsProcess = exec(nodeBinary, args, {\n background: true,\n env: {...process.env, SHOPIFY_CLI_NO_ANALYTICS: '1'},\n input: JSON.stringify({payload, skipMonorailAnalytics, skipMetricAnalytics}),\n externalErrorHandler: async (error: unknown) => {\n outputDebug(`Failed to send analytics in background: ${(error as Error).message}`)\n },\n })\n // eslint-disable-next-line no-void\n void analyticsProcess\n\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n let message = 'Failed to report usage analytics'\n if (error instanceof Error) {\n message = message.concat(`: ${error.message}`)\n }\n outputDebug(message)\n await sendErrorToBugsnag(error, 'expected_error')\n }\n}\n\nasync function buildPayload({\n config,\n errorMessage,\n exitMode,\n}: ReportAnalyticsEventOptions): Promise<AnalyticsPayload | undefined> {\n const {commandStartOptions, environmentFlags, ...sensitiveMetadata} = metadata.getAllSensitiveMetadata()\n if (commandStartOptions === undefined) {\n outputDebug('Unable to log analytics event - no information on executed command')\n return\n }\n const {startCommand, startArgs, startTime, endTime} = commandStartOptions\n const currentTime = endTime ?? new Date().getTime()\n\n // All bundled plugins appear as `@shopify/cli` in the payload\n const {'@shopify/cli': internalPluginsPublic, ...externalPluginsPublic} = await fanoutHooks(\n config,\n 'public_command_metadata',\n {},\n )\n const {'@shopify/cli': internalPluginsSensitive, ...externalPluginsSensitive} = await fanoutHooks(\n config,\n 'sensitive_command_metadata',\n {},\n )\n\n const environmentData = await getEnvironmentData(config)\n const sensitiveEnvironmentData = await getSensitiveEnvironmentData(config)\n const publicMetadata = metadata.getAllPublicMetadata()\n\n // Automatically calculate the total time spent in the command, excluding time spent in subtimers.\n const subTimers = ['cmd_all_timing_network_ms', 'cmd_all_timing_prompts_ms'] as const\n const totalTimeFromSubtimers = subTimers.reduce((total, timer) => {\n const value = publicMetadata[timer]\n if (value !== undefined) {\n return total + value\n }\n return total\n }, 0)\n const wallClockElapsed = currentTime - startTime\n const totalTimeWithoutSubtimers = wallClockElapsed - totalTimeFromSubtimers\n\n const payload = {\n public: {\n command: startCommand,\n time_start: startTime,\n time_end: currentTime,\n total_time: wallClockElapsed,\n success: exitMode === 'ok' && errorMessage === undefined,\n cli_version: CLI_KIT_VERSION,\n ruby_version: '',\n node_version: process.version.replace('v', ''),\n is_employee: await isShopify(),\n ...environmentData,\n ...internalPluginsPublic,\n ...publicMetadata,\n cmd_all_timing_active_ms: totalTimeWithoutSubtimers,\n cmd_all_exit: exitMode,\n user_id: await getLastSeenUserIdAfterAuth(),\n request_ids: requestIdsCollection.getRequestIds(),\n },\n sensitive: {\n args: startArgs.join(' '),\n cmd_all_environment_flags: environmentFlags,\n error_message: errorMessage,\n ...internalPluginsSensitive,\n ...sensitiveEnvironmentData,\n metadata: JSON.stringify({\n ...sensitiveMetadata,\n extraPublic: {\n ...externalPluginsPublic,\n },\n extraSensitive: {...externalPluginsSensitive},\n }),\n },\n }\n\n // round down timing metrics\n const timingMetrics = ['cmd_all_timing_active_ms', 'cmd_all_timing_network_ms', 'cmd_all_timing_prompts_ms'] as const\n timingMetrics.forEach((metric) => {\n const current = payload.public[metric]\n if (current !== undefined) {\n payload.public[metric] = Math.floor(current)\n }\n })\n\n return sanitizePayload(payload)\n}\n\nfunction sanitizePayload<T>(payload: T): T {\n const payloadString = JSON.stringify(payload)\n // Remove Theme Access passwords from the payload\n const sanitizedPayloadString = payloadString\n .replace(/shptka_\\w*/g, '*****')\n .replace(/(--store-password(?:=|\\s+))(?:\"[^\"]*\"|'[^']*'|[^\\s\"]+)/g, '$1*****')\n .replace(/((?:store-password|SHOPIFY_FLAG_STORE_PASSWORD)\\\\?\":\\\\?\")[^\"\\\\]*/g, '$1*****')\n return JSON.parse(sanitizedPayloadString)\n}\n\n/**\n * Records timing data for performance monitoring. Call twice with the same\n * event name to start and stop timing. First call starts the timer, second\n * call stops it and records the duration.\n *\n * @example\n * ```ts\n * recordTiming('theme-upload') // Start timing\n * // ... do work ...\n * recordTiming('theme-upload') // Stop timing and record duration\n * ```\n *\n * @param eventName - Unique identifier for the timing event\n */\nexport function recordTiming(eventName: string): void {\n storageRecordTiming(eventName)\n}\n\n/**\n * Records error information for debugging and monitoring. Use this to track\n * any exceptions or error conditions that occur during theme operations.\n * Errors are automatically categorized for easier analysis.\n *\n * @example\n * ```ts\n * try {\n * // ... risky operation ...\n * } catch (error) {\n * recordError(error)\n * }\n * ```\n *\n * @param error - Error object or message to record\n */\nexport function recordError<T>(error: T): T {\n storageRecordError(error)\n return error\n}\n\n/**\n * Records retry attempts for network operations. Use this to track when\n * operations are retried due to transient failures. Helps identify\n * problematic endpoints or operations that frequently fail.\n *\n * @example\n * ```ts\n * recordRetry('https://api.shopify.com/themes', 'upload')\n * ```\n *\n * @param url - The URL or endpoint being retried\n * @param operation - Description of the operation being retried\n */\nexport function recordRetry(url: string, operation: string): void {\n storageRecordRetry(url, operation)\n}\n\n/**\n * Records custom events for tracking specific user actions or system events.\n * Use this for important milestones, user interactions, or significant\n * state changes in the application.\n *\n * @example\n * ```ts\n * recordEvent('theme-dev-started')\n * recordEvent('file-watcher-connected')\n * ```\n *\n * @param eventName - Descriptive name for the event\n */\nexport function recordEvent(eventName: string): void {\n storageRecordEvent(eventName)\n}\n\n/**\n * Compiles and returns all runtime analytics data collected during the session.\n * This includes timing measurements, error records, retry attempts, and custom\n * events. Use this to retrieve a complete snapshot of analytics data for\n * reporting or debugging purposes.\n *\n * @example\n * ```ts\n * const analyticsData = compileData()\n * console.log(`Recorded ${analyticsData.timings.length} timing events`)\n * console.log(`Recorded ${analyticsData.errors.length} errors`)\n * ```\n *\n * @returns Object containing all collected analytics data including timings, errors, retries, and events\n */\nexport function compileData(): RuntimeData {\n return storageCompileData()\n}\n"]}
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/public/node/analytics.ts"],"names":[],"mappings":"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","sourcesContent":["import {alwaysLogAnalytics, alwaysLogMetrics, analyticsDisabled, ciPlatform, isShopify} from './context/local.js'\nimport * as metadata from './metadata.js'\nimport {publishMonorailEvent, MONORAIL_COMMAND_TOPIC, type Schemas} from './monorail.js'\nimport {fanoutHooks} from './plugins.js'\nimport {sendErrorToBugsnag} from './error-handler.js'\nimport {outputContent, outputDebug, outputToken} from './output.js'\nimport {\n recordTiming as storageRecordTiming,\n recordError as storageRecordError,\n recordRetry as storageRecordRetry,\n recordEvent as storageRecordEvent,\n compileData as storageCompileData,\n RuntimeData,\n} from '../../private/node/analytics/storage.js'\nimport {getEnvironmentData, getSensitiveEnvironmentData} from '../../private/node/analytics.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {recordMetrics} from '../../private/node/otel-metrics.js'\nimport {runWithRateLimit} from '../../private/node/conf-store.js'\nimport {reportingRateLimit} from '../../private/node/constants.js'\nimport {getLastSeenUserIdAfterAuth} from '../../private/node/session.js'\nimport {requestIdsCollection} from '../../private/node/request-ids.js'\n\nimport {Interfaces} from '@oclif/core'\n\nexport type CommandExitMode =\n // The command completed successfully\n | 'ok'\n // The command exited for some unexpected reason -- i.e. a bug\n | 'unexpected_error'\n // The command exited with an error, but its one we expect and doesn't point to a bug -- i.e. malformed config files\n | 'expected_error'\n\ninterface ReportAnalyticsEventOptions {\n config: Interfaces.Config\n errorMessage?: string\n exitMode: CommandExitMode\n}\n\ntype MonorailCommandPayload = Schemas[typeof MONORAIL_COMMAND_TOPIC]\ninterface AnalyticsPayload {\n public: MonorailCommandPayload['public'] & {cmd_all_exit: CommandExitMode}\n sensitive: MonorailCommandPayload['sensitive']\n}\n\nasync function sendAnalyticsEvent(\n payload: AnalyticsPayload,\n skipMonorailAnalytics: boolean,\n skipMetricAnalytics: boolean,\n): Promise<void> {\n const doMonorail = async () => {\n if (skipMonorailAnalytics) return\n const response = await publishMonorailEvent(MONORAIL_COMMAND_TOPIC, payload.public, payload.sensitive)\n if (response.type === 'error') {\n outputDebug(response.message)\n }\n }\n\n const doOpenTelemetry = async () => {\n const active = payload.public.cmd_all_timing_active_ms ?? 0\n const network = payload.public.cmd_all_timing_network_ms ?? 0\n const prompt = payload.public.cmd_all_timing_prompts_ms ?? 0\n\n return recordMetrics(\n {\n skipMetricAnalytics,\n cliVersion: payload.public.cli_version,\n owningPlugin: payload.public.cmd_all_plugin ?? '@shopify/cli',\n command: payload.public.command,\n exitMode: payload.public.cmd_all_exit,\n },\n {\n active,\n network,\n prompt,\n },\n )\n }\n\n await Promise.all([doMonorail(), doOpenTelemetry()])\n}\n\nexport async function sendAnalyticsEventFromStdin(): Promise<void> {\n try {\n const {readStdinString} = await import('./system.js')\n const payloadStr = await readStdinString()\n if (payloadStr === undefined) throw new Error('No analytics payload received from stdin')\n\n const {payload, skipMonorailAnalytics, skipMetricAnalytics} = JSON.parse(payloadStr) as {\n payload: AnalyticsPayload\n skipMonorailAnalytics: boolean\n skipMetricAnalytics: boolean\n }\n\n await sendAnalyticsEvent(payload, skipMonorailAnalytics, skipMetricAnalytics)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n outputDebug(`Failed to send analytics in background: ${message}`)\n await sendErrorToBugsnag(error, 'expected_error')\n }\n}\n\n/**\n * Report an analytics event, sending it off to Monorail -- Shopify's internal analytics service.\n *\n * The payload for an event includes both generic data, and data gathered from installed plug-ins.\n *\n */\nexport async function reportAnalyticsEvent(options: ReportAnalyticsEventOptions): Promise<void> {\n try {\n const commandStartOptions = metadata.getAllSensitiveMetadata().commandStartOptions\n if (commandStartOptions?.startCommand === 'send-analytics') return\n\n const payload = await buildPayload(options)\n if (payload === undefined) return\n\n let withinRateLimit = false\n await runWithRateLimit({\n key: 'report-analytics-event',\n ...reportingRateLimit,\n task: async () => {\n withinRateLimit = true\n },\n })\n if (!withinRateLimit) {\n outputDebug(outputContent`Skipping command analytics due to rate limiting, payload: ${outputToken.json(payload)}`)\n return\n }\n\n const skipMonorailAnalytics = !alwaysLogAnalytics() && analyticsDisabled()\n const skipMetricAnalytics = !alwaysLogMetrics() && analyticsDisabled()\n if (skipMonorailAnalytics && skipMetricAnalytics) {\n outputDebug(outputContent`Skipping command analytics, payload: ${outputToken.json(payload)}`)\n return\n }\n\n const [{platformAndArch}, {isInsideContainer}] = await Promise.all([import('./os.js'), import('./system.js')])\n const sendInBackground =\n !commandStartOptions?.requiresSyncAnalytics &&\n platformAndArch().platform !== 'windows' &&\n !ciPlatform().isCI &&\n !isInsideContainer()\n const deliveryDescription = sendInBackground ? ' in background' : ''\n outputDebug(outputContent`Sending command analytics${deliveryDescription}, payload: ${outputToken.json(payload)}`)\n\n if (!sendInBackground) {\n await sendAnalyticsEvent(payload, skipMonorailAnalytics, skipMetricAnalytics)\n return\n }\n\n const {exec} = await import('./system.js')\n const argv = process.argv\n if (!argv[1]) return\n const nodeBinary = process.execPath\n const shopifyBinary = argv[1]\n const args = [shopifyBinary, 'send-analytics']\n\n const analyticsProcess = exec(nodeBinary, args, {\n background: true,\n env: {...process.env, SHOPIFY_CLI_NO_ANALYTICS: '1'},\n input: JSON.stringify({payload, skipMonorailAnalytics, skipMetricAnalytics}),\n externalErrorHandler: async (error: unknown) => {\n outputDebug(`Failed to send analytics in background: ${(error as Error).message}`)\n },\n })\n // eslint-disable-next-line no-void\n void analyticsProcess\n\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n let message = 'Failed to report usage analytics'\n if (error instanceof Error) {\n message = message.concat(`: ${error.message}`)\n }\n outputDebug(message)\n await sendErrorToBugsnag(error, 'expected_error')\n }\n}\n\nasync function buildPayload({\n config,\n errorMessage,\n exitMode,\n}: ReportAnalyticsEventOptions): Promise<AnalyticsPayload | undefined> {\n const {commandStartOptions, environmentFlags, ...sensitiveMetadata} = metadata.getAllSensitiveMetadata()\n if (commandStartOptions === undefined) {\n outputDebug('Unable to log analytics event - no information on executed command')\n return\n }\n const {startCommand, startArgs, startTime, endTime} = commandStartOptions\n const currentTime = endTime ?? new Date().getTime()\n\n // All bundled plugins appear as `@shopify/cli` in the payload\n const {'@shopify/cli': internalPluginsPublic, ...externalPluginsPublic} = await fanoutHooks(\n config,\n 'public_command_metadata',\n {},\n )\n const {'@shopify/cli': internalPluginsSensitive, ...externalPluginsSensitive} = await fanoutHooks(\n config,\n 'sensitive_command_metadata',\n {},\n )\n\n const environmentData = await getEnvironmentData(config)\n const sensitiveEnvironmentData = await getSensitiveEnvironmentData(config)\n const publicMetadata = metadata.getAllPublicMetadata()\n\n // Automatically calculate the total time spent in the command, excluding time spent in subtimers.\n const subTimers = ['cmd_all_timing_network_ms', 'cmd_all_timing_prompts_ms'] as const\n const totalTimeFromSubtimers = subTimers.reduce((total, timer) => {\n const value = publicMetadata[timer]\n if (value !== undefined) {\n return total + value\n }\n return total\n }, 0)\n const wallClockElapsed = currentTime - startTime\n const totalTimeWithoutSubtimers = wallClockElapsed - totalTimeFromSubtimers\n\n const payload = {\n public: {\n command: startCommand,\n time_start: startTime,\n time_end: currentTime,\n total_time: wallClockElapsed,\n success: exitMode === 'ok' && errorMessage === undefined,\n cli_version: CLI_KIT_VERSION,\n ruby_version: '',\n node_version: process.version.replace('v', ''),\n is_employee: await isShopify(),\n ...environmentData,\n ...internalPluginsPublic,\n ...publicMetadata,\n cmd_all_timing_active_ms: totalTimeWithoutSubtimers,\n cmd_all_exit: exitMode,\n user_id: await getLastSeenUserIdAfterAuth(),\n request_ids: requestIdsCollection.getRequestIds(),\n },\n sensitive: {\n args: startArgs.join(' '),\n cmd_all_environment_flags: environmentFlags,\n error_message: errorMessage,\n ...internalPluginsSensitive,\n ...sensitiveEnvironmentData,\n metadata: JSON.stringify({\n ...sensitiveMetadata,\n extraPublic: {\n ...externalPluginsPublic,\n },\n extraSensitive: {...externalPluginsSensitive},\n }),\n },\n }\n\n // round down timing metrics\n const timingMetrics = ['cmd_all_timing_active_ms', 'cmd_all_timing_network_ms', 'cmd_all_timing_prompts_ms'] as const\n timingMetrics.forEach((metric) => {\n const current = payload.public[metric]\n if (current !== undefined) {\n payload.public[metric] = Math.floor(current)\n }\n })\n\n return sanitizePayload(payload)\n}\n\nfunction sanitizePayload<T>(payload: T): T {\n const payloadString = JSON.stringify(payload)\n // Redaction runs on the serialized payload, so a flag value that was quoted arrives with its quotes\n // escaped. Every flag rule below matches that escaped form first, and its bare-value alternative\n // treats a JSON escape as part of the value, so a value can never be redacted only halfway or leave\n // behind a string that no longer parses.\n const sanitizedPayloadString = payloadString\n .replace(/shptka_\\w*/g, '*****')\n .replace(/(--store-password(?:=|\\s+))(?:\\\\\"[^\"\\\\]*\\\\\"|'[^']*'|(?:\\\\.|[^\\s\"\\\\])+)/g, '$1*****')\n .replace(/((?:store-password|SHOPIFY_FLAG_STORE_PASSWORD)\\\\?\":\\\\?\")[^\"\\\\]*/g, '$1*****')\n .replace(/(--signup(?:=|\\s+))(?:\\\\\"[^\"\\\\]*\\\\\"|'[^']*'|(?:\\\\.|[^\\s\"\\\\])+)/g, '$1*****')\n .replace(/((?:signup|SHOPIFY_FLAG_SIGNUP)\\\\?\":\\\\?\")[^\"\\\\]*/g, '$1*****')\n .replace(/(?<![\\w-])(signup=)[^&\\s\"'\\\\]+/g, '$1*****')\n return JSON.parse(sanitizedPayloadString)\n}\n\n/**\n * Records timing data for performance monitoring. Call twice with the same\n * event name to start and stop timing. First call starts the timer, second\n * call stops it and records the duration.\n *\n * @example\n * ```ts\n * recordTiming('theme-upload') // Start timing\n * // ... do work ...\n * recordTiming('theme-upload') // Stop timing and record duration\n * ```\n *\n * @param eventName - Unique identifier for the timing event\n */\nexport function recordTiming(eventName: string): void {\n storageRecordTiming(eventName)\n}\n\n/**\n * Records error information for debugging and monitoring. Use this to track\n * any exceptions or error conditions that occur during theme operations.\n * Errors are automatically categorized for easier analysis.\n *\n * @example\n * ```ts\n * try {\n * // ... risky operation ...\n * } catch (error) {\n * recordError(error)\n * }\n * ```\n *\n * @param error - Error object or message to record\n */\nexport function recordError<T>(error: T): T {\n storageRecordError(error)\n return error\n}\n\n/**\n * Records retry attempts for network operations. Use this to track when\n * operations are retried due to transient failures. Helps identify\n * problematic endpoints or operations that frequently fail.\n *\n * @example\n * ```ts\n * recordRetry('https://api.shopify.com/themes', 'upload')\n * ```\n *\n * @param url - The URL or endpoint being retried\n * @param operation - Description of the operation being retried\n */\nexport function recordRetry(url: string, operation: string): void {\n storageRecordRetry(url, operation)\n}\n\n/**\n * Records custom events for tracking specific user actions or system events.\n * Use this for important milestones, user interactions, or significant\n * state changes in the application.\n *\n * @example\n * ```ts\n * recordEvent('theme-dev-started')\n * recordEvent('file-watcher-connected')\n * ```\n *\n * @param eventName - Descriptive name for the event\n */\nexport function recordEvent(eventName: string): void {\n storageRecordEvent(eventName)\n}\n\n/**\n * Compiles and returns all runtime analytics data collected during the session.\n * This includes timing measurements, error records, retry attempts, and custom\n * events. Use this to retrieve a complete snapshot of analytics data for\n * reporting or debugging purposes.\n *\n * @example\n * ```ts\n * const analyticsData = compileData()\n * console.log(`Recorded ${analyticsData.timings.length} timing events`)\n * console.log(`Recorded ${analyticsData.errors.length} errors`)\n * ```\n *\n * @returns Object containing all collected analytics data including timings, errors, retries, and events\n */\nexport function compileData(): RuntimeData {\n return storageCompileData()\n}\n"]}
@@ -182,12 +182,13 @@ export function shouldReportErrorAsUnexpected(error) {
182
182
  /**
183
183
  * Detects raw graphql-request `ClientError`s that are expected environmental conditions rather than
184
184
  * CLI bugs. These reach the reporter as plain `Error`s (not `FatalError`s) and would otherwise be
185
- * reported as unexpected. Two distinct cases, both kept out of crash reporting:
185
+ * reported as unexpected.
186
186
  *
187
187
  * HTTP 401 (unauthenticated) is not "transient" in the retry sense — it means the user's session
188
188
  * token is expired or invalid, a credential/environment condition (see issue #7891). Rate limiting
189
189
  * (HTTP 429, or a `THROTTLED`/`429` GraphQL code on any error in the response) matches the shape
190
- * detected by `errorsIncludeStatus429` in `private/node/api.ts`.
190
+ * detected by `errorsIncludeStatus429` in `private/node/api.ts`. Gateway errors (502/503/504) are
191
+ * also expected infrastructure failures.
191
192
  *
192
193
  * Scoped to the external `ClientError` shape only — importing the cli-kit `GraphQLClientError`
193
194
  * wrapper here would create an `error.ts → headers.ts → error.ts` import cycle.
@@ -207,7 +208,7 @@ function isExpectedApiError(error) {
207
208
  return false;
208
209
  }
209
210
  const status = candidate.response.status;
210
- if (status === 401 || status === 429) {
211
+ if (status === 401 || status === 429 || status === 502 || status === 503 || status === 504) {
211
212
  return true;
212
213
  }
213
214
  return hasRateLimitCode(candidate.response.errors);