@shopify/cli-kit 4.8.5 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/private/node/analytics.js +5 -3
- package/dist/private/node/analytics.js.map +1 -1
- package/dist/private/node/api/status-checks.d.ts +7 -0
- package/dist/private/node/api/status-checks.js +11 -0
- package/dist/private/node/api/status-checks.js.map +1 -0
- package/dist/private/node/api.d.ts +15 -0
- package/dist/private/node/api.js +28 -0
- package/dist/private/node/api.js.map +1 -1
- package/dist/private/node/command-event-context.d.ts +29 -0
- package/dist/private/node/command-event-context.js +43 -0
- package/dist/private/node/command-event-context.js.map +1 -0
- package/dist/private/node/command-event-output.d.ts +7 -0
- package/dist/private/node/command-event-output.js +16 -0
- package/dist/private/node/command-event-output.js.map +1 -0
- package/dist/private/node/command-json-schema.d.ts +10 -0
- package/dist/private/node/command-json-schema.js +38 -0
- package/dist/private/node/command-json-schema.js.map +1 -0
- package/dist/private/node/context/agent.d.ts +1 -0
- package/dist/private/node/context/agent.js +44 -0
- package/dist/private/node/context/agent.js.map +1 -0
- package/dist/private/node/json-error.d.ts +23 -0
- package/dist/private/node/json-error.js +123 -0
- package/dist/private/node/json-error.js.map +1 -0
- package/dist/private/node/output.js +3 -1
- package/dist/private/node/output.js.map +1 -1
- package/dist/private/node/output.test.d.ts +1 -0
- package/dist/private/node/output.test.js +74 -0
- package/dist/private/node/output.test.js.map +1 -0
- package/dist/private/node/session/device-authorization.js +49 -15
- package/dist/private/node/session/device-authorization.js.map +1 -1
- package/dist/private/node/session/validate.js +9 -22
- package/dist/private/node/session/validate.js.map +1 -1
- package/dist/private/node/ui/alert.d.ts +1 -1
- package/dist/private/node/ui/alert.js +29 -3
- package/dist/private/node/ui/alert.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.d.ts +8 -1
- package/dist/private/node/ui/components/ConcurrentOutput.js +54 -0
- package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.js +3 -3
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.js.map +1 -1
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js +16 -1
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.js +3 -2
- package/dist/private/node/ui/components/Prompts/PromptLayout.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.test.js +20 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.test.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.d.ts +2 -9
- package/dist/private/node/ui/components/Tasks.js +5 -44
- package/dist/private/node/ui/components/Tasks.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.js +3 -3
- package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.test.js +15 -1
- package/dist/private/node/ui/components/TextPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/token-item.d.ts +2 -0
- package/dist/private/node/ui/components/token-item.js +26 -0
- package/dist/private/node/ui/components/token-item.js.map +1 -1
- package/dist/private/node/ui/hooks/use-async-and-unmount.d.ts +3 -3
- package/dist/private/node/ui/hooks/use-async-and-unmount.js +2 -2
- package/dist/private/node/ui/hooks/use-async-and-unmount.js.map +1 -1
- package/dist/private/node/ui/tasks.d.ts +10 -0
- package/dist/private/node/ui/tasks.js +68 -0
- package/dist/private/node/ui/tasks.js.map +1 -0
- package/dist/public/common/command-events.d.ts +125 -0
- package/dist/public/common/command-events.js +54 -0
- package/dist/public/common/command-events.js.map +1 -0
- package/dist/public/common/json-output-schema.d.ts +10 -0
- package/dist/public/common/json-output-schema.js +17 -0
- package/dist/public/common/json-output-schema.js.map +1 -0
- 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/api/admin.js +18 -1
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/app-management.d.ts +1 -0
- package/dist/public/node/api/app-management.js +4 -0
- package/dist/public/node/api/app-management.js.map +1 -1
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.d.ts +3 -3
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js +5 -3
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js.map +1 -1
- package/dist/public/node/base-command.d.ts +6 -0
- package/dist/public/node/base-command.js +34 -5
- package/dist/public/node/base-command.js.map +1 -1
- package/dist/public/node/cli-launcher.js +20 -2
- package/dist/public/node/cli-launcher.js.map +1 -1
- package/dist/public/node/cli.d.ts +1 -0
- package/dist/public/node/cli.js +2 -0
- package/dist/public/node/cli.js.map +1 -1
- package/dist/public/node/command-events.d.ts +65 -0
- package/dist/public/node/command-events.js +71 -0
- package/dist/public/node/command-events.js.map +1 -0
- package/dist/public/node/context/local.d.ts +6 -0
- package/dist/public/node/context/local.js +10 -1
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/custom-oclif-loader.d.ts +6 -0
- package/dist/public/node/custom-oclif-loader.js +45 -19
- package/dist/public/node/custom-oclif-loader.js.map +1 -1
- package/dist/public/node/environment.d.ts +2 -1
- package/dist/public/node/environment.js +3 -2
- package/dist/public/node/environment.js.map +1 -1
- package/dist/public/node/error/index.d.ts +91 -0
- package/dist/public/node/error/index.js +266 -0
- package/dist/public/node/error/index.js.map +1 -0
- package/dist/public/node/error/schema.d.ts +472 -0
- package/dist/public/node/error/schema.js +54 -0
- package/dist/public/node/error/schema.js.map +1 -0
- package/dist/public/node/error/types.d.ts +9 -0
- package/dist/public/node/error/types.js +2 -0
- package/dist/public/node/error/types.js.map +1 -0
- package/dist/public/node/error.d.ts +1 -87
- package/dist/public/node/error.js +1 -252
- package/dist/public/node/error.js.map +1 -1
- package/dist/public/node/fs.d.ts +17 -3
- package/dist/public/node/fs.js +7 -5
- package/dist/public/node/fs.js.map +1 -1
- package/dist/public/node/json-output-schema.d.ts +26 -0
- package/dist/public/node/json-output-schema.js +30 -0
- package/dist/public/node/json-output-schema.js.map +1 -0
- package/dist/public/node/local-storage.d.ts +1 -0
- package/dist/public/node/local-storage.js +54 -21
- package/dist/public/node/local-storage.js.map +1 -1
- package/dist/public/node/monorail.d.ts +3 -1
- package/dist/public/node/monorail.js +1 -1
- package/dist/public/node/monorail.js.map +1 -1
- package/dist/public/node/multiple-installation-warning.d.ts +1 -1
- package/dist/public/node/multiple-installation-warning.js +2 -3
- package/dist/public/node/multiple-installation-warning.js.map +1 -1
- package/dist/public/node/no-input.d.ts +11 -0
- package/dist/public/node/no-input.js +19 -0
- package/dist/public/node/no-input.js.map +1 -0
- package/dist/public/node/output.d.ts +6 -0
- package/dist/public/node/output.js +40 -0
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/path.js +3 -1
- package/dist/public/node/path.js.map +1 -1
- package/dist/public/node/system.d.ts +2 -2
- package/dist/public/node/system.js +8 -4
- package/dist/public/node/system.js.map +1 -1
- package/dist/public/node/testing/output.d.ts +30 -0
- package/dist/public/node/testing/output.js +83 -0
- package/dist/public/node/testing/output.js.map +1 -1
- package/dist/public/node/ui.d.ts +5 -1
- package/dist/public/node/ui.js +89 -5
- package/dist/public/node/ui.js.map +1 -1
- package/dist/public/node/upgrade.js +17 -2
- package/dist/public/node/upgrade.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextPrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TextPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAC,WAAW,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AACpD,OAAO,SAAS,MAAM,wBAAwB,CAAA;AAC9C,OAAO,EAAC,sBAAsB,EAAC,MAAM,iBAAiB,CAAA;AAEtD,OAAO,cAAc,MAAM,8BAA8B,CAAA;AACzD,OAAO,SAAS,EAAE,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAA;AAC7D,OAAO,KAAK,EAAE,EAAoB,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AAEhF,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAC,MAAM,KAAK,CAAA;AACvC,OAAO,OAAO,MAAM,SAAS,CAAA;AAgB7B,MAAM,UAAU,GAAuC,CAAC,EACtD,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,YAAY,GAAG,EAAE,EACjB,QAAQ,GAAG,KAAK,EAChB,UAAU,GAAG,KAAK,EAClB,mBAAmB,GAAG,SAAS,EAC/B,WAAW,EACX,OAAO,EACP,aAAa,GAAG,EAAE,GACnB,EAAE,EAAE;IACH,IAAI,QAAQ,IAAI,YAAY,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IACzD,CAAC;IAED,MAAM,cAAc,GAAG,WAAW,CAChC,CAAC,KAAa,EAAsB,EAAE;QACpC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;QACxB,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,+BAA+B,CAAA;QAE7E,OAAO,SAAS,CAAA;IAClB,CAAC,EACD,CAAC,UAAU,EAAE,QAAQ,CAAC,CACvB,CAAA;IAED,MAAM,EAAC,QAAQ,EAAC,GAAG,SAAS,EAAE,CAAA;IAC9B,MAAM,EAAC,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,EAAC,GAAG,SAAS,CAAS;QACzE,aAAa;KACd,CAAC,CAAA;IACF,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAA;IACjE,MAAM,iBAAiB,GAAG,eAAe,KAAK,EAAE,CAAA;IAChD,MAAM,eAAe,GAAG,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,eAAe,CAAA;IACjF,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAqB,SAAS,CAAC,CAAA;IACjE,MAAM,KAAK,GAAG,WAAW,KAAK,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;IAChE,MAAM,
|
|
1
|
+
{"version":3,"file":"TextPrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TextPrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["import {TokenizedText} from './TokenizedText.js'\nimport {TextInput} from './TextInput.js'\nimport {handleCtrlC, useComplete} from '../../ui.js'\nimport useLayout from '../hooks/use-layout.js'\nimport {messageWithPunctuation} from '../utilities.js'\nimport {AbortSignal} from '../../../../public/node/abort.js'\nimport {platformAndArch} from '../../../../public/node/os.js'\nimport useAbortSignal from '../hooks/use-abort-signal.js'\nimport usePrompt, {PromptState} from '../hooks/use-prompt.js'\nimport React, {FunctionComponent, useCallback, useEffect, useState} from 'react'\n\nimport {Box, useInput, Text} from 'ink'\nimport figures from 'figures'\nimport type {InlineToken, TokenItem} from './token-item.js'\n\nexport interface TextPromptProps {\n message: TokenItem\n onSubmit: (value: string) => void\n defaultValue?: string\n password?: boolean\n validate?: (value: string) => string | undefined\n allowEmpty?: boolean\n emptyDisplayedValue?: string\n abortSignal?: AbortSignal\n preview?: (value: string) => TokenItem<InlineToken>\n initialAnswer?: string\n}\n\nconst TextPrompt: FunctionComponent<TextPromptProps> = ({\n message,\n onSubmit,\n validate,\n defaultValue = '',\n password = false,\n allowEmpty = false,\n emptyDisplayedValue = '(empty)',\n abortSignal,\n preview,\n initialAnswer = '',\n}) => {\n if (password && defaultValue) {\n throw new Error(\"Can't use defaultValue with password\")\n }\n\n const validateAnswer = useCallback(\n (value: string): string | undefined => {\n if (validate) {\n return validate(value)\n }\n\n if (value.length === 0 && !allowEmpty) return 'Type an answer to the prompt.'\n\n return undefined\n },\n [allowEmpty, validate],\n )\n\n const {oneThird} = useLayout()\n const {promptState, setPromptState, answer, setAnswer} = usePrompt<string>({\n initialAnswer,\n })\n const answerOrDefault = answer.length > 0 ? answer : defaultValue\n const displayEmptyValue = answerOrDefault === ''\n const displayedAnswer = displayEmptyValue ? emptyDisplayedValue : answerOrDefault\n const complete = useComplete()\n const [error, setError] = useState<string | undefined>(undefined)\n const color = promptState === PromptState.Error ? 'red' : 'cyan'\n const {isAborted} = useAbortSignal(abortSignal)\n\n useInput((input, key) => {\n handleCtrlC(input, key)\n\n if (key.return) {\n const error = validateAnswer(answerOrDefault)\n\n if (error) {\n setPromptState(PromptState.Error)\n setError(error)\n } else {\n setPromptState(PromptState.Submitted)\n }\n }\n })\n\n useEffect(() => {\n if (promptState === PromptState.Submitted) {\n onSubmit(answerOrDefault)\n complete()\n }\n }, [answerOrDefault, onSubmit, promptState, complete])\n\n return isAborted ? null : (\n <Box flexDirection=\"column\" marginBottom={1} width={oneThird}>\n <Box>\n <Box marginRight={2}>\n <Text>?</Text>\n </Box>\n <TokenizedText item={messageWithPunctuation(message)} />\n </Box>\n {promptState === PromptState.Submitted ? (\n <Box>\n <Box width={3}>\n <Text color=\"cyan\">{figures.tick}</Text>\n </Box>\n\n <Box flexGrow={1}>\n <Text color=\"cyan\" dimColor={displayEmptyValue}>\n {password ? '*'.repeat(answer.length) : displayedAnswer}\n </Text>\n </Box>\n </Box>\n ) : (\n <Box flexDirection=\"column\">\n <Box>\n <Box marginRight={2}>\n <Text color={color}>{`>`}</Text>\n </Box>\n <Box flexGrow={1}>\n <TextInput\n value={answer}\n onChange={(answer) => {\n setAnswer(answer)\n setPromptState(PromptState.Idle)\n }}\n defaultValue={defaultValue}\n color={color}\n password={password}\n />\n </Box>\n </Box>\n {platformAndArch().platform === 'windows' ? (\n <Box\n marginLeft={3}\n borderStyle=\"single\"\n borderColor={color}\n borderBottom={false}\n borderLeft={false}\n borderRight={false}\n />\n ) : (\n <Box marginLeft={3}>\n <Text color={color}>{'▔'.repeat(oneThird - 3)}</Text>\n </Box>\n )}\n {promptState === PromptState.Error ? (\n <Box marginLeft={3}>\n <Text color={color}>{error}</Text>\n </Box>\n ) : null}\n {promptState !== PromptState.Error && preview ? (\n <Box marginLeft={3}>\n <TokenizedText item={preview(answerOrDefault)} />\n </Box>\n ) : null}\n </Box>\n )}\n </Box>\n )\n}\n\nexport {TextPrompt}\n"]}
|
|
@@ -3,10 +3,24 @@ import { getLastFrameAfterUnmount, sendInputAndWaitForChange, waitForInputsToBeR
|
|
|
3
3
|
import { unstyled } from '../../../../public/node/output.js';
|
|
4
4
|
import { AbortController } from '../../../../public/node/abort.js';
|
|
5
5
|
import colors from '../../../../public/node/colors.js';
|
|
6
|
+
import { platformAndArch } from '../../../../public/node/os.js';
|
|
6
7
|
import React from 'react';
|
|
7
|
-
import { describe, expect, test, vi } from 'vitest';
|
|
8
|
+
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
9
|
+
vi.mock('../../../../public/node/os.js');
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
vi.mocked(platformAndArch).mockReturnValue({ platform: 'darwin', arch: 'arm64' });
|
|
12
|
+
});
|
|
8
13
|
const ENTER = '\r';
|
|
9
14
|
describe('TextPrompt', () => {
|
|
15
|
+
test.each(['windows', 'darwin', 'linux'])('renders the underline on %s', async (platform) => {
|
|
16
|
+
vi.mocked(platformAndArch).mockReturnValue({ platform, arch: 'amd64' });
|
|
17
|
+
const renderInstance = render(React.createElement(TextPrompt, { onSubmit: () => { }, message: "Test question" }));
|
|
18
|
+
const underline = (platform === 'windows' ? '─' : '▔').repeat(77);
|
|
19
|
+
expect(renderInstance.lastFrame()).toContain(colors.cyan(underline));
|
|
20
|
+
await waitForInputsToBeReady();
|
|
21
|
+
await sendInputAndWaitForChange(renderInstance, ENTER);
|
|
22
|
+
expect(renderInstance.lastFrame()).toContain(colors.red(underline));
|
|
23
|
+
});
|
|
10
24
|
test('default state', () => {
|
|
11
25
|
const { lastFrame } = render(React.createElement(TextPrompt, { onSubmit: () => { }, message: "Test question", defaultValue: "Placeholder" }));
|
|
12
26
|
expect(unstyled(lastFrame())).toMatchInlineSnapshot(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextPrompt.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TextPrompt.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {TextPrompt} from './TextPrompt.js'\nimport {getLastFrameAfterUnmount, sendInputAndWaitForChange, waitForInputsToBeReady, render} from '../../testing/ui.js'\nimport {unstyled} from '../../../../public/node/output.js'\nimport {AbortController} from '../../../../public/node/abort.js'\nimport colors from '../../../../public/node/colors.js'\nimport React from 'react'\n\nimport {describe, expect, test, vi} from 'vitest'\n\nconst ENTER = '\\r'\n\ndescribe('TextPrompt', () => {\n test('default state', () => {\n const {lastFrame} = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" defaultValue=\"Placeholder\" />)\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"? Test question:\n > Placeholder\n ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n \"\n `)\n })\n\n test('default validation error', async () => {\n const renderInstance = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ENTER)\n // testing with styles because the color changes to red\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[31m>\u001b[39m \u001b[31m\u001b[41m█\u001b[49m\u001b[39m\n \u001b[31m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \u001b[31mType an answer to the prompt.\u001b[39m\n \"\n `)\n await sendInputAndWaitForChange(renderInstance, 'A')\n // color changes back to valid color\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[36m>\u001b[39m \u001b[36mA\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \"\n `)\n })\n\n test('custom validation error', async () => {\n const renderInstance = render(\n <TextPrompt\n onSubmit={() => {}}\n message=\"Test question\"\n validate={(value) => (value.includes('shopify') ? \"App name can't include the word shopify\" : undefined)}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'this-test-includes-shopify')\n await sendInputAndWaitForChange(renderInstance, ENTER)\n // testing with styles because the color changes to red\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[31m>\u001b[39m \u001b[31mthis-test-includes-shopify\u001b[41m█\u001b[49m\u001b[39m\n \u001b[31m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \u001b[31mApp name can't include the word shopify\u001b[39m\n \"\n `)\n })\n\n test('submitting the value', async () => {\n const onSubmit = vi.fn()\n const renderInstance = render(<TextPrompt onSubmit={onSubmit} message=\"Test question\" />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'A')\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(onSubmit).toHaveBeenCalledWith('A')\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ A\n \"\n `)\n })\n\n test('submitting the default value', async () => {\n const onSubmit = vi.fn()\n const renderInstance = render(<TextPrompt onSubmit={onSubmit} message=\"Test question\" defaultValue=\"A\" />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(onSubmit).toHaveBeenCalledWith('A')\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ A\n \"\n `)\n })\n\n test('display the empty value when no input is entered and there is no default value', async () => {\n const onSubmit = vi.fn()\n const renderInstance = render(\n <TextPrompt onSubmit={onSubmit} message=\"Test question\" allowEmpty emptyDisplayedValue=\"empty\" />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(onSubmit).toHaveBeenCalledWith('')\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ empty\n \"\n `)\n })\n\n test(\"display the default value when allow empty is enabled but the user don't modify it\", async () => {\n const onSubmit = vi.fn()\n const renderInstance = render(\n <TextPrompt\n onSubmit={onSubmit}\n message=\"Test question\"\n allowEmpty\n emptyDisplayedValue=\"empty\"\n defaultValue=\"A\"\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(onSubmit).toHaveBeenCalledWith('A')\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ A\n \"\n `)\n })\n\n test('text wrapping', async () => {\n // component width is 80 characters wide in tests but because of the question mark and\n // spaces before the question, we only have 77 characters to work with\n const renderInstance = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'A'.repeat(77))\n await sendInputAndWaitForChange(renderInstance, 'B'.repeat(6))\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[36m>\u001b[39m \u001b[36mAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\u001b[39m\n \u001b[36mBBBBBB\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \"\n `)\n })\n\n test(\"masking the input if it's a password\", async () => {\n const renderInstance = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" password />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'ABC')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[36m>\u001b[39m \u001b[36m***\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ ***\n \"\n `)\n })\n\n test(\"doesn't append a colon to the message if it ends with a question mark\", async () => {\n const {lastFrame} = render(<TextPrompt onSubmit={() => {}} message=\"Test question?\" />)\n\n expect(lastFrame()!).toMatchInlineSnapshot(`\n \"? Test question?\n \u001b[36m>\u001b[39m \u001b[36m\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \"\n `)\n })\n\n test(\"doesn't allow to pass defaultValue and password at the same time\", async () => {\n const renderInstance = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" password defaultValue=\"A\" />)\n\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toContain(\"ERROR Can't use defaultValue with password\")\n })\n\n test('abortController can be used to exit the prompt from outside', async () => {\n const abortController = new AbortController()\n\n const renderInstance = render(\n <TextPrompt\n onSubmit={() => {}}\n message=\"Test question\"\n defaultValue=\"Placeholder\"\n abortSignal={abortController.signal}\n />,\n )\n const promise = renderInstance.waitUntilExit()\n\n abortController.abort()\n\n // wait for the onAbort promise to resolve\n await new Promise((resolve) => setTimeout(resolve, 0))\n\n await expect(promise).resolves.toEqual(undefined)\n })\n\n test('shows a preview footer when provided', async () => {\n const renderInstance = render(\n <TextPrompt\n onSubmit={() => {}}\n message=\"How tall are you in cm?\"\n preview={(value) => `You are ${colors.cyan(String(Number(value) / 100))}m tall.`}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, '180')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? How tall are you in cm?\n \u001b[36m>\u001b[39m \u001b[36m180\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n You are \u001b[36m1.8\u001b[39mm tall.\n \"\n `)\n })\n\n test('the preview footer wraps when the value is very long', async () => {\n const renderInstance = render(\n <TextPrompt\n onSubmit={() => {}}\n message=\"How tall are you?\"\n preview={(value) =>\n `You are ${colors.cyan(\n `incredibly humongously savagely unnaturally monstrously pathetically arrogantly ${value}`,\n )} tall.`\n }\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'uber')\n\n expect(renderInstance.lastFrame()!).toMatchInlineSnapshot(`\n \"? How tall are you?\n \u001b[36m>\u001b[39m \u001b[36muber\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n You are \u001b[36mincredibly humongously savagely unnaturally monstrously pathetically \u001b[39m\n \u001b[36marrogantly uber\u001b[39m tall.\n \"\n `)\n })\n})\n"]}
|
|
1
|
+
{"version":3,"file":"TextPrompt.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TextPrompt.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {TextPrompt} from './TextPrompt.js'\nimport {getLastFrameAfterUnmount, sendInputAndWaitForChange, waitForInputsToBeReady, render} from '../../testing/ui.js'\nimport {unstyled} from '../../../../public/node/output.js'\nimport {AbortController} from '../../../../public/node/abort.js'\nimport colors from '../../../../public/node/colors.js'\nimport {platformAndArch} from '../../../../public/node/os.js'\nimport React from 'react'\n\nimport {beforeEach, describe, expect, test, vi} from 'vitest'\n\nvi.mock('../../../../public/node/os.js')\n\nbeforeEach(() => {\n vi.mocked(platformAndArch).mockReturnValue({platform: 'darwin', arch: 'arm64'})\n})\n\nconst ENTER = '\\r'\n\ndescribe('TextPrompt', () => {\n test.each(['windows', 'darwin', 'linux'] as const)('renders the underline on %s', async (platform) => {\n vi.mocked(platformAndArch).mockReturnValue({platform, arch: 'amd64'})\n const renderInstance = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" />)\n const underline = (platform === 'windows' ? '─' : '▔').repeat(77)\n\n expect(renderInstance.lastFrame()).toContain(colors.cyan(underline))\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ENTER)\n\n expect(renderInstance.lastFrame()).toContain(colors.red(underline))\n })\n\n test('default state', () => {\n const {lastFrame} = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" defaultValue=\"Placeholder\" />)\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"? Test question:\n > Placeholder\n ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n \"\n `)\n })\n\n test('default validation error', async () => {\n const renderInstance = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ENTER)\n // testing with styles because the color changes to red\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[31m>\u001b[39m \u001b[31m\u001b[41m█\u001b[49m\u001b[39m\n \u001b[31m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \u001b[31mType an answer to the prompt.\u001b[39m\n \"\n `)\n await sendInputAndWaitForChange(renderInstance, 'A')\n // color changes back to valid color\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[36m>\u001b[39m \u001b[36mA\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \"\n `)\n })\n\n test('custom validation error', async () => {\n const renderInstance = render(\n <TextPrompt\n onSubmit={() => {}}\n message=\"Test question\"\n validate={(value) => (value.includes('shopify') ? \"App name can't include the word shopify\" : undefined)}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'this-test-includes-shopify')\n await sendInputAndWaitForChange(renderInstance, ENTER)\n // testing with styles because the color changes to red\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[31m>\u001b[39m \u001b[31mthis-test-includes-shopify\u001b[41m█\u001b[49m\u001b[39m\n \u001b[31m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \u001b[31mApp name can't include the word shopify\u001b[39m\n \"\n `)\n })\n\n test('submitting the value', async () => {\n const onSubmit = vi.fn()\n const renderInstance = render(<TextPrompt onSubmit={onSubmit} message=\"Test question\" />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'A')\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(onSubmit).toHaveBeenCalledWith('A')\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ A\n \"\n `)\n })\n\n test('submitting the default value', async () => {\n const onSubmit = vi.fn()\n const renderInstance = render(<TextPrompt onSubmit={onSubmit} message=\"Test question\" defaultValue=\"A\" />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(onSubmit).toHaveBeenCalledWith('A')\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ A\n \"\n `)\n })\n\n test('display the empty value when no input is entered and there is no default value', async () => {\n const onSubmit = vi.fn()\n const renderInstance = render(\n <TextPrompt onSubmit={onSubmit} message=\"Test question\" allowEmpty emptyDisplayedValue=\"empty\" />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(onSubmit).toHaveBeenCalledWith('')\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ empty\n \"\n `)\n })\n\n test(\"display the default value when allow empty is enabled but the user don't modify it\", async () => {\n const onSubmit = vi.fn()\n const renderInstance = render(\n <TextPrompt\n onSubmit={onSubmit}\n message=\"Test question\"\n allowEmpty\n emptyDisplayedValue=\"empty\"\n defaultValue=\"A\"\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(onSubmit).toHaveBeenCalledWith('A')\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ A\n \"\n `)\n })\n\n test('text wrapping', async () => {\n // component width is 80 characters wide in tests but because of the question mark and\n // spaces before the question, we only have 77 characters to work with\n const renderInstance = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'A'.repeat(77))\n await sendInputAndWaitForChange(renderInstance, 'B'.repeat(6))\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[36m>\u001b[39m \u001b[36mAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\u001b[39m\n \u001b[36mBBBBBB\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \"\n `)\n })\n\n test(\"masking the input if it's a password\", async () => {\n const renderInstance = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" password />)\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'ABC')\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? Test question:\n \u001b[36m>\u001b[39m \u001b[36m***\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \"\n `)\n\n await sendInputAndWaitForChange(renderInstance, ENTER)\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toMatchInlineSnapshot(`\n \"? Test question:\n ✔ ***\n \"\n `)\n })\n\n test(\"doesn't append a colon to the message if it ends with a question mark\", async () => {\n const {lastFrame} = render(<TextPrompt onSubmit={() => {}} message=\"Test question?\" />)\n\n expect(lastFrame()!).toMatchInlineSnapshot(`\n \"? Test question?\n \u001b[36m>\u001b[39m \u001b[36m\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n \"\n `)\n })\n\n test(\"doesn't allow to pass defaultValue and password at the same time\", async () => {\n const renderInstance = render(<TextPrompt onSubmit={() => {}} message=\"Test question\" password defaultValue=\"A\" />)\n\n expect(unstyled(getLastFrameAfterUnmount(renderInstance)!)).toContain(\"ERROR Can't use defaultValue with password\")\n })\n\n test('abortController can be used to exit the prompt from outside', async () => {\n const abortController = new AbortController()\n\n const renderInstance = render(\n <TextPrompt\n onSubmit={() => {}}\n message=\"Test question\"\n defaultValue=\"Placeholder\"\n abortSignal={abortController.signal}\n />,\n )\n const promise = renderInstance.waitUntilExit()\n\n abortController.abort()\n\n // wait for the onAbort promise to resolve\n await new Promise((resolve) => setTimeout(resolve, 0))\n\n await expect(promise).resolves.toEqual(undefined)\n })\n\n test('shows a preview footer when provided', async () => {\n const renderInstance = render(\n <TextPrompt\n onSubmit={() => {}}\n message=\"How tall are you in cm?\"\n preview={(value) => `You are ${colors.cyan(String(Number(value) / 100))}m tall.`}\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, '180')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"? How tall are you in cm?\n \u001b[36m>\u001b[39m \u001b[36m180\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n You are \u001b[36m1.8\u001b[39mm tall.\n \"\n `)\n })\n\n test('the preview footer wraps when the value is very long', async () => {\n const renderInstance = render(\n <TextPrompt\n onSubmit={() => {}}\n message=\"How tall are you?\"\n preview={(value) =>\n `You are ${colors.cyan(\n `incredibly humongously savagely unnaturally monstrously pathetically arrogantly ${value}`,\n )} tall.`\n }\n />,\n )\n\n await waitForInputsToBeReady()\n await sendInputAndWaitForChange(renderInstance, 'uber')\n\n expect(renderInstance.lastFrame()!).toMatchInlineSnapshot(`\n \"? How tall are you?\n \u001b[36m>\u001b[39m \u001b[36muber\u001b[46m█\u001b[49m\u001b[39m\n \u001b[36m▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\u001b[39m\n You are \u001b[36mincredibly humongously savagely unnaturally monstrously pathetically \u001b[39m\n \u001b[36marrogantly uber\u001b[39m tall.\n \"\n `)\n })\n})\n"]}
|
|
@@ -36,3 +36,5 @@ export type InlineToken = Exclude<Token, ListToken>;
|
|
|
36
36
|
export type TokenItem<T extends Token = Token> = T | T[];
|
|
37
37
|
export declare function tokenItemToString(token: TokenItem): string;
|
|
38
38
|
export declare function appendToTokenItem(token: TokenItem, suffix: string): TokenItem;
|
|
39
|
+
/** Converts tokens to JSON message text, retaining link URLs and list titles. */
|
|
40
|
+
export declare function tokenItemToJsonString(token: TokenItem): string;
|
|
@@ -60,4 +60,30 @@ export function tokenItemToString(token) {
|
|
|
60
60
|
export function appendToTokenItem(token, suffix) {
|
|
61
61
|
return Array.isArray(token) ? [...token, { char: suffix }] : [token, { char: suffix }];
|
|
62
62
|
}
|
|
63
|
+
/** Converts tokens to JSON message text, retaining link URLs and list titles. */
|
|
64
|
+
export function tokenItemToJsonString(token) {
|
|
65
|
+
if (!Array.isArray(token))
|
|
66
|
+
return tokenToJsonString(token);
|
|
67
|
+
return token
|
|
68
|
+
.map((item, index) => {
|
|
69
|
+
const value = tokenToJsonString(item);
|
|
70
|
+
const needsLeadingSpace = index !== 0 && !(typeof item !== 'string' && 'char' in item);
|
|
71
|
+
return needsLeadingSpace ? ` ${value}` : value;
|
|
72
|
+
})
|
|
73
|
+
.join('');
|
|
74
|
+
}
|
|
75
|
+
function tokenToJsonString(token) {
|
|
76
|
+
if (typeof token === 'string')
|
|
77
|
+
return token;
|
|
78
|
+
if ('link' in token) {
|
|
79
|
+
const { label, url } = token.link;
|
|
80
|
+
return label && label !== url ? `${label} (${url})` : url;
|
|
81
|
+
}
|
|
82
|
+
if ('list' in token) {
|
|
83
|
+
const title = token.list.title ? tokenItemToJsonString(token.list.title).trim() : undefined;
|
|
84
|
+
const items = token.list.items.map(tokenItemToJsonString).join('; ');
|
|
85
|
+
return title ? `${title}${items ? `: ${items}` : ''}` : items;
|
|
86
|
+
}
|
|
87
|
+
return tokenItemToString(token);
|
|
88
|
+
}
|
|
63
89
|
//# sourceMappingURL=token-item.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-item.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/token-item.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,oDAAoD;AAwDpD,MAAM,UAAU,iBAAiB,CAAC,KAAgB;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAA;IACd,CAAC;SAAM,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,OAAO,CAAA;IACtB,CAAC;SAAM,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3B,kHAAkH;QAClH,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAA;IAC3C,CAAC;SAAM,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,IAAI,CAAA;IACnB,CAAC;SAAM,IAAI,WAAW,IAAI,KAAK,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC,SAAS,CAAA;IACxB,CAAC;SAAM,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,OAAO,CAAA;IACtB,CAAC;SAAM,IAAI,UAAU,IAAI,KAAK,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC,QAAQ,CAAA;IACvB,CAAC;SAAM,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC1D,CAAC;SAAM,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,IAAI,CAAA;IACnB,CAAC;SAAM,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,IAAI,CAAA;IACnB,CAAC;SAAM,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,IAAI,CAAA;IACnB,CAAC;SAAM,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,KAAK,CAAA;IACpB,CAAC;SAAM,CAAC;QACN,OAAO,KAAK;aACT,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YACnB,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,MAAM,IAAI,IAAI,CAAC,EAAE,CAAC;gBACjE,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAA;YACtC,CAAC;iBAAM,CAAC;gBACN,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAA;YAChC,CAAC;QACH,CAAC,CAAC;aACD,IAAI,CAAC,EAAE,CAAC,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgB,EAAE,MAAc;IAChE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,EAAE,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAA;AACpF,CAAC","sourcesContent":["// Token shapes and the pure helpers that operate on them.\n//\n// These live apart from `TokenizedText.tsx` on purpose. That file is a React\n// component module: importing it pulls in `react` and `ink`, and through Ink,\n// `react-reconciler`, `yoga-layout` and its WebAssembly. Non-rendering modules\n// such as `output.ts`, `error.ts` and `common/string.ts` need only the types\n// and `tokenItemToString`, and importing them from here keeps the terminal UI\n// runtime out of the startup path of every command.\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\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"]}
|
|
1
|
+
{"version":3,"file":"token-item.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/token-item.ts"],"names":[],"mappings":"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","sourcesContent":["// Token shapes and the pure helpers that operate on them.\n//\n// These live apart from `TokenizedText.tsx` on purpose. That file is a React\n// component module: importing it pulls in `react` and `ink`, and through Ink,\n// `react-reconciler`, `yoga-layout` and its WebAssembly. Non-rendering modules\n// such as `output.ts`, `error.ts` and `common/string.ts` need only the types\n// and `tokenItemToString`, and importing them from here keeps the terminal UI\n// runtime out of the startup path of every command.\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\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\n/** Converts tokens to JSON message text, retaining link URLs and list titles. */\nexport function tokenItemToJsonString(token: TokenItem): string {\n if (!Array.isArray(token)) return tokenToJsonString(token)\n\n return token\n .map((item, index) => {\n const value = tokenToJsonString(item)\n const needsLeadingSpace = index !== 0 && !(typeof item !== 'string' && 'char' in item)\n return needsLeadingSpace ? ` ${value}` : value\n })\n .join('')\n}\n\nfunction tokenToJsonString(token: Token): string {\n if (typeof token === 'string') return token\n\n if ('link' in token) {\n const {label, url} = token.link\n return label && label !== url ? `${label} (${url})` : url\n }\n\n if ('list' in token) {\n const title = token.list.title ? tokenItemToJsonString(token.list.title).trim() : undefined\n const items = token.list.items.map(tokenItemToJsonString).join('; ')\n return title ? `${title}${items ? `: ${items}` : ''}` : items\n }\n\n return tokenItemToString(token)\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
interface Options {
|
|
2
|
-
onFulfilled?: () => unknown;
|
|
1
|
+
interface Options<T> {
|
|
2
|
+
onFulfilled?: (result: T) => unknown;
|
|
3
3
|
onRejected?: (error: Error) => void;
|
|
4
4
|
}
|
|
5
|
-
export default function useAsyncAndUnmount(asyncFunction: () => Promise<
|
|
5
|
+
export default function useAsyncAndUnmount<T>(asyncFunction: () => Promise<T>, { onFulfilled, onRejected }?: Options<T>): void;
|
|
6
6
|
export {};
|
|
@@ -5,8 +5,8 @@ export default function useAsyncAndUnmount(asyncFunction, { onFulfilled = () =>
|
|
|
5
5
|
const [result, setResult] = useState(null);
|
|
6
6
|
useEffect(() => {
|
|
7
7
|
asyncFunction()
|
|
8
|
-
.then(() => {
|
|
9
|
-
onFulfilled();
|
|
8
|
+
.then((result) => {
|
|
9
|
+
onFulfilled(result);
|
|
10
10
|
setResult({});
|
|
11
11
|
})
|
|
12
12
|
.catch((error) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-async-and-unmount.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/hooks/use-async-and-unmount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,aAAa,CAAA;AACvC,OAAO,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AAOzC,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,
|
|
1
|
+
{"version":3,"file":"use-async-and-unmount.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/hooks/use-async-and-unmount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,aAAa,CAAA;AACvC,OAAO,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AAOzC,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,aAA+B,EAC/B,EAAC,WAAW,GAAG,GAAG,EAAE,GAAE,CAAC,EAAE,UAAU,GAAG,GAAG,EAAE,GAAE,CAAC,KAAgB,EAAE;IAEhE,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAyB,IAAI,CAAC,CAAA;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,aAAa,EAAE;aACZ,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,WAAW,CAAC,MAAM,CAAC,CAAA;YACnB,SAAS,CAAC,EAAE,CAAC,CAAA;QACf,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,UAAU,CAAC,KAAK,CAAC,CAAA;YACjB,SAAS,CAAC,EAAC,KAAK,EAAC,CAAC,CAAA;QACpB,CAAC,CAAC,CAAA;IACN,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACxB,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;AACd,CAAC","sourcesContent":["import {useComplete} from '../../ui.js'\nimport {useEffect, useState} from 'react'\n\ninterface Options<T> {\n onFulfilled?: (result: T) => unknown\n onRejected?: (error: Error) => void\n}\n\nexport default function useAsyncAndUnmount<T>(\n asyncFunction: () => Promise<T>,\n {onFulfilled = () => {}, onRejected = () => {}}: Options<T> = {},\n) {\n const complete = useComplete()\n const [result, setResult] = useState<{error?: Error} | null>(null)\n\n useEffect(() => {\n asyncFunction()\n .then((result) => {\n onFulfilled(result)\n setResult({})\n })\n .catch((error) => {\n onRejected(error)\n setResult({error})\n })\n }, [])\n\n useEffect(() => {\n if (result !== null) {\n complete(result.error)\n }\n }, [result])\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { TokenizedString } from '../../../public/node/output.js';
|
|
2
|
+
export interface Task<TContext = unknown> {
|
|
3
|
+
title: string | TokenizedString;
|
|
4
|
+
task: (ctx: TContext, task: Task<TContext>) => Promise<void | Task<TContext>[]>;
|
|
5
|
+
retry?: number;
|
|
6
|
+
retryCount?: number;
|
|
7
|
+
errors?: Error[];
|
|
8
|
+
skip?: (ctx: TContext) => boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function runTasks<TContext>(tasks: Task<TContext>[], onTask?: (task: Task<TContext>) => void): Promise<TContext>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { emitCommandEvent } from '../../../public/node/command-events.js';
|
|
2
|
+
import { randomUUID } from '../../../public/node/crypto.js';
|
|
3
|
+
import { unstyled } from '../../../public/node/output.js';
|
|
4
|
+
export async function runTasks(tasks, onTask = () => { }) {
|
|
5
|
+
const context = {};
|
|
6
|
+
const operation = randomUUID();
|
|
7
|
+
let currentTask;
|
|
8
|
+
const execute = async (task) => {
|
|
9
|
+
try {
|
|
10
|
+
onTask(task);
|
|
11
|
+
return await runTask(task, context, (status) => {
|
|
12
|
+
emitCommandEvent({
|
|
13
|
+
type: 'progress',
|
|
14
|
+
operation,
|
|
15
|
+
status: status === 'started' && currentTask ? 'updated' : status,
|
|
16
|
+
message: taskMessage(task),
|
|
17
|
+
}, { alreadyRendered: true });
|
|
18
|
+
currentTask = task;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
emitCommandEvent({ type: 'progress', operation, status: 'failed', message: taskMessage(task) }, { alreadyRendered: true });
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
for (const task of tasks) {
|
|
27
|
+
// eslint-disable-next-line no-await-in-loop
|
|
28
|
+
const subTasks = await execute(task);
|
|
29
|
+
if (Array.isArray(subTasks) && subTasks.length > 0 && subTasks.every((task) => 'task' in task)) {
|
|
30
|
+
for (const subTask of subTasks) {
|
|
31
|
+
// eslint-disable-next-line no-await-in-loop
|
|
32
|
+
await execute(subTask);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// A task list can grow while it runs, so only the entire list marks the operation complete.
|
|
37
|
+
if (currentTask) {
|
|
38
|
+
emitCommandEvent({ type: 'progress', operation, status: 'completed', message: taskMessage(currentTask), current: 1, total: 1 }, { alreadyRendered: true });
|
|
39
|
+
}
|
|
40
|
+
return context;
|
|
41
|
+
}
|
|
42
|
+
async function runTask(task, context, onProgress) {
|
|
43
|
+
task.retryCount = 0;
|
|
44
|
+
task.errors = [];
|
|
45
|
+
const maxAttempts = task.retry && task.retry > 0 ? task.retry + 1 : 1;
|
|
46
|
+
let started = false;
|
|
47
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
48
|
+
try {
|
|
49
|
+
if (task.skip?.(context))
|
|
50
|
+
return;
|
|
51
|
+
onProgress(started ? 'retrying' : 'started');
|
|
52
|
+
started = true;
|
|
53
|
+
// eslint-disable-next-line no-await-in-loop
|
|
54
|
+
return await task.task(context, task);
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (attempt === maxAttempts)
|
|
59
|
+
throw error;
|
|
60
|
+
task.errors.push(error);
|
|
61
|
+
task.retryCount = attempt;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function taskMessage(task) {
|
|
66
|
+
return unstyled(typeof task.title === 'string' ? task.title : task.title.value);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../../src/private/node/ui/tasks.ts"],"names":[],"mappings":"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","sourcesContent":["import {emitCommandEvent} from '../../../public/node/command-events.js'\nimport {randomUUID} from '../../../public/node/crypto.js'\nimport {TokenizedString, unstyled} from '../../../public/node/output.js'\n\nexport interface Task<TContext = unknown> {\n title: string | TokenizedString\n task: (ctx: TContext, task: Task<TContext>) => Promise<void | Task<TContext>[]>\n retry?: number\n retryCount?: number\n errors?: Error[]\n skip?: (ctx: TContext) => boolean\n}\n\nexport async function runTasks<TContext>(tasks: Task<TContext>[], onTask: (task: Task<TContext>) => void = () => {}) {\n const context = {} as TContext\n const operation = randomUUID()\n let currentTask: Task<TContext> | undefined\n\n const execute = async (task: Task<TContext>) => {\n try {\n onTask(task)\n return await runTask(task, context, (status) => {\n emitCommandEvent(\n {\n type: 'progress',\n operation,\n status: status === 'started' && currentTask ? 'updated' : status,\n message: taskMessage(task),\n },\n {alreadyRendered: true},\n )\n currentTask = task\n })\n } catch (error) {\n emitCommandEvent(\n {type: 'progress', operation, status: 'failed', message: taskMessage(task)},\n {alreadyRendered: true},\n )\n throw error\n }\n }\n\n for (const task of tasks) {\n // eslint-disable-next-line no-await-in-loop\n const subTasks = await execute(task)\n\n if (Array.isArray(subTasks) && subTasks.length > 0 && subTasks.every((task) => 'task' in task)) {\n for (const subTask of subTasks) {\n // eslint-disable-next-line no-await-in-loop\n await execute(subTask)\n }\n }\n }\n\n // A task list can grow while it runs, so only the entire list marks the operation complete.\n if (currentTask) {\n emitCommandEvent(\n {type: 'progress', operation, status: 'completed', message: taskMessage(currentTask), current: 1, total: 1},\n {alreadyRendered: true},\n )\n }\n\n return context\n}\n\nasync function runTask<TContext>(\n task: Task<TContext>,\n context: TContext,\n onProgress: (status: 'started' | 'retrying') => void,\n) {\n task.retryCount = 0\n task.errors = []\n const maxAttempts = task.retry && task.retry > 0 ? task.retry + 1 : 1\n let started = false\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n if (task.skip?.(context)) return\n\n onProgress(started ? 'retrying' : 'started')\n started = true\n\n // eslint-disable-next-line no-await-in-loop\n return await task.task(context, task)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n if (attempt === maxAttempts) throw error\n task.errors.push(error)\n task.retryCount = attempt\n }\n }\n}\n\nfunction taskMessage<TContext>(task: Task<TContext>) {\n return unstyled(typeof task.title === 'string' ? task.title : task.title.value)\n}\n"]}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Schema for a diagnostic emitted while a command executes. */
|
|
3
|
+
export declare const commandDiagnosticEventSchema: z.ZodObject<{
|
|
4
|
+
type: z.ZodLiteral<"diagnostic">;
|
|
5
|
+
timestamp: z.ZodString;
|
|
6
|
+
level: z.ZodEnum<["debug", "info", "warning", "error"]>;
|
|
7
|
+
message: z.ZodString;
|
|
8
|
+
code: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, "strict", z.ZodTypeAny, {
|
|
10
|
+
type: "diagnostic";
|
|
11
|
+
message: string;
|
|
12
|
+
timestamp: string;
|
|
13
|
+
level: "info" | "error" | "debug" | "warning";
|
|
14
|
+
code?: string | undefined;
|
|
15
|
+
}, {
|
|
16
|
+
type: "diagnostic";
|
|
17
|
+
message: string;
|
|
18
|
+
timestamp: string;
|
|
19
|
+
level: "info" | "error" | "debug" | "warning";
|
|
20
|
+
code?: string | undefined;
|
|
21
|
+
}>;
|
|
22
|
+
/** Schema for a progress update emitted while a command executes. */
|
|
23
|
+
export declare const commandProgressEventSchema: z.ZodObject<{
|
|
24
|
+
type: z.ZodLiteral<"progress">;
|
|
25
|
+
timestamp: z.ZodString;
|
|
26
|
+
status: z.ZodEnum<["started", "updated", "retrying", "completed", "failed"]>;
|
|
27
|
+
operation: z.ZodString;
|
|
28
|
+
message: z.ZodOptional<z.ZodString>;
|
|
29
|
+
current: z.ZodOptional<z.ZodNumber>;
|
|
30
|
+
total: z.ZodOptional<z.ZodNumber>;
|
|
31
|
+
}, "strict", z.ZodTypeAny, {
|
|
32
|
+
type: "progress";
|
|
33
|
+
status: "started" | "updated" | "retrying" | "completed" | "failed";
|
|
34
|
+
timestamp: string;
|
|
35
|
+
operation: string;
|
|
36
|
+
message?: string | undefined;
|
|
37
|
+
current?: number | undefined;
|
|
38
|
+
total?: number | undefined;
|
|
39
|
+
}, {
|
|
40
|
+
type: "progress";
|
|
41
|
+
status: "started" | "updated" | "retrying" | "completed" | "failed";
|
|
42
|
+
timestamp: string;
|
|
43
|
+
operation: string;
|
|
44
|
+
message?: string | undefined;
|
|
45
|
+
current?: number | undefined;
|
|
46
|
+
total?: number | undefined;
|
|
47
|
+
}>;
|
|
48
|
+
/** Schema for side events emitted while a command executes. */
|
|
49
|
+
export declare const commandEventSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
50
|
+
type: z.ZodLiteral<"diagnostic">;
|
|
51
|
+
timestamp: z.ZodString;
|
|
52
|
+
level: z.ZodEnum<["debug", "info", "warning", "error"]>;
|
|
53
|
+
message: z.ZodString;
|
|
54
|
+
code: z.ZodOptional<z.ZodString>;
|
|
55
|
+
}, "strict", z.ZodTypeAny, {
|
|
56
|
+
type: "diagnostic";
|
|
57
|
+
message: string;
|
|
58
|
+
timestamp: string;
|
|
59
|
+
level: "info" | "error" | "debug" | "warning";
|
|
60
|
+
code?: string | undefined;
|
|
61
|
+
}, {
|
|
62
|
+
type: "diagnostic";
|
|
63
|
+
message: string;
|
|
64
|
+
timestamp: string;
|
|
65
|
+
level: "info" | "error" | "debug" | "warning";
|
|
66
|
+
code?: string | undefined;
|
|
67
|
+
}>, z.ZodObject<{
|
|
68
|
+
type: z.ZodLiteral<"progress">;
|
|
69
|
+
timestamp: z.ZodString;
|
|
70
|
+
status: z.ZodEnum<["started", "updated", "retrying", "completed", "failed"]>;
|
|
71
|
+
operation: z.ZodString;
|
|
72
|
+
message: z.ZodOptional<z.ZodString>;
|
|
73
|
+
current: z.ZodOptional<z.ZodNumber>;
|
|
74
|
+
total: z.ZodOptional<z.ZodNumber>;
|
|
75
|
+
}, "strict", z.ZodTypeAny, {
|
|
76
|
+
type: "progress";
|
|
77
|
+
status: "started" | "updated" | "retrying" | "completed" | "failed";
|
|
78
|
+
timestamp: string;
|
|
79
|
+
operation: string;
|
|
80
|
+
message?: string | undefined;
|
|
81
|
+
current?: number | undefined;
|
|
82
|
+
total?: number | undefined;
|
|
83
|
+
}, {
|
|
84
|
+
type: "progress";
|
|
85
|
+
status: "started" | "updated" | "retrying" | "completed" | "failed";
|
|
86
|
+
timestamp: string;
|
|
87
|
+
operation: string;
|
|
88
|
+
message?: string | undefined;
|
|
89
|
+
current?: number | undefined;
|
|
90
|
+
total?: number | undefined;
|
|
91
|
+
}>]>;
|
|
92
|
+
/** A diagnostic emitted while a command executes. */
|
|
93
|
+
export type CommandDiagnosticEvent = z.infer<typeof commandDiagnosticEventSchema>;
|
|
94
|
+
/** A progress update emitted while a command executes. */
|
|
95
|
+
export type CommandProgressEvent = z.infer<typeof commandProgressEventSchema>;
|
|
96
|
+
/** A side event emitted while a command executes. */
|
|
97
|
+
export type CommandEvent = z.infer<typeof commandEventSchema>;
|
|
98
|
+
/** An event before its emission timestamp is added. */
|
|
99
|
+
export type CommandEventInput<TEvent extends CommandEvent = CommandEvent> = TEvent extends unknown ? Omit<TEvent, 'timestamp'> : never;
|
|
100
|
+
/** Presentation details that are not included in the emitted event. */
|
|
101
|
+
export interface CommandEventEmissionOptions {
|
|
102
|
+
/** The event is already visible in the command's text UI. */
|
|
103
|
+
alreadyRendered?: boolean;
|
|
104
|
+
}
|
|
105
|
+
/** Receives one timestamped event from a command execution. */
|
|
106
|
+
export type CommandEventSink<TEvent extends CommandEvent = CommandEvent> = (event: TEvent, options?: CommandEventEmissionOptions) => void;
|
|
107
|
+
/** Emits timestamped side events from one command execution. */
|
|
108
|
+
export interface CommandEventChannel<TEvent extends CommandEvent = CommandEvent> {
|
|
109
|
+
emit: (event: CommandEventInput<TEvent>, options?: CommandEventEmissionOptions) => void;
|
|
110
|
+
}
|
|
111
|
+
/** Supplies the current time when an event is emitted. */
|
|
112
|
+
export type CommandEventClock = () => Date;
|
|
113
|
+
/** Options for a command event channel. */
|
|
114
|
+
export interface CommandEventChannelOptions<TEvent extends CommandEvent> {
|
|
115
|
+
sink?: CommandEventSink<TEvent>;
|
|
116
|
+
clock?: CommandEventClock;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Creates a synchronous, execution-scoped channel for command side events.
|
|
120
|
+
* Adapters validate events at their output boundary; the channel preserves domain-specific event fields.
|
|
121
|
+
*
|
|
122
|
+
* @param options - The event sink and clock used by the channel.
|
|
123
|
+
* @returns A channel that adds a whole-second UTC timestamp before synchronously delivering each event.
|
|
124
|
+
*/
|
|
125
|
+
export declare function createCommandEventChannel<TEvent extends CommandEvent = CommandEvent>(options?: CommandEventChannelOptions<TEvent>): CommandEventChannel<TEvent>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { formatJsonOutputTimestamp, jsonOutputTimestampSchema } from './json-output-schema.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/** Schema for a diagnostic emitted while a command executes. */
|
|
4
|
+
export const commandDiagnosticEventSchema = z
|
|
5
|
+
.object({
|
|
6
|
+
type: z.literal('diagnostic'),
|
|
7
|
+
timestamp: jsonOutputTimestampSchema,
|
|
8
|
+
level: z.enum(['debug', 'info', 'warning', 'error']),
|
|
9
|
+
message: z.string(),
|
|
10
|
+
code: z.string().min(1).optional().describe('A stable diagnostic code, included only when known.'),
|
|
11
|
+
})
|
|
12
|
+
.strict();
|
|
13
|
+
/** Schema for a progress update emitted while a command executes. */
|
|
14
|
+
export const commandProgressEventSchema = z
|
|
15
|
+
.object({
|
|
16
|
+
type: z.literal('progress'),
|
|
17
|
+
timestamp: jsonOutputTimestampSchema,
|
|
18
|
+
status: z.enum(['started', 'updated', 'retrying', 'completed', 'failed']),
|
|
19
|
+
operation: z.string(),
|
|
20
|
+
message: z.string().optional(),
|
|
21
|
+
current: z.number().int().nonnegative().optional(),
|
|
22
|
+
total: z.number().int().nonnegative().optional(),
|
|
23
|
+
})
|
|
24
|
+
.strict();
|
|
25
|
+
/** Schema for side events emitted while a command executes. */
|
|
26
|
+
export const commandEventSchema = z.discriminatedUnion('type', [
|
|
27
|
+
commandDiagnosticEventSchema,
|
|
28
|
+
commandProgressEventSchema,
|
|
29
|
+
]);
|
|
30
|
+
/**
|
|
31
|
+
* Creates a synchronous, execution-scoped channel for command side events.
|
|
32
|
+
* Adapters validate events at their output boundary; the channel preserves domain-specific event fields.
|
|
33
|
+
*
|
|
34
|
+
* @param options - The event sink and clock used by the channel.
|
|
35
|
+
* @returns A channel that adds a whole-second UTC timestamp before synchronously delivering each event.
|
|
36
|
+
*/
|
|
37
|
+
export function createCommandEventChannel(options = {}) {
|
|
38
|
+
const sink = options.sink ?? (() => { });
|
|
39
|
+
const clock = options.clock ?? (() => new Date());
|
|
40
|
+
return {
|
|
41
|
+
emit(event, emissionOptions) {
|
|
42
|
+
const timestamp = formatJsonOutputTimestamp(clock());
|
|
43
|
+
// TypeScript cannot reconstruct the generic event from its distributive Omit.
|
|
44
|
+
const timestampedEvent = { ...event, timestamp };
|
|
45
|
+
if (emissionOptions === undefined) {
|
|
46
|
+
sink(timestampedEvent);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
sink(timestampedEvent, emissionOptions);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=command-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-events.js","sourceRoot":"","sources":["../../../src/public/common/command-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,yBAAyB,EAAE,yBAAyB,EAAC,MAAM,yBAAyB,CAAA;AAC5F,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAA;AAErB,gEAAgE;AAChE,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC;KAC1C,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IAC7B,SAAS,EAAE,yBAAyB;IACpC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACpD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;CACnG,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,qEAAqE;AACrE,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC;KACxC,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IAC3B,SAAS,EAAE,yBAAyB;IACpC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IACzE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IAClD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;CACjD,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,+DAA+D;AAC/D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC7D,4BAA4B;IAC5B,0BAA0B;CAC3B,CAAC,CAAA;AA0CF;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CACvC,UAA8C,EAAE;IAEhD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;IAEjD,OAAO;QACL,IAAI,CAAC,KAAK,EAAE,eAAe;YACzB,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,EAAE,CAAC,CAAA;YACpD,8EAA8E;YAC9E,MAAM,gBAAgB,GAAG,EAAC,GAAG,KAAK,EAAE,SAAS,EAAsB,CAAA;YACnE,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;gBAClC,IAAI,CAAC,gBAAgB,CAAC,CAAA;YACxB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAA;YACzC,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC","sourcesContent":["import {formatJsonOutputTimestamp, jsonOutputTimestampSchema} from './json-output-schema.js'\nimport {z} from 'zod'\n\n/** Schema for a diagnostic emitted while a command executes. */\nexport const commandDiagnosticEventSchema = z\n .object({\n type: z.literal('diagnostic'),\n timestamp: jsonOutputTimestampSchema,\n level: z.enum(['debug', 'info', 'warning', 'error']),\n message: z.string(),\n code: z.string().min(1).optional().describe('A stable diagnostic code, included only when known.'),\n })\n .strict()\n\n/** Schema for a progress update emitted while a command executes. */\nexport const commandProgressEventSchema = z\n .object({\n type: z.literal('progress'),\n timestamp: jsonOutputTimestampSchema,\n status: z.enum(['started', 'updated', 'retrying', 'completed', 'failed']),\n operation: z.string(),\n message: z.string().optional(),\n current: z.number().int().nonnegative().optional(),\n total: z.number().int().nonnegative().optional(),\n })\n .strict()\n\n/** Schema for side events emitted while a command executes. */\nexport const commandEventSchema = z.discriminatedUnion('type', [\n commandDiagnosticEventSchema,\n commandProgressEventSchema,\n])\n\n/** A diagnostic emitted while a command executes. */\nexport type CommandDiagnosticEvent = z.infer<typeof commandDiagnosticEventSchema>\n\n/** A progress update emitted while a command executes. */\nexport type CommandProgressEvent = z.infer<typeof commandProgressEventSchema>\n\n/** A side event emitted while a command executes. */\nexport type CommandEvent = z.infer<typeof commandEventSchema>\n\n/** An event before its emission timestamp is added. */\nexport type CommandEventInput<TEvent extends CommandEvent = CommandEvent> = TEvent extends unknown\n ? Omit<TEvent, 'timestamp'>\n : never\n\n/** Presentation details that are not included in the emitted event. */\nexport interface CommandEventEmissionOptions {\n /** The event is already visible in the command's text UI. */\n alreadyRendered?: boolean\n}\n\n/** Receives one timestamped event from a command execution. */\nexport type CommandEventSink<TEvent extends CommandEvent = CommandEvent> = (\n event: TEvent,\n options?: CommandEventEmissionOptions,\n) => void\n\n/** Emits timestamped side events from one command execution. */\nexport interface CommandEventChannel<TEvent extends CommandEvent = CommandEvent> {\n emit: (event: CommandEventInput<TEvent>, options?: CommandEventEmissionOptions) => void\n}\n\n/** Supplies the current time when an event is emitted. */\nexport type CommandEventClock = () => Date\n\n/** Options for a command event channel. */\nexport interface CommandEventChannelOptions<TEvent extends CommandEvent> {\n sink?: CommandEventSink<TEvent>\n clock?: CommandEventClock\n}\n\n/**\n * Creates a synchronous, execution-scoped channel for command side events.\n * Adapters validate events at their output boundary; the channel preserves domain-specific event fields.\n *\n * @param options - The event sink and clock used by the channel.\n * @returns A channel that adds a whole-second UTC timestamp before synchronously delivering each event.\n */\nexport function createCommandEventChannel<TEvent extends CommandEvent = CommandEvent>(\n options: CommandEventChannelOptions<TEvent> = {},\n): CommandEventChannel<TEvent> {\n const sink = options.sink ?? (() => {})\n const clock = options.clock ?? (() => new Date())\n\n return {\n emit(event, emissionOptions) {\n const timestamp = formatJsonOutputTimestamp(clock())\n // TypeScript cannot reconstruct the generic event from its distributive Omit.\n const timestampedEvent = {...event, timestamp} as unknown as TEvent\n if (emissionOptions === undefined) {\n sink(timestampedEvent)\n } else {\n sink(timestampedEvent, emissionOptions)\n }\n },\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** UTC instants in CLI-owned JSON use whole seconds and the Z timezone marker. */
|
|
3
|
+
export declare const jsonOutputTimestampSchema: z.ZodString;
|
|
4
|
+
/**
|
|
5
|
+
* Formats an instant for CLI-owned JSON, truncating fractional seconds without rounding.
|
|
6
|
+
*
|
|
7
|
+
* @param date - The instant to format.
|
|
8
|
+
* @returns A UTC ISO 8601 timestamp with whole seconds and the Z timezone marker.
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatJsonOutputTimestamp(date: Date): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** UTC instants in CLI-owned JSON use whole seconds and the Z timezone marker. */
|
|
3
|
+
export const jsonOutputTimestampSchema = z
|
|
4
|
+
.string()
|
|
5
|
+
.datetime({ precision: 0 })
|
|
6
|
+
.regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/)
|
|
7
|
+
.describe('A UTC ISO 8601 instant with whole seconds and the Z timezone marker.');
|
|
8
|
+
/**
|
|
9
|
+
* Formats an instant for CLI-owned JSON, truncating fractional seconds without rounding.
|
|
10
|
+
*
|
|
11
|
+
* @param date - The instant to format.
|
|
12
|
+
* @returns A UTC ISO 8601 timestamp with whole seconds and the Z timezone marker.
|
|
13
|
+
*/
|
|
14
|
+
export function formatJsonOutputTimestamp(date) {
|
|
15
|
+
return date.toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=json-output-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-output-schema.js","sourceRoot":"","sources":["../../../src/public/common/json-output-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAA;AAErB,kFAAkF;AAClF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC;KACvC,MAAM,EAAE;KACR,QAAQ,CAAC,EAAC,SAAS,EAAE,CAAC,EAAC,CAAC;KACxB,KAAK,CAAC,wCAAwC,CAAC;KAC/C,QAAQ,CAAC,sEAAsE,CAAC,CAAA;AAEnF;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAU;IAClD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;AACrD,CAAC","sourcesContent":["import {z} from 'zod'\n\n/** UTC instants in CLI-owned JSON use whole seconds and the Z timezone marker. */\nexport const jsonOutputTimestampSchema = z\n .string()\n .datetime({precision: 0})\n .regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/)\n .describe('A UTC ISO 8601 instant with whole seconds and the Z timezone marker.')\n\n/**\n * Formats an instant for CLI-owned JSON, truncating fractional seconds without rounding.\n *\n * @param date - The instant to format.\n * @returns A UTC ISO 8601 timestamp with whole seconds and the Z timezone marker.\n */\nexport function formatJsonOutputTimestamp(date: Date): string {\n return date.toISOString().replace(/\\.\\d{3}Z$/, 'Z')\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CLI_KIT_VERSION = "4.
|
|
1
|
+
export declare const CLI_KIT_VERSION = "4.9.0";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const CLI_KIT_VERSION = '4.
|
|
1
|
+
export const CLI_KIT_VERSION = '4.9.0';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '4.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '4.9.0'\n"]}
|