@shopify/cli-kit 3.92.1 → 3.93.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/api/graphql/admin/generated/find_development_theme_by_name.d.ts +16 -0
- package/dist/cli/api/graphql/admin/generated/find_development_theme_by_name.js +60 -0
- package/dist/cli/api/graphql/admin/generated/find_development_theme_by_name.js.map +1 -0
- package/dist/private/node/api/graphql.d.ts +10 -0
- package/dist/private/node/api/graphql.js +67 -5
- package/dist/private/node/api/graphql.js.map +1 -1
- package/dist/private/node/conf-store.d.ts +13 -0
- package/dist/private/node/conf-store.js +17 -3
- package/dist/private/node/conf-store.js.map +1 -1
- package/dist/private/node/constants.d.ts +3 -0
- package/dist/private/node/constants.js +3 -0
- package/dist/private/node/constants.js.map +1 -1
- package/dist/private/node/session/exchange.d.ts +22 -8
- package/dist/private/node/session/exchange.js +37 -14
- package/dist/private/node/session/exchange.js.map +1 -1
- package/dist/private/node/session/schema.d.ts +62 -62
- package/dist/private/node/session/scopes.js +3 -2
- package/dist/private/node/session/scopes.js.map +1 -1
- package/dist/private/node/session/store.d.ts +7 -0
- package/dist/private/node/session/store.js +17 -0
- package/dist/private/node/session/store.js.map +1 -1
- package/dist/private/node/session/validate.d.ts +5 -4
- package/dist/private/node/session/validate.js +34 -7
- package/dist/private/node/session/validate.js.map +1 -1
- package/dist/private/node/session.d.ts +1 -1
- package/dist/private/node/session.js +77 -32
- package/dist/private/node/session.js.map +1 -1
- package/dist/private/node/testing/ui.js +6 -4
- package/dist/private/node/testing/ui.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.test.js +5 -5
- package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.js +5 -2
- package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.test.js +2 -2
- package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.test.js +10 -10
- package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
- package/dist/private/node/ui/components/Table/Table.js +2 -2
- package/dist/private/node/ui/components/Table/Table.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.test.js +6 -6
- package/dist/private/node/ui/components/Tasks.test.js.map +1 -1
- package/dist/private/node/ui/components/TextAnimation.test.js +1 -1
- package/dist/private/node/ui/components/TextAnimation.test.js.map +1 -1
- package/dist/private/node/ui/components/TextInput.test.js +4 -4
- package/dist/private/node/ui/components/TextInput.test.js.map +1 -1
- package/dist/private/node/ui/components/TokenizedText.js +1 -0
- package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
- package/dist/private/node/ui/hooks/use-select-state.js +1 -3
- package/dist/private/node/ui/hooks/use-select-state.js.map +1 -1
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/analytics.js +4 -4
- package/dist/public/node/analytics.js.map +1 -1
- package/dist/public/node/api/admin.js +1 -3
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/rest-api-throttler.d.ts +14 -0
- package/dist/public/node/api/rest-api-throttler.js +14 -87
- package/dist/public/node/api/rest-api-throttler.js.map +1 -1
- package/dist/public/node/archiver.js +6 -7
- package/dist/public/node/archiver.js.map +1 -1
- package/dist/public/node/cli-launcher.d.ts +1 -1
- package/dist/public/node/cli-launcher.js +9 -9
- package/dist/public/node/cli-launcher.js.map +1 -1
- package/dist/public/node/cli.js +4 -1
- package/dist/public/node/cli.js.map +1 -1
- package/dist/public/node/context/fqdn.js +1 -0
- package/dist/public/node/context/fqdn.js.map +1 -1
- package/dist/public/node/context/local.d.ts +7 -0
- package/dist/public/node/context/local.js +9 -0
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/dot-env.js +1 -1
- package/dist/public/node/dot-env.js.map +1 -1
- package/dist/public/node/environment.d.ts +4 -9
- package/dist/public/node/environment.js +6 -12
- package/dist/public/node/environment.js.map +1 -1
- package/dist/public/node/environments.js +4 -3
- package/dist/public/node/environments.js.map +1 -1
- package/dist/public/node/error-handler.js +1 -1
- package/dist/public/node/error-handler.js.map +1 -1
- package/dist/public/node/error.js +1 -0
- package/dist/public/node/error.js.map +1 -1
- package/dist/public/node/fs.d.ts +9 -1
- package/dist/public/node/fs.js +16 -4
- package/dist/public/node/fs.js.map +1 -1
- package/dist/public/node/git.d.ts +10 -4
- package/dist/public/node/git.js +101 -80
- package/dist/public/node/git.js.map +1 -1
- package/dist/public/node/global-context.js +1 -3
- package/dist/public/node/global-context.js.map +1 -1
- package/dist/public/node/hooks/postrun.d.ts +7 -0
- package/dist/public/node/hooks/postrun.js +61 -1
- package/dist/public/node/hooks/postrun.js.map +1 -1
- package/dist/public/node/hooks/prerun.d.ts +3 -2
- package/dist/public/node/hooks/prerun.js +9 -22
- package/dist/public/node/hooks/prerun.js.map +1 -1
- package/dist/public/node/http.js +1 -1
- package/dist/public/node/http.js.map +1 -1
- package/dist/public/node/import-extractor.d.ts +17 -0
- package/dist/public/node/import-extractor.js +84 -23
- package/dist/public/node/import-extractor.js.map +1 -1
- package/dist/public/node/is-global.d.ts +9 -1
- package/dist/public/node/is-global.js +55 -12
- package/dist/public/node/is-global.js.map +1 -1
- package/dist/public/node/mimes.js +1 -1
- package/dist/public/node/mimes.js.map +1 -1
- package/dist/public/node/node-package-manager.d.ts +1 -1
- package/dist/public/node/node-package-manager.js +4 -1
- package/dist/public/node/node-package-manager.js.map +1 -1
- package/dist/public/node/os.js +1 -0
- package/dist/public/node/os.js.map +1 -1
- package/dist/public/node/output.js +3 -2
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/path.d.ts +11 -0
- package/dist/public/node/path.js +30 -1
- package/dist/public/node/path.js.map +1 -1
- package/dist/public/node/result.js +1 -0
- package/dist/public/node/result.js.map +1 -1
- package/dist/public/node/serial-batch-processor.js +1 -3
- package/dist/public/node/serial-batch-processor.js.map +1 -1
- package/dist/public/node/session-prompt.js +10 -2
- package/dist/public/node/session-prompt.js.map +1 -1
- package/dist/public/node/session.js +6 -6
- package/dist/public/node/session.js.map +1 -1
- package/dist/public/node/themes/api.d.ts +1 -0
- package/dist/public/node/themes/api.js +26 -0
- package/dist/public/node/themes/api.js.map +1 -1
- package/dist/public/node/themes/conf.js +3 -5
- package/dist/public/node/themes/conf.js.map +1 -1
- package/dist/public/node/themes/factories.js +1 -0
- package/dist/public/node/themes/factories.js.map +1 -1
- package/dist/public/node/themes/theme-manager.d.ts +2 -2
- package/dist/public/node/themes/theme-manager.js +13 -8
- package/dist/public/node/themes/theme-manager.js.map +1 -1
- package/dist/public/node/{toml.d.ts → toml/codec.d.ts} +1 -1
- package/dist/public/node/{toml.js → toml/codec.js} +1 -1
- package/dist/public/node/toml/codec.js.map +1 -0
- package/dist/public/node/toml/index.d.ts +1 -0
- package/dist/public/node/toml/index.js +2 -0
- package/dist/public/node/toml/index.js.map +1 -0
- package/dist/public/node/toml/toml-file.d.ts +88 -0
- package/dist/public/node/toml/toml-file.js +159 -0
- package/dist/public/node/toml/toml-file.js.map +1 -0
- package/dist/public/node/tree-kill.js +1 -1
- package/dist/public/node/tree-kill.js.map +1 -1
- package/dist/public/node/ui.js +1 -0
- package/dist/public/node/ui.js.map +1 -1
- package/dist/public/node/upgrade.d.ts +28 -1
- package/dist/public/node/upgrade.js +184 -16
- package/dist/public/node/upgrade.js.map +1 -1
- package/dist/public/node/version.d.ts +9 -0
- package/dist/public/node/version.js +16 -1
- package/dist/public/node/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -12
- package/dist/public/node/custom-oclif-loader.d.ts +0 -6
- package/dist/public/node/custom-oclif-loader.js +0 -79
- package/dist/public/node/custom-oclif-loader.js.map +0 -1
- package/dist/public/node/toml.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextInput.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TextInput.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {TextInput} from './TextInput.js'\nimport {\n sendInputAndWait,\n sendInputAndWaitForChange,\n waitForChange,\n waitForInputsToBeReady,\n render,\n} from '../../testing/ui.js'\nimport React, {useState} from 'react'\nimport {describe, test, expect, vi} from 'vitest'\n\nconst ARROW_LEFT = '\\u001B[D'\nconst ARROW_RIGHT = '\\u001B[C'\nconst DELETE = '\\u007F'\nconst TAB = '\\u0009'\n\ndescribe('TextInput', () => {\n test('default state', () => {\n const {lastFrame} = render(<TextInput value=\"\" onChange={() => {}} />)\n\n // inverted space escape sequence\n expect(lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('displays value with cursor', () => {\n const {lastFrame} = render(<TextInput value=\"Hello\" onChange={() => {}} />)\n\n // inverted space escape sequence after Hello\n expect(lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('displays placeholder', () => {\n const {lastFrame} = render(<TextInput value=\"\" placeholder=\"Placeholder\" onChange={() => {}} />)\n\n // inverted escape sequence around \"P\", laceholder after that\n expect(lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[7mP\u001b[27m\u001b[2mlaceholder\u001b[22m\u001b[39m\"')\n })\n\n test('moves the cursor with arrows', async () => {\n const renderInstance = render(<TextInput value=\"Hello\" onChange={() => {}} />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHell\u001b[7mo\u001b[27m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHel\u001b[7ml\u001b[27mo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHe\u001b[7ml\u001b[27mlo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mH\u001b[7me\u001b[27mllo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[7mH\u001b[27mello\u001b[39m\"')\n // cursor can't go before the first character\n await sendInputAndWait(renderInstance, 100, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[7mH\u001b[27mello\u001b[39m\"')\n\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mH\u001b[7me\u001b[27mllo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHe\u001b[7ml\u001b[27mlo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHel\u001b[7ml\u001b[27mo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHell\u001b[7mo\u001b[27m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n // cursor can't go after the last character\n await sendInputAndWait(renderInstance, 100, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('in noColor mode replaces the current character with █', async () => {\n const renderInstance = render(<TextInput noColor value=\"Hello\" onChange={() => {}} />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"Hello█\"')\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"Hell█\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"Hel█o\"')\n })\n\n test('moves the cursor when deleting', async () => {\n const StatefulTextInput = () => {\n const [value, setValue] = useState('Hello')\n\n return <TextInput value={value} onChange={setValue} />\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHell\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHel\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHe\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mH\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[46m█\u001b[49m\u001b[39m\"')\n // cannot delete after the value has been cleared\n await sendInputAndWait(renderInstance, 100, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('accepts input', async () => {\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n\n return <TextInput value={value} onChange={setValue} />\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'H')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mH\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, 'ello')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('onChange', async () => {\n const onChange = vi.fn()\n\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n\n return (\n <TextInput\n value={value}\n onChange={(value) => {\n setValue(value)\n onChange(value)\n }}\n />\n )\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'X')\n\n expect(onChange).toHaveBeenCalledWith('X')\n })\n\n test('deletes at the beginning and in the middle of text', async () => {\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n\n return <TextInput value={value} onChange={setValue} />\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'T')\n await sendInputAndWaitForChange(renderInstance, 'e')\n await sendInputAndWaitForChange(renderInstance, 's')\n await sendInputAndWaitForChange(renderInstance, 't')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mTe\u001b[7mt\u001b[27m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n await sendInputAndWait(renderInstance, 100, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[7mT\u001b[27met\u001b[39m\"')\n })\n\n test('adjusts cursor when text is shorter than last value', async () => {\n let resetValue = () => {}\n\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n resetValue = () => setValue('')\n\n return <TextInput value={value} onChange={setValue} />\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'A')\n await sendInputAndWaitForChange(renderInstance, 'B')\n\n await waitForChange(resetValue, renderInstance.lastFrame)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, 'A')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mA\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, 'B')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mAB\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test(\"masking the input if it's a password\", async () => {\n const renderInstance = render(<TextInput onChange={() => {}} value=\"ABC\" password />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m***\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('tab completes with placeholder content', async () => {\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n const placeholder = 'Hello'\n\n return <TextInput value={value} onChange={setValue} placeholder={placeholder} />\n }\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, TAB)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n})\n"]}
|
|
1
|
+
{"version":3,"file":"TextInput.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TextInput.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {TextInput} from './TextInput.js'\nimport {\n sendInputAndWait,\n sendInputAndWaitForChange,\n waitForChange,\n waitForInputsToBeReady,\n render,\n} from '../../testing/ui.js'\nimport React, {useState} from 'react'\nimport {describe, test, expect, vi} from 'vitest'\n\nconst ARROW_LEFT = '\\u001B[D'\nconst ARROW_RIGHT = '\\u001B[C'\nconst DELETE = '\\u007F'\nconst TAB = '\\u0009'\n\ndescribe('TextInput', () => {\n test('default state', () => {\n const {lastFrame} = render(<TextInput value=\"\" onChange={() => {}} />)\n\n // inverted space escape sequence\n expect(lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('displays value with cursor', () => {\n const {lastFrame} = render(<TextInput value=\"Hello\" onChange={() => {}} />)\n\n // inverted space escape sequence after Hello\n expect(lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('displays placeholder', () => {\n const {lastFrame} = render(<TextInput value=\"\" placeholder=\"Placeholder\" onChange={() => {}} />)\n\n // inverted escape sequence around \"P\", laceholder after that\n expect(lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[7mP\u001b[27m\u001b[2mlaceholder\u001b[22m\u001b[39m\"')\n })\n\n test('moves the cursor with arrows', async () => {\n const renderInstance = render(<TextInput value=\"Hello\" onChange={() => {}} />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHell\u001b[7mo\u001b[27m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHel\u001b[7ml\u001b[27mo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHe\u001b[7ml\u001b[27mlo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mH\u001b[7me\u001b[27mllo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[7mH\u001b[27mello\u001b[39m\"')\n // cursor can't go before the first character\n await sendInputAndWait(renderInstance, 10, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[7mH\u001b[27mello\u001b[39m\"')\n\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mH\u001b[7me\u001b[27mllo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHe\u001b[7ml\u001b[27mlo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHel\u001b[7ml\u001b[27mo\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHell\u001b[7mo\u001b[27m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n // cursor can't go after the last character\n await sendInputAndWait(renderInstance, 10, ARROW_RIGHT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('in noColor mode replaces the current character with █', async () => {\n const renderInstance = render(<TextInput noColor value=\"Hello\" onChange={() => {}} />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"Hello█\"')\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"Hell█\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"Hel█o\"')\n })\n\n test('moves the cursor when deleting', async () => {\n const StatefulTextInput = () => {\n const [value, setValue] = useState('Hello')\n\n return <TextInput value={value} onChange={setValue} />\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHell\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHel\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHe\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mH\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[46m█\u001b[49m\u001b[39m\"')\n // cannot delete after the value has been cleared\n await sendInputAndWait(renderInstance, 10, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('accepts input', async () => {\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n\n return <TextInput value={value} onChange={setValue} />\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'H')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mH\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, 'ello')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('onChange', async () => {\n const onChange = vi.fn()\n\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n\n return (\n <TextInput\n value={value}\n onChange={(value) => {\n setValue(value)\n onChange(value)\n }}\n />\n )\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'X')\n\n expect(onChange).toHaveBeenCalledWith('X')\n })\n\n test('deletes at the beginning and in the middle of text', async () => {\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n\n return <TextInput value={value} onChange={setValue} />\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'T')\n await sendInputAndWaitForChange(renderInstance, 'e')\n await sendInputAndWaitForChange(renderInstance, 's')\n await sendInputAndWaitForChange(renderInstance, 't')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n await sendInputAndWaitForChange(renderInstance, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mTe\u001b[7mt\u001b[27m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n await sendInputAndWaitForChange(renderInstance, ARROW_LEFT)\n await sendInputAndWait(renderInstance, 10, DELETE)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[7mT\u001b[27met\u001b[39m\"')\n })\n\n test('adjusts cursor when text is shorter than last value', async () => {\n let resetValue = () => {}\n\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n resetValue = () => setValue('')\n\n return <TextInput value={value} onChange={setValue} />\n }\n\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'A')\n await sendInputAndWaitForChange(renderInstance, 'B')\n\n await waitForChange(resetValue, renderInstance.lastFrame)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, 'A')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mA\u001b[46m█\u001b[49m\u001b[39m\"')\n await sendInputAndWaitForChange(renderInstance, 'B')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mAB\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test(\"masking the input if it's a password\", async () => {\n const renderInstance = render(<TextInput onChange={() => {}} value=\"ABC\" password />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36m***\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n\n test('tab completes with placeholder content', async () => {\n const StatefulTextInput = () => {\n const [value, setValue] = useState('')\n const placeholder = 'Hello'\n\n return <TextInput value={value} onChange={setValue} placeholder={placeholder} />\n }\n const renderInstance = render(<StatefulTextInput />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, TAB)\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot('\"\u001b[36mHello\u001b[46m█\u001b[49m\u001b[39m\"')\n })\n})\n"]}
|
|
@@ -20,6 +20,7 @@ export function tokenItemToString(token) {
|
|
|
20
20
|
return token.command;
|
|
21
21
|
}
|
|
22
22
|
else if ('link' in token) {
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty label should fall through to url
|
|
23
24
|
return token.link.label || token.link.url;
|
|
24
25
|
}
|
|
25
26
|
else if ('char' in token) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenizedText.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TokenizedText.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Command} from './Command.js'\nimport {Link} from './Link.js'\nimport {List} from './List.js'\nimport {UserInput} from './UserInput.js'\nimport {FilePath} from './FilePath.js'\nimport {Subdued} from './Subdued.js'\nimport React, {FunctionComponent} from 'react'\nimport {Box, Text} from 'ink'\n\nexport interface LinkToken {\n link: {\n label?: string\n url: string\n }\n}\n\nexport interface UserInputToken {\n userInput: string\n}\n\nexport interface ListToken {\n list: {\n title?: TokenItem<InlineToken>\n items: TokenItem<InlineToken>[]\n ordered?: boolean\n }\n}\n\nexport interface BoldToken {\n bold: string\n}\n\nexport type Token =\n | string\n | {\n command: string\n }\n | LinkToken\n | {\n char: string\n }\n | UserInputToken\n | {\n subdued: string\n }\n | {\n filePath: string\n }\n | ListToken\n | BoldToken\n | {\n info: string\n }\n | {\n warn: string\n }\n | {\n error: string\n }\n\nexport type InlineToken = Exclude<Token, ListToken>\nexport type TokenItem<T extends Token = Token> = T | T[]\n\ntype DisplayType = 'block' | 'inline'\ninterface Block {\n display: DisplayType\n value: Token\n}\n\nfunction tokenToBlock(token: Token): Block {\n return {\n display: typeof token !== 'string' && 'list' in token ? 'block' : 'inline',\n value: token,\n }\n}\n\nexport function tokenItemToString(token: TokenItem): string {\n if (typeof token === 'string') {\n return token\n } else if ('command' in token) {\n return token.command\n } else if ('link' in token) {\n return token.link.label || token.link.url\n } else if ('char' in token) {\n return token.char\n } else if ('userInput' in token) {\n return token.userInput\n } else if ('subdued' in token) {\n return token.subdued\n } else if ('filePath' in token) {\n return token.filePath\n } else if ('list' in token) {\n return token.list.items.map(tokenItemToString).join(' ')\n } else if ('bold' in token) {\n return token.bold\n } else if ('info' in token) {\n return token.info\n } else if ('warn' in token) {\n return token.warn\n } else if ('error' in token) {\n return token.error\n } else {\n return token\n .map((item, index) => {\n if (index !== 0 && !(typeof item !== 'string' && 'char' in item)) {\n return ` ${tokenItemToString(item)}`\n } else {\n return tokenItemToString(item)\n }\n })\n .join('')\n }\n}\n\nexport function appendToTokenItem(token: TokenItem, suffix: string): TokenItem {\n return Array.isArray(token) ? [...token, {char: suffix}] : [token, {char: suffix}]\n}\n\nfunction splitByDisplayType(acc: Block[][], item: Block) {\n if (item.display === 'block') {\n acc.push([item])\n } else {\n const last = acc[acc.length - 1]\n if (last && last[0]!.display === 'inline') {\n last.push(item)\n } else {\n acc.push([item])\n }\n }\n return acc\n}\n\nconst InlineBlocks: React.FC<{blocks: Block[]}> = ({blocks}) => {\n return (\n <Text>\n {blocks.map((block, blockIndex) => (\n <Text key={blockIndex}>\n {blockIndex !== 0 && !(typeof block.value !== 'string' && 'char' in block.value) && <Text> </Text>}\n <TokenizedText item={block.value} />\n </Text>\n ))}\n </Text>\n )\n}\n\ninterface TokenizedTextProps {\n item: TokenItem\n}\n\n/**\n * `TokenizedText` renders a text string with tokens that can be either strings,\n * links, and commands.\n */\nconst TokenizedText: FunctionComponent<TokenizedTextProps> = ({item}) => {\n if (typeof item === 'string') {\n return <Text>{item}</Text>\n } else if ('command' in item) {\n return <Command command={item.command} />\n } else if ('link' in item) {\n return <Link {...item.link} />\n } else if ('char' in item) {\n return <Text>{item.char[0]}</Text>\n } else if ('userInput' in item) {\n return <UserInput userInput={item.userInput} />\n } else if ('subdued' in item) {\n return <Subdued subdued={item.subdued} />\n } else if ('filePath' in item) {\n return <FilePath filePath={item.filePath} />\n } else if ('list' in item) {\n return <List {...item.list} />\n } else if ('bold' in item) {\n return <Text bold>{item.bold}</Text>\n } else if ('info' in item) {\n return <Text color=\"blue\">{item.info}</Text>\n } else if ('warn' in item) {\n return <Text color=\"yellow\">{item.warn}</Text>\n } else if ('error' in item) {\n return <Text color=\"red\">{item.error}</Text>\n } else {\n const groupedItems = item.map(tokenToBlock).reduce(splitByDisplayType, [])\n\n return groupedItems.length === 1 && groupedItems[0]!.every((item) => item.display === 'inline') ? (\n <InlineBlocks blocks={groupedItems[0]!} />\n ) : (\n <Box flexDirection=\"column\">\n {groupedItems.map((items, groupIndex) => {\n if (items[0]!.display === 'inline') {\n return <InlineBlocks blocks={items} key={groupIndex} />\n } else {\n return <List key={groupIndex} {...(items[0]!.value as ListToken).list} />\n }\n })}\n </Box>\n )\n }\n}\n\nexport {TokenizedText}\n"]}
|
|
1
|
+
{"version":3,"file":"TokenizedText.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TokenizedText.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Command} from './Command.js'\nimport {Link} from './Link.js'\nimport {List} from './List.js'\nimport {UserInput} from './UserInput.js'\nimport {FilePath} from './FilePath.js'\nimport {Subdued} from './Subdued.js'\nimport React, {FunctionComponent} from 'react'\nimport {Box, Text} from 'ink'\n\nexport interface LinkToken {\n link: {\n label?: string\n url: string\n }\n}\n\nexport interface UserInputToken {\n userInput: string\n}\n\nexport interface ListToken {\n list: {\n title?: TokenItem<InlineToken>\n items: TokenItem<InlineToken>[]\n ordered?: boolean\n }\n}\n\nexport interface BoldToken {\n bold: string\n}\n\nexport type Token =\n | string\n | {\n command: string\n }\n | LinkToken\n | {\n char: string\n }\n | UserInputToken\n | {\n subdued: string\n }\n | {\n filePath: string\n }\n | ListToken\n | BoldToken\n | {\n info: string\n }\n | {\n warn: string\n }\n | {\n error: string\n }\n\nexport type InlineToken = Exclude<Token, ListToken>\nexport type TokenItem<T extends Token = Token> = T | T[]\n\ntype DisplayType = 'block' | 'inline'\ninterface Block {\n display: DisplayType\n value: Token\n}\n\nfunction tokenToBlock(token: Token): Block {\n return {\n display: typeof token !== 'string' && 'list' in token ? 'block' : 'inline',\n value: token,\n }\n}\n\nexport function tokenItemToString(token: TokenItem): string {\n if (typeof token === 'string') {\n return token\n } else if ('command' in token) {\n return token.command\n } else if ('link' in token) {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty label should fall through to url\n return token.link.label || token.link.url\n } else if ('char' in token) {\n return token.char\n } else if ('userInput' in token) {\n return token.userInput\n } else if ('subdued' in token) {\n return token.subdued\n } else if ('filePath' in token) {\n return token.filePath\n } else if ('list' in token) {\n return token.list.items.map(tokenItemToString).join(' ')\n } else if ('bold' in token) {\n return token.bold\n } else if ('info' in token) {\n return token.info\n } else if ('warn' in token) {\n return token.warn\n } else if ('error' in token) {\n return token.error\n } else {\n return token\n .map((item, index) => {\n if (index !== 0 && !(typeof item !== 'string' && 'char' in item)) {\n return ` ${tokenItemToString(item)}`\n } else {\n return tokenItemToString(item)\n }\n })\n .join('')\n }\n}\n\nexport function appendToTokenItem(token: TokenItem, suffix: string): TokenItem {\n return Array.isArray(token) ? [...token, {char: suffix}] : [token, {char: suffix}]\n}\n\nfunction splitByDisplayType(acc: Block[][], item: Block) {\n if (item.display === 'block') {\n acc.push([item])\n } else {\n const last = acc[acc.length - 1]\n if (last && last[0]!.display === 'inline') {\n last.push(item)\n } else {\n acc.push([item])\n }\n }\n return acc\n}\n\nconst InlineBlocks: React.FC<{blocks: Block[]}> = ({blocks}) => {\n return (\n <Text>\n {blocks.map((block, blockIndex) => (\n <Text key={blockIndex}>\n {blockIndex !== 0 && !(typeof block.value !== 'string' && 'char' in block.value) && <Text> </Text>}\n <TokenizedText item={block.value} />\n </Text>\n ))}\n </Text>\n )\n}\n\ninterface TokenizedTextProps {\n item: TokenItem\n}\n\n/**\n * `TokenizedText` renders a text string with tokens that can be either strings,\n * links, and commands.\n */\nconst TokenizedText: FunctionComponent<TokenizedTextProps> = ({item}) => {\n if (typeof item === 'string') {\n return <Text>{item}</Text>\n } else if ('command' in item) {\n return <Command command={item.command} />\n } else if ('link' in item) {\n return <Link {...item.link} />\n } else if ('char' in item) {\n return <Text>{item.char[0]}</Text>\n } else if ('userInput' in item) {\n return <UserInput userInput={item.userInput} />\n } else if ('subdued' in item) {\n return <Subdued subdued={item.subdued} />\n } else if ('filePath' in item) {\n return <FilePath filePath={item.filePath} />\n } else if ('list' in item) {\n return <List {...item.list} />\n } else if ('bold' in item) {\n return <Text bold>{item.bold}</Text>\n } else if ('info' in item) {\n return <Text color=\"blue\">{item.info}</Text>\n } else if ('warn' in item) {\n return <Text color=\"yellow\">{item.warn}</Text>\n } else if ('error' in item) {\n return <Text color=\"red\">{item.error}</Text>\n } else {\n const groupedItems = item.map(tokenToBlock).reduce(splitByDisplayType, [])\n\n return groupedItems.length === 1 && groupedItems[0]!.every((item) => item.display === 'inline') ? (\n <InlineBlocks blocks={groupedItems[0]!} />\n ) : (\n <Box flexDirection=\"column\">\n {groupedItems.map((items, groupIndex) => {\n if (items[0]!.display === 'inline') {\n return <InlineBlocks blocks={items} key={groupIndex} />\n } else {\n return <List key={groupIndex} {...(items[0]!.value as ListToken).list} />\n }\n })}\n </Box>\n )\n }\n}\n\nexport {TokenizedText}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-select-state.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/hooks/use-select-state.ts"],"names":[],"mappings":"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","sourcesContent":["import {Item} from '../components/SelectInput.js'\nimport {useReducer, useCallback, useMemo, useState} from 'react'\nimport {isDeepStrictEqual} from 'node:util'\n\ntype Option<T> = Item<T>\n\ntype OptionMapItem<T> = Option<T> & {\n previous: OptionMapItem<T> | undefined\n next: OptionMapItem<T> | undefined\n index: number\n}\n\nexport default class OptionMap<T> extends Map<T, OptionMapItem<T>> {\n readonly first: OptionMapItem<T> | undefined\n\n constructor(options: Option<T>[]) {\n const items: [T, OptionMapItem<T>][] = []\n let firstItem: OptionMapItem<T> | undefined\n let previous: OptionMapItem<T> | undefined\n let index = 0\n\n for (const option of options) {\n const item = {\n ...option,\n previous,\n next: undefined,\n index,\n }\n\n if (previous) {\n previous.next = item\n }\n\n if (!firstItem) {\n firstItem = item\n }\n\n items.push([option.value, item])\n index++\n previous = item\n }\n\n super(items)\n this.first = firstItem\n }\n}\n\ninterface State<T> {\n /**\n * Map where key is option's value and value is option's index.\n */\n optionMap: OptionMap<T>\n\n /**\n * Number of visible options.\n */\n visibleOptionCount: number\n\n /**\n * Index of the first visible option.\n */\n visibleFromIndex: number\n\n /**\n * Index of the last visible option.\n */\n visibleToIndex: number\n\n /**\n * Value of the previously selected option.\n */\n previousValue: T | undefined\n\n /**\n * Value of the selected option.\n */\n value: T | undefined\n}\n\ntype Action<T> = SelectNextOptionAction | SelectPreviousOptionAction | SelectOptionAction<T> | ResetAction<T>\n\ninterface SelectNextOptionAction {\n type: 'select-next-option'\n}\n\ninterface SelectPreviousOptionAction {\n type: 'select-previous-option'\n}\n\ninterface SelectOptionAction<T> {\n type: 'select-option'\n option: Option<T>\n}\n\ninterface ResetAction<T> {\n type: 'reset'\n state: State<T>\n}\n\nconst reducer = <T>(state: State<T>, action: Action<T>): State<T> => {\n switch (action.type) {\n case 'select-next-option': {\n if (typeof state.value === 'undefined') {\n return state\n }\n\n const item = state.optionMap.get(state.value)\n\n if (!item) {\n return state\n }\n\n let next = item.next\n\n while (next && next.disabled) {\n next = next.next\n }\n\n if (!next) {\n return state\n }\n\n const needsToScroll = next.index > state.visibleToIndex\n\n if (!needsToScroll) {\n return {\n ...state,\n value: next.value,\n }\n }\n\n const nextVisibleToIndex = next.index\n const nextVisibleFromIndex = nextVisibleToIndex - state.visibleOptionCount + 1\n\n return {\n ...state,\n value: next.value,\n visibleFromIndex: nextVisibleFromIndex,\n visibleToIndex: nextVisibleToIndex,\n previousValue: state.value,\n }\n }\n\n case 'select-previous-option': {\n if (typeof state.value === 'undefined') {\n return state\n }\n\n const item = state.optionMap.get(state.value)\n\n if (!item) {\n return state\n }\n\n let previous = item.previous\n\n while (previous && previous.disabled) {\n previous = previous.previous\n }\n\n if (!previous) {\n return state\n }\n\n const needsToScroll = previous.index < state.visibleFromIndex\n\n if (!needsToScroll) {\n return {\n ...state,\n value: previous.value,\n }\n }\n\n const nextVisibleFromIndex = previous.index\n const nextVisibleToIndex = nextVisibleFromIndex + state.visibleOptionCount - 1\n\n return {\n ...state,\n value: previous.value,\n visibleFromIndex: nextVisibleFromIndex,\n visibleToIndex: nextVisibleToIndex,\n previousValue: state.value,\n }\n }\n\n case 'select-option': {\n const item = state.optionMap.get(action.option.value)\n\n if (!item) {\n return state\n }\n\n return {\n ...state,\n value: item.value,\n previousValue: state.value,\n }\n }\n\n case 'reset': {\n return action.state\n }\n\n default: {\n return state\n }\n }\n}\n\nexport interface UseSelectStateProps<T> {\n /**\n * Number of items to display.\n *\n */\n visibleOptionCount: number\n\n /**\n * Options.\n */\n options: Option<T>[]\n\n /**\n * Initially selected option's value.\n */\n defaultValue?: T\n}\n\nexport type SelectState<T> = Pick<State<T>, 'visibleOptionCount' | 'visibleFromIndex' | 'visibleToIndex' | 'value'> & {\n /**\n * Visible options.\n */\n visibleOptions: (Option<T> & {index: number})[]\n\n /**\n * Select next option and scroll the list down, if needed.\n */\n selectNextOption: () => void\n\n /**\n * Select previous option and scroll the list up, if needed.\n */\n selectPreviousOption: () => void\n\n /**\n * Select option directly.\n */\n selectOption: (option: Option<T>) => void\n}\n\ntype CreateDefaultStateProps<T> = Pick<UseSelectStateProps<T>, 'visibleOptionCount' | 'defaultValue' | 'options'>\n\nconst createDefaultState = <T>({\n visibleOptionCount: customVisibleOptionCount,\n defaultValue,\n options,\n}: CreateDefaultStateProps<T>) => {\n const visibleOptionCount =\n typeof customVisibleOptionCount === 'number' ? Math.min(customVisibleOptionCount, options.length) : options.length\n const optionMap = new OptionMap(options)\n const defaultOption = typeof defaultValue === 'undefined' ? undefined : optionMap.get(defaultValue)\n let option = defaultOption && !defaultOption.disabled ? defaultOption : optionMap.first\n\n while (option && option.disabled) {\n option = option.next\n }\n\n return {\n optionMap,\n visibleOptionCount,\n visibleFromIndex: 0,\n visibleToIndex: visibleOptionCount - 1,\n value: option?.value,\n previousValue: option?.value,\n }\n}\n\nexport const useSelectState = <T>({visibleOptionCount, options, defaultValue}: UseSelectStateProps<T>) => {\n const [state, dispatch] = useReducer(reducer, {visibleOptionCount, defaultValue, options}, createDefaultState)\n const [lastOptions, setLastOptions] = useState(options)\n const [lastVisibleOptionCount, setLastVisibleOptionCount] = useState(visibleOptionCount)\n\n if (options !== lastOptions && !isDeepStrictEqual(options, lastOptions)) {\n dispatch({\n type: 'reset',\n state: createDefaultState({visibleOptionCount, defaultValue, options}),\n })\n\n setLastOptions(options)\n }\n\n if (visibleOptionCount !== lastVisibleOptionCount) {\n dispatch({\n type: 'reset',\n state: createDefaultState({visibleOptionCount, defaultValue, options}),\n })\n\n setLastVisibleOptionCount(visibleOptionCount)\n }\n\n const selectNextOption = useCallback(() => {\n dispatch({\n type: 'select-next-option',\n })\n }, [])\n\n const selectPreviousOption = useCallback(() => {\n dispatch({\n type: 'select-previous-option',\n })\n }, [])\n\n const selectOption = useCallback(({option}: {option: Option<T>}) => {\n dispatch({\n type: 'select-option',\n option,\n })\n }, [])\n\n const visibleOptions = useMemo(() => {\n return options.slice(state.visibleFromIndex)\n }, [options, state.visibleFromIndex])\n\n return {\n visibleFromIndex: state.visibleFromIndex,\n visibleToIndex: state.visibleToIndex,\n value: state.value,\n visibleOptions,\n selectNextOption,\n selectPreviousOption,\n selectOption,\n previousValue: state.previousValue,\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-select-state.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/hooks/use-select-state.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AAChE,OAAO,EAAC,iBAAiB,EAAC,MAAM,WAAW,CAAA;AAU3C,MAAM,CAAC,OAAO,OAAO,SAAa,SAAQ,GAAwB;IAGhE,YAAY,OAAoB;QAC9B,MAAM,KAAK,GAA4B,EAAE,CAAA;QACzC,IAAI,SAAuC,CAAA;QAC3C,IAAI,QAAsC,CAAA;QAC1C,IAAI,KAAK,GAAG,CAAC,CAAA;QAEb,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG;gBACX,GAAG,MAAM;gBACT,QAAQ;gBACR,IAAI,EAAE,SAAS;gBACf,KAAK;aACN,CAAA;YAED,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAA;YACtB,CAAC;YAED,SAAS,KAAT,SAAS,GAAK,IAAI,EAAA;YAElB,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;YAChC,KAAK,EAAE,CAAA;YACP,QAAQ,GAAG,IAAI,CAAA;QACjB,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,CAAA;QACZ,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;IACxB,CAAC;CACF;AAsDD,MAAM,OAAO,GAAG,CAAI,KAAe,EAAE,MAAiB,EAAY,EAAE;IAClE,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC1B,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;gBACvC,OAAO,KAAK,CAAA;YACd,CAAC;YAED,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAE7C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,KAAK,CAAA;YACd,CAAC;YAED,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;YAEpB,OAAO,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC7B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;YAClB,CAAC;YAED,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,KAAK,CAAA;YACd,CAAC;YAED,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,cAAc,CAAA;YAEvD,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,OAAO;oBACL,GAAG,KAAK;oBACR,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB,CAAA;YACH,CAAC;YAED,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAA;YACrC,MAAM,oBAAoB,GAAG,kBAAkB,GAAG,KAAK,CAAC,kBAAkB,GAAG,CAAC,CAAA;YAE9E,OAAO;gBACL,GAAG,KAAK;gBACR,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,gBAAgB,EAAE,oBAAoB;gBACtC,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,KAAK,CAAC,KAAK;aAC3B,CAAA;QACH,CAAC;QAED,KAAK,wBAAwB,CAAC,CAAC,CAAC;YAC9B,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;gBACvC,OAAO,KAAK,CAAA;YACd,CAAC;YAED,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAE7C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,KAAK,CAAA;YACd,CAAC;YAED,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;YAE5B,OAAO,QAAQ,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACrC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAA;YAC9B,CAAC;YAED,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,KAAK,CAAA;YACd,CAAC;YAED,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC,gBAAgB,CAAA;YAE7D,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,OAAO;oBACL,GAAG,KAAK;oBACR,KAAK,EAAE,QAAQ,CAAC,KAAK;iBACtB,CAAA;YACH,CAAC;YAED,MAAM,oBAAoB,GAAG,QAAQ,CAAC,KAAK,CAAA;YAC3C,MAAM,kBAAkB,GAAG,oBAAoB,GAAG,KAAK,CAAC,kBAAkB,GAAG,CAAC,CAAA;YAE9E,OAAO;gBACL,GAAG,KAAK;gBACR,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,gBAAgB,EAAE,oBAAoB;gBACtC,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,KAAK,CAAC,KAAK;aAC3B,CAAA;QACH,CAAC;QAED,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAErD,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,KAAK,CAAA;YACd,CAAC;YAED,OAAO;gBACL,GAAG,KAAK;gBACR,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,aAAa,EAAE,KAAK,CAAC,KAAK;aAC3B,CAAA;QACH,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,OAAO,MAAM,CAAC,KAAK,CAAA;QACrB,CAAC;QAED,OAAO,CAAC,CAAC,CAAC;YACR,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AA4CD,MAAM,kBAAkB,GAAG,CAAI,EAC7B,kBAAkB,EAAE,wBAAwB,EAC5C,YAAY,EACZ,OAAO,GACoB,EAAE,EAAE;IAC/B,MAAM,kBAAkB,GACtB,OAAO,wBAAwB,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,wBAAwB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAA;IACpH,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,CAAA;IACxC,MAAM,aAAa,GAAG,OAAO,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IACnG,IAAI,MAAM,GAAG,aAAa,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAA;IAEvF,OAAO,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAA;IACtB,CAAC;IAED,OAAO;QACL,SAAS;QACT,kBAAkB;QAClB,gBAAgB,EAAE,CAAC;QACnB,cAAc,EAAE,kBAAkB,GAAG,CAAC;QACtC,KAAK,EAAE,MAAM,EAAE,KAAK;QACpB,aAAa,EAAE,MAAM,EAAE,KAAK;KAC7B,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAAI,EAAC,kBAAkB,EAAE,OAAO,EAAE,YAAY,EAAyB,EAAE,EAAE;IACvG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,EAAC,kBAAkB,EAAE,YAAY,EAAE,OAAO,EAAC,EAAE,kBAAkB,CAAC,CAAA;IAC9G,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IACvD,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAAA;IAExF,IAAI,OAAO,KAAK,WAAW,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;QACxE,QAAQ,CAAC;YACP,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,kBAAkB,CAAC,EAAC,kBAAkB,EAAE,YAAY,EAAE,OAAO,EAAC,CAAC;SACvE,CAAC,CAAA;QAEF,cAAc,CAAC,OAAO,CAAC,CAAA;IACzB,CAAC;IAED,IAAI,kBAAkB,KAAK,sBAAsB,EAAE,CAAC;QAClD,QAAQ,CAAC;YACP,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,kBAAkB,CAAC,EAAC,kBAAkB,EAAE,YAAY,EAAE,OAAO,EAAC,CAAC;SACvE,CAAC,CAAA;QAEF,yBAAyB,CAAC,kBAAkB,CAAC,CAAA;IAC/C,CAAC;IAED,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,EAAE;QACxC,QAAQ,CAAC;YACP,IAAI,EAAE,oBAAoB;SAC3B,CAAC,CAAA;IACJ,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,oBAAoB,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5C,QAAQ,CAAC;YACP,IAAI,EAAE,wBAAwB;SAC/B,CAAC,CAAA;IACJ,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,EAAC,MAAM,EAAsB,EAAE,EAAE;QACjE,QAAQ,CAAC;YACP,IAAI,EAAE,eAAe;YACrB,MAAM;SACP,CAAC,CAAA;IACJ,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE;QAClC,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAA;IAC9C,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAA;IAErC,OAAO;QACL,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,cAAc;QACd,gBAAgB;QAChB,oBAAoB;QACpB,YAAY;QACZ,aAAa,EAAE,KAAK,CAAC,aAAa;KACnC,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {Item} from '../components/SelectInput.js'\nimport {useReducer, useCallback, useMemo, useState} from 'react'\nimport {isDeepStrictEqual} from 'node:util'\n\ntype Option<T> = Item<T>\n\ntype OptionMapItem<T> = Option<T> & {\n previous: OptionMapItem<T> | undefined\n next: OptionMapItem<T> | undefined\n index: number\n}\n\nexport default class OptionMap<T> extends Map<T, OptionMapItem<T>> {\n readonly first: OptionMapItem<T> | undefined\n\n constructor(options: Option<T>[]) {\n const items: [T, OptionMapItem<T>][] = []\n let firstItem: OptionMapItem<T> | undefined\n let previous: OptionMapItem<T> | undefined\n let index = 0\n\n for (const option of options) {\n const item = {\n ...option,\n previous,\n next: undefined,\n index,\n }\n\n if (previous) {\n previous.next = item\n }\n\n firstItem ??= item\n\n items.push([option.value, item])\n index++\n previous = item\n }\n\n super(items)\n this.first = firstItem\n }\n}\n\ninterface State<T> {\n /**\n * Map where key is option's value and value is option's index.\n */\n optionMap: OptionMap<T>\n\n /**\n * Number of visible options.\n */\n visibleOptionCount: number\n\n /**\n * Index of the first visible option.\n */\n visibleFromIndex: number\n\n /**\n * Index of the last visible option.\n */\n visibleToIndex: number\n\n /**\n * Value of the previously selected option.\n */\n previousValue: T | undefined\n\n /**\n * Value of the selected option.\n */\n value: T | undefined\n}\n\ntype Action<T> = SelectNextOptionAction | SelectPreviousOptionAction | SelectOptionAction<T> | ResetAction<T>\n\ninterface SelectNextOptionAction {\n type: 'select-next-option'\n}\n\ninterface SelectPreviousOptionAction {\n type: 'select-previous-option'\n}\n\ninterface SelectOptionAction<T> {\n type: 'select-option'\n option: Option<T>\n}\n\ninterface ResetAction<T> {\n type: 'reset'\n state: State<T>\n}\n\nconst reducer = <T>(state: State<T>, action: Action<T>): State<T> => {\n switch (action.type) {\n case 'select-next-option': {\n if (typeof state.value === 'undefined') {\n return state\n }\n\n const item = state.optionMap.get(state.value)\n\n if (!item) {\n return state\n }\n\n let next = item.next\n\n while (next && next.disabled) {\n next = next.next\n }\n\n if (!next) {\n return state\n }\n\n const needsToScroll = next.index > state.visibleToIndex\n\n if (!needsToScroll) {\n return {\n ...state,\n value: next.value,\n }\n }\n\n const nextVisibleToIndex = next.index\n const nextVisibleFromIndex = nextVisibleToIndex - state.visibleOptionCount + 1\n\n return {\n ...state,\n value: next.value,\n visibleFromIndex: nextVisibleFromIndex,\n visibleToIndex: nextVisibleToIndex,\n previousValue: state.value,\n }\n }\n\n case 'select-previous-option': {\n if (typeof state.value === 'undefined') {\n return state\n }\n\n const item = state.optionMap.get(state.value)\n\n if (!item) {\n return state\n }\n\n let previous = item.previous\n\n while (previous && previous.disabled) {\n previous = previous.previous\n }\n\n if (!previous) {\n return state\n }\n\n const needsToScroll = previous.index < state.visibleFromIndex\n\n if (!needsToScroll) {\n return {\n ...state,\n value: previous.value,\n }\n }\n\n const nextVisibleFromIndex = previous.index\n const nextVisibleToIndex = nextVisibleFromIndex + state.visibleOptionCount - 1\n\n return {\n ...state,\n value: previous.value,\n visibleFromIndex: nextVisibleFromIndex,\n visibleToIndex: nextVisibleToIndex,\n previousValue: state.value,\n }\n }\n\n case 'select-option': {\n const item = state.optionMap.get(action.option.value)\n\n if (!item) {\n return state\n }\n\n return {\n ...state,\n value: item.value,\n previousValue: state.value,\n }\n }\n\n case 'reset': {\n return action.state\n }\n\n default: {\n return state\n }\n }\n}\n\nexport interface UseSelectStateProps<T> {\n /**\n * Number of items to display.\n *\n */\n visibleOptionCount: number\n\n /**\n * Options.\n */\n options: Option<T>[]\n\n /**\n * Initially selected option's value.\n */\n defaultValue?: T\n}\n\nexport type SelectState<T> = Pick<State<T>, 'visibleOptionCount' | 'visibleFromIndex' | 'visibleToIndex' | 'value'> & {\n /**\n * Visible options.\n */\n visibleOptions: (Option<T> & {index: number})[]\n\n /**\n * Select next option and scroll the list down, if needed.\n */\n selectNextOption: () => void\n\n /**\n * Select previous option and scroll the list up, if needed.\n */\n selectPreviousOption: () => void\n\n /**\n * Select option directly.\n */\n selectOption: (option: Option<T>) => void\n}\n\ntype CreateDefaultStateProps<T> = Pick<UseSelectStateProps<T>, 'visibleOptionCount' | 'defaultValue' | 'options'>\n\nconst createDefaultState = <T>({\n visibleOptionCount: customVisibleOptionCount,\n defaultValue,\n options,\n}: CreateDefaultStateProps<T>) => {\n const visibleOptionCount =\n typeof customVisibleOptionCount === 'number' ? Math.min(customVisibleOptionCount, options.length) : options.length\n const optionMap = new OptionMap(options)\n const defaultOption = typeof defaultValue === 'undefined' ? undefined : optionMap.get(defaultValue)\n let option = defaultOption && !defaultOption.disabled ? defaultOption : optionMap.first\n\n while (option && option.disabled) {\n option = option.next\n }\n\n return {\n optionMap,\n visibleOptionCount,\n visibleFromIndex: 0,\n visibleToIndex: visibleOptionCount - 1,\n value: option?.value,\n previousValue: option?.value,\n }\n}\n\nexport const useSelectState = <T>({visibleOptionCount, options, defaultValue}: UseSelectStateProps<T>) => {\n const [state, dispatch] = useReducer(reducer, {visibleOptionCount, defaultValue, options}, createDefaultState)\n const [lastOptions, setLastOptions] = useState(options)\n const [lastVisibleOptionCount, setLastVisibleOptionCount] = useState(visibleOptionCount)\n\n if (options !== lastOptions && !isDeepStrictEqual(options, lastOptions)) {\n dispatch({\n type: 'reset',\n state: createDefaultState({visibleOptionCount, defaultValue, options}),\n })\n\n setLastOptions(options)\n }\n\n if (visibleOptionCount !== lastVisibleOptionCount) {\n dispatch({\n type: 'reset',\n state: createDefaultState({visibleOptionCount, defaultValue, options}),\n })\n\n setLastVisibleOptionCount(visibleOptionCount)\n }\n\n const selectNextOption = useCallback(() => {\n dispatch({\n type: 'select-next-option',\n })\n }, [])\n\n const selectPreviousOption = useCallback(() => {\n dispatch({\n type: 'select-previous-option',\n })\n }, [])\n\n const selectOption = useCallback(({option}: {option: Option<T>}) => {\n dispatch({\n type: 'select-option',\n option,\n })\n }, [])\n\n const visibleOptions = useMemo(() => {\n return options.slice(state.visibleFromIndex)\n }, [options, state.visibleFromIndex])\n\n return {\n visibleFromIndex: state.visibleFromIndex,\n visibleToIndex: state.visibleToIndex,\n value: state.value,\n visibleOptions,\n selectNextOption,\n selectPreviousOption,\n selectOption,\n previousValue: state.previousValue,\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CLI_KIT_VERSION = "3.
|
|
1
|
+
export declare const CLI_KIT_VERSION = "3.93.1";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const CLI_KIT_VERSION = '3.
|
|
1
|
+
export const CLI_KIT_VERSION = '3.93.1';
|
|
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,QAAQ,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '3.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '3.93.1'\n"]}
|
|
@@ -52,13 +52,13 @@ export async function reportAnalyticsEvent(options) {
|
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
54
|
const doOpenTelemetry = async () => {
|
|
55
|
-
const active = payload.public.cmd_all_timing_active_ms
|
|
56
|
-
const network = payload.public.cmd_all_timing_network_ms
|
|
57
|
-
const prompt = payload.public.cmd_all_timing_prompts_ms
|
|
55
|
+
const active = payload.public.cmd_all_timing_active_ms ?? 0;
|
|
56
|
+
const network = payload.public.cmd_all_timing_network_ms ?? 0;
|
|
57
|
+
const prompt = payload.public.cmd_all_timing_prompts_ms ?? 0;
|
|
58
58
|
return recordMetrics({
|
|
59
59
|
skipMetricAnalytics,
|
|
60
60
|
cliVersion: payload.public.cli_version,
|
|
61
|
-
owningPlugin: payload.public.cmd_all_plugin
|
|
61
|
+
owningPlugin: payload.public.cmd_all_plugin ?? '@shopify/cli',
|
|
62
62
|
command: payload.public.command,
|
|
63
63
|
exitMode: options.exitMode,
|
|
64
64
|
}, {
|
|
@@ -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, isShopify} from './context/local.js'\nimport * as metadata from './metadata.js'\nimport {publishMonorailEvent, MONORAIL_COMMAND_TOPIC} 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\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 payload = await buildPayload(options)\n if (payload === undefined) {\n // Nothing to log\n return\n }\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 }\n\n const doMonorail = async () => {\n if (skipMonorailAnalytics) {\n return\n }\n const response = await publishMonorailEvent(MONORAIL_COMMAND_TOPIC, payload.public, payload.sensitive)\n if (response.type === 'error') {\n outputDebug(response.message)\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: options.exitMode,\n },\n {\n active,\n network,\n prompt,\n },\n )\n }\n await Promise.all([doMonorail(), doOpenTelemetry()])\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({config, errorMessage, exitMode}: ReportAnalyticsEventOptions) {\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} = commandStartOptions\n const currentTime = 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 let 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 // strip undefined fields -- they make up the majority of payloads due to wide metadata structure.\n payload = JSON.parse(JSON.stringify(payload))\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.replace(/shptka_\\w*/g, '*****')\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, isShopify} from './context/local.js'\nimport * as metadata from './metadata.js'\nimport {publishMonorailEvent, MONORAIL_COMMAND_TOPIC} 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\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 payload = await buildPayload(options)\n if (payload === undefined) {\n // Nothing to log\n return\n }\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 }\n\n const doMonorail = async () => {\n if (skipMonorailAnalytics) {\n return\n }\n const response = await publishMonorailEvent(MONORAIL_COMMAND_TOPIC, payload.public, payload.sensitive)\n if (response.type === 'error') {\n outputDebug(response.message)\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: options.exitMode,\n },\n {\n active,\n network,\n prompt,\n },\n )\n }\n await Promise.all([doMonorail(), doOpenTelemetry()])\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({config, errorMessage, exitMode}: ReportAnalyticsEventOptions) {\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} = commandStartOptions\n const currentTime = 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 let 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 // strip undefined fields -- they make up the majority of payloads due to wide metadata structure.\n payload = JSON.parse(JSON.stringify(payload))\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.replace(/shptka_\\w*/g, '*****')\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"]}
|
|
@@ -39,9 +39,7 @@ export async function adminRequest(query, session, variables) {
|
|
|
39
39
|
export async function adminRequestDoc(options) {
|
|
40
40
|
const { query, session, variables, version, responseOptions, preferredBehaviour } = options;
|
|
41
41
|
let apiVersion = version ?? LatestApiVersionByFQDN.get(session.storeFqdn);
|
|
42
|
-
|
|
43
|
-
apiVersion = await fetchLatestSupportedApiVersion(session, preferredBehaviour);
|
|
44
|
-
}
|
|
42
|
+
apiVersion ?? (apiVersion = await fetchLatestSupportedApiVersion(session, preferredBehaviour));
|
|
45
43
|
let storeDomain = session.storeFqdn;
|
|
46
44
|
const addedHeaders = themeAccessHeaders(session);
|
|
47
45
|
if (serviceEnvironment() === 'local') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../../src/public/node/api/admin.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n graphqlRequest,\n graphqlRequestDoc,\n GraphQLResponseOptions,\n GraphQLVariables,\n UnauthorizedHandler,\n} from './graphql.js'\nimport {AdminSession} from '../session.js'\nimport {outputContent, outputToken} from '../output.js'\nimport {AbortError, BugError} from '../error.js'\nimport {\n restRequestBody,\n restRequestHeaders,\n restRequestUrl,\n isThemeAccessSession,\n} from '../../../private/node/api/rest.js'\nimport {isNetworkError} from '../../../private/node/api.js'\nimport {RequestModeInput, shopifyFetch} from '../http.js'\nimport {PublicApiVersions} from '../../../cli/api/graphql/admin/generated/public_api_versions.js'\nimport {themeKitAccessDomain} from '../../../private/node/constants.js'\nimport {serviceEnvironment} from '../../../private/node/context/service.js'\nimport {DevServerCore} from '../vendor/dev_server/index.js'\nimport {ClientError, Variables} from 'graphql-request'\n\nimport {TypedDocumentNode} from '@graphql-typed-document-node/core'\n\nconst LatestApiVersionByFQDN = new Map<string, string>()\n\n/**\n * Executes a GraphQL query against the Admin API.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @returns The response of the query of generic type <T>.\n */\nexport async function adminRequest<T>(query: string, session: AdminSession, variables?: GraphQLVariables): Promise<T> {\n const api = 'Admin'\n const version = await fetchLatestSupportedApiVersion(session)\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const url = adminUrl(storeDomain, version, session)\n return graphqlRequest({query, api, addedHeaders, url, token: session.token, variables})\n}\n\nexport interface AdminRequestOptions<TResult, TVariables extends Variables> {\n /** GraphQL query to execute. */\n query: TypedDocumentNode<TResult, TVariables>\n /** Shopify admin session including token and Store FQDN. */\n session: AdminSession\n /** GraphQL variables to pass to the query. */\n variables?: TVariables\n /** API version. */\n version?: string\n /** Control how API responses will be handled. */\n responseOptions?: GraphQLResponseOptions<TResult>\n /** Custom request behaviour for retries and timeouts. */\n preferredBehaviour?: RequestModeInput\n}\n\n/**\n * Executes a GraphQL query against the Admin API. Uses typed documents.\n *\n * @param options - Admin request options.\n * @returns The response of the query of generic type <TResult>.\n */\nexport async function adminRequestDoc<TResult, TVariables extends Variables>(\n options: AdminRequestOptions<TResult, TVariables>,\n): Promise<TResult> {\n const {query, session, variables, version, responseOptions, preferredBehaviour} = options\n\n let apiVersion = version ?? LatestApiVersionByFQDN.get(session.storeFqdn)\n if (!apiVersion) {\n apiVersion = await fetchLatestSupportedApiVersion(session, preferredBehaviour)\n }\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const opts = {\n url: adminUrl(storeDomain, apiVersion, session),\n api: 'Admin',\n token: session.token,\n addedHeaders,\n }\n let unauthorizedHandler: UnauthorizedHandler | undefined\n if ('refresh' in session) {\n unauthorizedHandler = {type: 'token_refresh', handler: session.refresh as () => Promise<{token: string}>}\n }\n const result = graphqlRequestDoc<TResult, TVariables>({\n ...opts,\n query,\n variables,\n responseOptions,\n unauthorizedHandler,\n preferredBehaviour,\n })\n return result\n}\n\nfunction themeAccessHeaders(session: AdminSession): Record<string, string> {\n return isThemeAccessSession(session)\n ? {'X-Shopify-Shop': session.storeFqdn, 'X-Shopify-Access-Token': session.token}\n : {}\n}\n\n/**\n * GraphQL query to retrieve the latest supported API version.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - The latest supported API version.\n */\nasync function fetchLatestSupportedApiVersion(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string> {\n const apiVersions = await supportedApiVersions(session, preferredBehaviour)\n\n const latest = apiVersions.reverse()[0]!\n LatestApiVersionByFQDN.set(session.storeFqdn, latest)\n return latest\n}\n\n/**\n * GraphQL query to retrieve all supported API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported API versions.\n */\nexport async function supportedApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string[]> {\n const apiVersions = await fetchApiVersions(session, preferredBehaviour)\n return apiVersions\n .filter((item) => item.supported)\n .map((item) => item.handle)\n .sort()\n}\n\n/**\n * GraphQL query to retrieve all API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported and unsupported API versions.\n */\nexport async function fetchApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<ApiVersion[]> {\n try {\n const response = await adminRequestDoc({\n query: PublicApiVersions,\n session,\n variables: {},\n version: 'unstable',\n responseOptions: {handleErrors: false},\n preferredBehaviour,\n })\n return response.publicApiVersions\n } catch (error) {\n if (error instanceof ClientError && error.response.status === 403) {\n const storeName = session.storeFqdn.replace('.myshopify.com', '')\n throw new AbortError(\n outputContent`Looks like you don't have access to this dev store: (${outputToken.link(\n storeName,\n `https://${session.storeFqdn}`,\n )})`,\n outputContent`If you're not the owner, create a dev store staff account for yourself`,\n )\n }\n if (error instanceof ClientError && (error.response.status === 401 || error.response.status === 404)) {\n throw new AbortError(\n `Error connecting to your store ${session.storeFqdn}: ${error.message} ${error.response.status} ${error.response.data}`,\n )\n }\n\n // Check for network-level errors (connection issues, timeouts, DNS failures, TLS/certificate errors, etc.)\n // All network errors should be treated as user-facing errors, not CLI bugs\n // Note: Some of these may have been retried already by lower-level retry logic\n if (isNetworkError(error)) {\n throw new AbortError(\n `Network error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'Check your internet connection and try again.',\n )\n }\n\n // Unknown errors are likely bugs in the CLI\n throw new BugError(\n `Unknown error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n}\n\n/**\n * Returns the Admin API URL for the given store and version.\n *\n * @param store - Store FQDN.\n * @param version - API version.\n * @param session - User session.\n * @returns - Admin API URL.\n */\nexport function adminUrl(store: string, version: string | undefined, session?: AdminSession): string {\n const realVersion = version ?? 'unstable'\n\n const url =\n session && isThemeAccessSession(session)\n ? `https://${themeKitAccessDomain}/cli/admin/api/${realVersion}/graphql.json`\n : `https://${store}/admin/api/${realVersion}/graphql.json`\n return url\n}\n\ninterface ApiVersion {\n handle: string\n supported: boolean\n}\n\n/**\n * Executes a REST request against the Admin API.\n *\n * @param method - Request's HTTP method.\n * @param path - Path of the REST resource.\n * @param session - Shopify Admin session including token and Store FQDN.\n * @param requestBody - Request body of including REST resource specific parameters.\n * @param searchParams - Search params, appended to the URL.\n * @param apiVersion - Admin API version.\n * @returns - The {@link RestResponse}.\n */\nexport async function restRequest<T>(\n method: string,\n path: string,\n session: AdminSession,\n requestBody?: T,\n searchParams: Record<string, string> = {},\n apiVersion = 'unstable',\n): Promise<RestResponse> {\n const url = restRequestUrl(session, apiVersion, path, searchParams)\n const body = restRequestBody<T>(requestBody)\n\n const headers = restRequestHeaders(session)\n const response = await shopifyFetch(url, {\n headers,\n method,\n body,\n })\n\n const json = await response.json().catch(() => ({}))\n\n return {\n json,\n status: response.status,\n headers: response.headers.raw(),\n }\n}\n\n/**\n * Respose of a REST request.\n */\nexport interface RestResponse {\n /**\n * REST JSON respose.\n */\n // Using `any` to avoid introducing extra DTO layers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: any\n\n /**\n * HTTP response status.\n */\n status: number\n\n /**\n * HTTP response headers.\n */\n headers: Record<string, string[]>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../../src/public/node/api/admin.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,iBAAiB,GAIlB,MAAM,cAAc,CAAA;AAErB,OAAO,EAAC,aAAa,EAAE,WAAW,EAAC,MAAM,cAAc,CAAA;AACvD,OAAO,EAAC,UAAU,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAA;AAChD,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,oBAAoB,GACrB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAmB,YAAY,EAAC,MAAM,YAAY,CAAA;AACzD,OAAO,EAAC,iBAAiB,EAAC,MAAM,iEAAiE,CAAA;AACjG,OAAO,EAAC,oBAAoB,EAAC,MAAM,oCAAoC,CAAA;AACvE,OAAO,EAAC,kBAAkB,EAAC,MAAM,0CAA0C,CAAA;AAC3E,OAAO,EAAC,aAAa,EAAC,MAAM,+BAA+B,CAAA;AAC3D,OAAO,EAAC,WAAW,EAAY,MAAM,iBAAiB,CAAA;AAItD,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAkB,CAAA;AAExD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,KAAa,EAAE,OAAqB,EAAE,SAA4B;IACtG,MAAM,GAAG,GAAG,OAAO,CAAA;IACnB,MAAM,OAAO,GAAG,MAAM,8BAA8B,CAAC,OAAO,CAAC,CAAA;IAC7D,IAAI,WAAW,GAAG,OAAO,CAAC,SAAS,CAAA;IACnC,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAEhD,IAAI,kBAAkB,EAAE,KAAK,OAAO,EAAE,CAAC;QACrC,YAAY,CAAC,kBAAkB,CAAC,GAAG,WAAW,CAAA;QAC9C,WAAW,GAAG,IAAI,aAAa,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/C,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACnD,OAAO,cAAc,CAAC,EAAC,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,SAAS,EAAC,CAAC,CAAA;AACzF,CAAC;AAiBD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAiD;IAEjD,MAAM,EAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAC,GAAG,OAAO,CAAA;IAEzF,IAAI,UAAU,GAAG,OAAO,IAAI,sBAAsB,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACzE,UAAU,KAAV,UAAU,GAAK,MAAM,8BAA8B,CAAC,OAAO,EAAE,kBAAkB,CAAC,EAAA;IAChF,IAAI,WAAW,GAAG,OAAO,CAAC,SAAS,CAAA;IACnC,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAEhD,IAAI,kBAAkB,EAAE,KAAK,OAAO,EAAE,CAAC;QACrC,YAAY,CAAC,kBAAkB,CAAC,GAAG,WAAW,CAAA;QAC9C,WAAW,GAAG,IAAI,aAAa,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/C,CAAC;IAED,MAAM,IAAI,GAAG;QACX,GAAG,EAAE,QAAQ,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC;QAC/C,GAAG,EAAE,OAAO;QACZ,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,YAAY;KACb,CAAA;IACD,IAAI,mBAAoD,CAAA;IACxD,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC;QACzB,mBAAmB,GAAG,EAAC,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,CAAC,OAAyC,EAAC,CAAA;IAC3G,CAAC;IACD,MAAM,MAAM,GAAG,iBAAiB,CAAsB;QACpD,GAAG,IAAI;QACP,KAAK;QACL,SAAS;QACT,eAAe;QACf,mBAAmB;QACnB,kBAAkB;KACnB,CAAC,CAAA;IACF,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAqB;IAC/C,OAAO,oBAAoB,CAAC,OAAO,CAAC;QAClC,CAAC,CAAC,EAAC,gBAAgB,EAAE,OAAO,CAAC,SAAS,EAAE,wBAAwB,EAAE,OAAO,CAAC,KAAK,EAAC;QAChF,CAAC,CAAC,EAAE,CAAA;AACR,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,8BAA8B,CAC3C,OAAqB,EACrB,kBAAqC;IAErC,MAAM,WAAW,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAA;IAE3E,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAE,CAAA;IACxC,sBAAsB,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IACrD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAqB,EACrB,kBAAqC;IAErC,MAAM,WAAW,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAA;IACvE,OAAO,WAAW;SACf,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;SAChC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;SAC1B,IAAI,EAAE,CAAA;AACX,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAqB,EACrB,kBAAqC;IAErC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC;YACrC,KAAK,EAAE,iBAAiB;YACxB,OAAO;YACP,SAAS,EAAE,EAAE;YACb,OAAO,EAAE,UAAU;YACnB,eAAe,EAAE,EAAC,YAAY,EAAE,KAAK,EAAC;YACtC,kBAAkB;SACnB,CAAC,CAAA;QACF,OAAO,QAAQ,CAAC,iBAAiB,CAAA;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAClE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAA;YACjE,MAAM,IAAI,UAAU,CAClB,aAAa,CAAA,wDAAwD,WAAW,CAAC,IAAI,CACnF,SAAS,EACT,WAAW,OAAO,CAAC,SAAS,EAAE,CAC/B,GAAG,EACJ,aAAa,CAAA,wEAAwE,CACtF,CAAA;QACH,CAAC;QACD,IAAI,KAAK,YAAY,WAAW,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC;YACrG,MAAM,IAAI,UAAU,CAClB,kCAAkC,OAAO,CAAC,SAAS,KAAK,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CACxH,CAAA;QACH,CAAC;QAED,2GAA2G;QAC3G,2EAA2E;QAC3E,+EAA+E;QAC/E,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CAClB,0CAA0C,OAAO,CAAC,SAAS,KACzD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,EACF,+CAA+C,CAChD,CAAA;QACH,CAAC;QAED,4CAA4C;QAC5C,MAAM,IAAI,QAAQ,CAChB,0CAA0C,OAAO,CAAC,SAAS,KACzD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,CACH,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,OAA2B,EAAE,OAAsB;IACzF,MAAM,WAAW,GAAG,OAAO,IAAI,UAAU,CAAA;IAEzC,MAAM,GAAG,GACP,OAAO,IAAI,oBAAoB,CAAC,OAAO,CAAC;QACtC,CAAC,CAAC,WAAW,oBAAoB,kBAAkB,WAAW,eAAe;QAC7E,CAAC,CAAC,WAAW,KAAK,cAAc,WAAW,eAAe,CAAA;IAC9D,OAAO,GAAG,CAAA;AACZ,CAAC;AAOD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,IAAY,EACZ,OAAqB,EACrB,WAAe,EACf,eAAuC,EAAE,EACzC,UAAU,GAAG,UAAU;IAEvB,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,CAAC,CAAA;IACnE,MAAM,IAAI,GAAG,eAAe,CAAI,WAAW,CAAC,CAAA;IAE5C,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE;QACvC,OAAO;QACP,MAAM;QACN,IAAI;KACL,CAAC,CAAA;IAEF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAEpD,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE;KAChC,CAAA;AACH,CAAC","sourcesContent":["import {\n graphqlRequest,\n graphqlRequestDoc,\n GraphQLResponseOptions,\n GraphQLVariables,\n UnauthorizedHandler,\n} from './graphql.js'\nimport {AdminSession} from '../session.js'\nimport {outputContent, outputToken} from '../output.js'\nimport {AbortError, BugError} from '../error.js'\nimport {\n restRequestBody,\n restRequestHeaders,\n restRequestUrl,\n isThemeAccessSession,\n} from '../../../private/node/api/rest.js'\nimport {isNetworkError} from '../../../private/node/api.js'\nimport {RequestModeInput, shopifyFetch} from '../http.js'\nimport {PublicApiVersions} from '../../../cli/api/graphql/admin/generated/public_api_versions.js'\nimport {themeKitAccessDomain} from '../../../private/node/constants.js'\nimport {serviceEnvironment} from '../../../private/node/context/service.js'\nimport {DevServerCore} from '../vendor/dev_server/index.js'\nimport {ClientError, Variables} from 'graphql-request'\n\nimport {TypedDocumentNode} from '@graphql-typed-document-node/core'\n\nconst LatestApiVersionByFQDN = new Map<string, string>()\n\n/**\n * Executes a GraphQL query against the Admin API.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @returns The response of the query of generic type <T>.\n */\nexport async function adminRequest<T>(query: string, session: AdminSession, variables?: GraphQLVariables): Promise<T> {\n const api = 'Admin'\n const version = await fetchLatestSupportedApiVersion(session)\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const url = adminUrl(storeDomain, version, session)\n return graphqlRequest({query, api, addedHeaders, url, token: session.token, variables})\n}\n\nexport interface AdminRequestOptions<TResult, TVariables extends Variables> {\n /** GraphQL query to execute. */\n query: TypedDocumentNode<TResult, TVariables>\n /** Shopify admin session including token and Store FQDN. */\n session: AdminSession\n /** GraphQL variables to pass to the query. */\n variables?: TVariables\n /** API version. */\n version?: string\n /** Control how API responses will be handled. */\n responseOptions?: GraphQLResponseOptions<TResult>\n /** Custom request behaviour for retries and timeouts. */\n preferredBehaviour?: RequestModeInput\n}\n\n/**\n * Executes a GraphQL query against the Admin API. Uses typed documents.\n *\n * @param options - Admin request options.\n * @returns The response of the query of generic type <TResult>.\n */\nexport async function adminRequestDoc<TResult, TVariables extends Variables>(\n options: AdminRequestOptions<TResult, TVariables>,\n): Promise<TResult> {\n const {query, session, variables, version, responseOptions, preferredBehaviour} = options\n\n let apiVersion = version ?? LatestApiVersionByFQDN.get(session.storeFqdn)\n apiVersion ??= await fetchLatestSupportedApiVersion(session, preferredBehaviour)\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const opts = {\n url: adminUrl(storeDomain, apiVersion, session),\n api: 'Admin',\n token: session.token,\n addedHeaders,\n }\n let unauthorizedHandler: UnauthorizedHandler | undefined\n if ('refresh' in session) {\n unauthorizedHandler = {type: 'token_refresh', handler: session.refresh as () => Promise<{token: string}>}\n }\n const result = graphqlRequestDoc<TResult, TVariables>({\n ...opts,\n query,\n variables,\n responseOptions,\n unauthorizedHandler,\n preferredBehaviour,\n })\n return result\n}\n\nfunction themeAccessHeaders(session: AdminSession): Record<string, string> {\n return isThemeAccessSession(session)\n ? {'X-Shopify-Shop': session.storeFqdn, 'X-Shopify-Access-Token': session.token}\n : {}\n}\n\n/**\n * GraphQL query to retrieve the latest supported API version.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - The latest supported API version.\n */\nasync function fetchLatestSupportedApiVersion(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string> {\n const apiVersions = await supportedApiVersions(session, preferredBehaviour)\n\n const latest = apiVersions.reverse()[0]!\n LatestApiVersionByFQDN.set(session.storeFqdn, latest)\n return latest\n}\n\n/**\n * GraphQL query to retrieve all supported API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported API versions.\n */\nexport async function supportedApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string[]> {\n const apiVersions = await fetchApiVersions(session, preferredBehaviour)\n return apiVersions\n .filter((item) => item.supported)\n .map((item) => item.handle)\n .sort()\n}\n\n/**\n * GraphQL query to retrieve all API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported and unsupported API versions.\n */\nexport async function fetchApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<ApiVersion[]> {\n try {\n const response = await adminRequestDoc({\n query: PublicApiVersions,\n session,\n variables: {},\n version: 'unstable',\n responseOptions: {handleErrors: false},\n preferredBehaviour,\n })\n return response.publicApiVersions\n } catch (error) {\n if (error instanceof ClientError && error.response.status === 403) {\n const storeName = session.storeFqdn.replace('.myshopify.com', '')\n throw new AbortError(\n outputContent`Looks like you don't have access to this dev store: (${outputToken.link(\n storeName,\n `https://${session.storeFqdn}`,\n )})`,\n outputContent`If you're not the owner, create a dev store staff account for yourself`,\n )\n }\n if (error instanceof ClientError && (error.response.status === 401 || error.response.status === 404)) {\n throw new AbortError(\n `Error connecting to your store ${session.storeFqdn}: ${error.message} ${error.response.status} ${error.response.data}`,\n )\n }\n\n // Check for network-level errors (connection issues, timeouts, DNS failures, TLS/certificate errors, etc.)\n // All network errors should be treated as user-facing errors, not CLI bugs\n // Note: Some of these may have been retried already by lower-level retry logic\n if (isNetworkError(error)) {\n throw new AbortError(\n `Network error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'Check your internet connection and try again.',\n )\n }\n\n // Unknown errors are likely bugs in the CLI\n throw new BugError(\n `Unknown error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n}\n\n/**\n * Returns the Admin API URL for the given store and version.\n *\n * @param store - Store FQDN.\n * @param version - API version.\n * @param session - User session.\n * @returns - Admin API URL.\n */\nexport function adminUrl(store: string, version: string | undefined, session?: AdminSession): string {\n const realVersion = version ?? 'unstable'\n\n const url =\n session && isThemeAccessSession(session)\n ? `https://${themeKitAccessDomain}/cli/admin/api/${realVersion}/graphql.json`\n : `https://${store}/admin/api/${realVersion}/graphql.json`\n return url\n}\n\ninterface ApiVersion {\n handle: string\n supported: boolean\n}\n\n/**\n * Executes a REST request against the Admin API.\n *\n * @param method - Request's HTTP method.\n * @param path - Path of the REST resource.\n * @param session - Shopify Admin session including token and Store FQDN.\n * @param requestBody - Request body of including REST resource specific parameters.\n * @param searchParams - Search params, appended to the URL.\n * @param apiVersion - Admin API version.\n * @returns - The {@link RestResponse}.\n */\nexport async function restRequest<T>(\n method: string,\n path: string,\n session: AdminSession,\n requestBody?: T,\n searchParams: Record<string, string> = {},\n apiVersion = 'unstable',\n): Promise<RestResponse> {\n const url = restRequestUrl(session, apiVersion, path, searchParams)\n const body = restRequestBody<T>(requestBody)\n\n const headers = restRequestHeaders(session)\n const response = await shopifyFetch(url, {\n headers,\n method,\n body,\n })\n\n const json = await response.json().catch(() => ({}))\n\n return {\n json,\n status: response.status,\n headers: response.headers.raw(),\n }\n}\n\n/**\n * Respose of a REST request.\n */\nexport interface RestResponse {\n /**\n * REST JSON respose.\n */\n // Using `any` to avoid introducing extra DTO layers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: any\n\n /**\n * HTTP response status.\n */\n status: number\n\n /**\n * HTTP response headers.\n */\n headers: Record<string, string[]>\n}\n"]}
|
|
@@ -13,6 +13,13 @@ export declare function throttle<T>(request: () => T): Promise<T>;
|
|
|
13
13
|
* @param response - The response object.
|
|
14
14
|
*/
|
|
15
15
|
export declare function updateApiCallLimitFromResponse(response: RestResponse): void;
|
|
16
|
+
/**
|
|
17
|
+
* Extracts the retry delay in milliseconds from the response's `retry-after` header.
|
|
18
|
+
*
|
|
19
|
+
* @param response - The response object.
|
|
20
|
+
* @returns The retry delay in milliseconds, or 0 if not present/invalid.
|
|
21
|
+
*/
|
|
22
|
+
export declare function extractRetryDelayMsFromResponse(response: RestResponse): number;
|
|
16
23
|
/**
|
|
17
24
|
* Retries an operation after a delay specified in the response headers.
|
|
18
25
|
*
|
|
@@ -21,3 +28,10 @@ export declare function updateApiCallLimitFromResponse(response: RestResponse):
|
|
|
21
28
|
* @returns - The response of the operation.
|
|
22
29
|
*/
|
|
23
30
|
export declare function delayAwareRetry(response: RestResponse, operation: () => Promise<RestResponse>): Promise<RestResponse>;
|
|
31
|
+
/**
|
|
32
|
+
* Extracts the API call limit (used/total) from the response's `x-shopify-shop-api-call-limit` header.
|
|
33
|
+
*
|
|
34
|
+
* @param response - The response object.
|
|
35
|
+
* @returns A tuple of [used, limit], or undefined if the header is missing/invalid.
|
|
36
|
+
*/
|
|
37
|
+
export declare function extractApiCallLimitFromResponse(response: RestResponse): [number, number] | undefined;
|
|
@@ -115,7 +115,13 @@ function throttlingState(context) {
|
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
const _throttlingState = {};
|
|
118
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Extracts the retry delay in milliseconds from the response's `retry-after` header.
|
|
120
|
+
*
|
|
121
|
+
* @param response - The response object.
|
|
122
|
+
* @returns The retry delay in milliseconds, or 0 if not present/invalid.
|
|
123
|
+
*/
|
|
124
|
+
export function extractRetryDelayMsFromResponse(response) {
|
|
119
125
|
const retryAfterStr = header(response, 'retry-after');
|
|
120
126
|
const retryAfter = tryParseInt(retryAfterStr);
|
|
121
127
|
if (!retryAfter) {
|
|
@@ -138,7 +144,13 @@ export async function delayAwareRetry(response, operation) {
|
|
|
138
144
|
}, retryDelay);
|
|
139
145
|
});
|
|
140
146
|
}
|
|
141
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Extracts the API call limit (used/total) from the response's `x-shopify-shop-api-call-limit` header.
|
|
149
|
+
*
|
|
150
|
+
* @param response - The response object.
|
|
151
|
+
* @returns A tuple of [used, limit], or undefined if the header is missing/invalid.
|
|
152
|
+
*/
|
|
153
|
+
export function extractApiCallLimitFromResponse(response) {
|
|
142
154
|
const apiCallLimit = header(response, 'x-shopify-shop-api-call-limit');
|
|
143
155
|
const [used, limit] = apiCallLimit
|
|
144
156
|
.split('/')
|
|
@@ -157,89 +169,4 @@ function header(response, name) {
|
|
|
157
169
|
}
|
|
158
170
|
return '';
|
|
159
171
|
}
|
|
160
|
-
if (import.meta.vitest) {
|
|
161
|
-
const { describe, test, expect, beforeEach } = import.meta.vitest;
|
|
162
|
-
let response;
|
|
163
|
-
beforeEach(() => {
|
|
164
|
-
response = {
|
|
165
|
-
json: {},
|
|
166
|
-
status: 200,
|
|
167
|
-
headers: {},
|
|
168
|
-
};
|
|
169
|
-
});
|
|
170
|
-
describe('retryAfter', () => {
|
|
171
|
-
test('when the "retry-after" header value is valid', async () => {
|
|
172
|
-
// Given
|
|
173
|
-
response.headers = {
|
|
174
|
-
'retry-after': ['2.0'],
|
|
175
|
-
};
|
|
176
|
-
// When
|
|
177
|
-
const retryAfterDelay = extractRetryDelayMsFromResponse(response);
|
|
178
|
-
// Then
|
|
179
|
-
expect(retryAfterDelay).toBe(2);
|
|
180
|
-
});
|
|
181
|
-
test('when the "retry-after" header value is not present', async () => {
|
|
182
|
-
// Given
|
|
183
|
-
response.headers = {
|
|
184
|
-
'retry-after': [],
|
|
185
|
-
};
|
|
186
|
-
// When
|
|
187
|
-
const retryAfterDelay = extractRetryDelayMsFromResponse(response);
|
|
188
|
-
// Then
|
|
189
|
-
expect(retryAfterDelay).toBe(0);
|
|
190
|
-
});
|
|
191
|
-
test('when the "retry-after" header value is valid', async () => {
|
|
192
|
-
// Given
|
|
193
|
-
response.headers = {
|
|
194
|
-
'retry-after': ['invalid'],
|
|
195
|
-
};
|
|
196
|
-
// When
|
|
197
|
-
const retryAfterDelay = extractRetryDelayMsFromResponse(response);
|
|
198
|
-
// Then
|
|
199
|
-
expect(retryAfterDelay).toBe(0);
|
|
200
|
-
});
|
|
201
|
-
test('when the "retry-after" header is not present', async () => {
|
|
202
|
-
// Given
|
|
203
|
-
response.headers = {};
|
|
204
|
-
// When
|
|
205
|
-
const retryAfterDelay = extractRetryDelayMsFromResponse(response);
|
|
206
|
-
// Then
|
|
207
|
-
expect(retryAfterDelay).toBe(0);
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
describe('apiCallLimit', () => {
|
|
211
|
-
test('when the "x-shopify-shop-api-call-limit" header is valid', async () => {
|
|
212
|
-
// Given
|
|
213
|
-
response.headers = {
|
|
214
|
-
'x-shopify-shop-api-call-limit': ['10/40'],
|
|
215
|
-
};
|
|
216
|
-
// When
|
|
217
|
-
const callLimit = extractApiCallLimitFromResponse(response);
|
|
218
|
-
const [used, limit] = callLimit;
|
|
219
|
-
// Then
|
|
220
|
-
expect(used).toBe(10);
|
|
221
|
-
expect(limit).toBe(40);
|
|
222
|
-
});
|
|
223
|
-
test('when the "x-shopify-shop-api-call-limit" header is invalid', async () => {
|
|
224
|
-
// Given
|
|
225
|
-
response.headers = {
|
|
226
|
-
'x-shopify-shop-api-call-limit': ['foo/bar'],
|
|
227
|
-
};
|
|
228
|
-
// When
|
|
229
|
-
const callLimit = extractApiCallLimitFromResponse(response);
|
|
230
|
-
// Then
|
|
231
|
-
expect(callLimit).toBeUndefined();
|
|
232
|
-
});
|
|
233
|
-
test('when the "x-shopify-shop-api-call-limit" header is not formatted as expected', async () => {
|
|
234
|
-
// Given
|
|
235
|
-
response.headers = {
|
|
236
|
-
'x-shopify-shop-api-call-limit': ['/10'],
|
|
237
|
-
};
|
|
238
|
-
// When
|
|
239
|
-
const callLimit = extractApiCallLimitFromResponse(response);
|
|
240
|
-
// Then
|
|
241
|
-
expect(callLimit).toBeUndefined();
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
172
|
//# sourceMappingURL=rest-api-throttler.js.map
|