@shopify/cli-kit 3.30.2 → 3.31.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/environment/fqdn.d.ts +6 -0
- package/dist/environment/fqdn.js +13 -2
- package/dist/environment/fqdn.js.map +1 -1
- package/dist/private/node/ui/components/Alert.test.js +3 -3
- package/dist/private/node/ui/components/Alert.test.js.map +1 -1
- package/dist/private/node/ui/components/Banner.js +5 -21
- package/dist/private/node/ui/components/Banner.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.d.ts +0 -1
- package/dist/private/node/ui/components/ConcurrentOutput.js +6 -16
- package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.test.js +3 -2
- package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
- package/dist/private/node/ui/components/FatalError.js +2 -2
- package/dist/private/node/ui/components/FatalError.js.map +1 -1
- package/dist/private/node/ui/components/FatalError.test.js +10 -10
- package/dist/private/node/ui/components/FatalError.test.js.map +1 -1
- package/dist/private/node/ui/components/Link.js +1 -1
- package/dist/private/node/ui/components/Link.js.map +1 -1
- package/dist/private/node/ui/components/Link.test.js +1 -1
- package/dist/private/node/ui/components/Link.test.js.map +1 -1
- package/dist/private/node/ui/components/Prompt.js +1 -1
- package/dist/private/node/ui/components/Prompt.js.map +1 -1
- package/dist/private/node/ui/components/Prompt.test.js +4 -2
- package/dist/private/node/ui/components/Prompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.d.ts +10 -0
- package/dist/private/node/ui/components/Tasks.js +27 -0
- package/dist/private/node/ui/components/Tasks.js.map +1 -0
- package/dist/private/node/ui/components/Tasks.test.d.ts +1 -0
- package/dist/private/node/ui/components/Tasks.test.js +50 -0
- package/dist/private/node/ui/components/Tasks.test.js.map +1 -0
- package/dist/private/node/ui/components/TextAnimation.d.ts +2 -4
- package/dist/private/node/ui/components/TextAnimation.js +24 -35
- package/dist/private/node/ui/components/TextAnimation.js.map +1 -1
- package/dist/private/node/ui/components/TokenizedText.test.js +1 -1
- package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -1
- package/dist/private/node/ui/hooks/use-async-and-unmount.d.ts +6 -0
- package/dist/private/node/ui/hooks/use-async-and-unmount.js +17 -0
- package/dist/private/node/ui/hooks/use-async-and-unmount.js.map +1 -0
- package/dist/private/node/ui/hooks/use-layout.d.ts +3 -0
- package/dist/private/node/ui/hooks/use-layout.js +21 -0
- package/dist/private/node/ui/hooks/use-layout.js.map +1 -0
- package/dist/private/node/ui.d.ts +11 -0
- package/dist/private/node/ui.js +1 -1
- package/dist/private/node/ui.js.map +1 -1
- package/dist/public/node/ui.d.ts +5 -0
- package/dist/public/node/ui.js +7 -0
- package/dist/public/node/ui.js.map +1 -1
- package/dist/session.js +8 -5
- package/dist/session.js.map +1 -1
- package/dist/string.d.ts +0 -6
- package/dist/string.js +0 -11
- package/dist/string.js.map +1 -1
- package/dist/testing/ui.d.ts +1 -0
- package/dist/testing/ui.js +4 -0
- package/dist/testing/ui.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -4
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TextAnimation } from './TextAnimation.js';
|
|
2
|
+
import useLayout from '../hooks/use-layout.js';
|
|
3
|
+
import useAsyncAndUnmount from '../hooks/use-async-and-unmount.js';
|
|
4
|
+
import { Box, Text } from 'ink';
|
|
5
|
+
import React, { useState } from 'react';
|
|
6
|
+
const loadingBarChar = '█';
|
|
7
|
+
const Tasks = ({ tasks }) => {
|
|
8
|
+
const { width } = useLayout();
|
|
9
|
+
const loadingBar = new Array(width).fill(loadingBarChar).join('');
|
|
10
|
+
const [currentTask, setCurrentTask] = useState(tasks[0]);
|
|
11
|
+
const [state, setState] = useState('loading');
|
|
12
|
+
const runTasks = async () => {
|
|
13
|
+
for (const task of tasks) {
|
|
14
|
+
setCurrentTask(task);
|
|
15
|
+
// eslint-disable-next-line no-await-in-loop
|
|
16
|
+
await task.task();
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
useAsyncAndUnmount(runTasks, { onFulfilled: () => setState('success'), onRejected: () => setState('failure') });
|
|
20
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
21
|
+
React.createElement(Box, null, state === 'loading' ? (React.createElement(TextAnimation, { text: loadingBar })) : (React.createElement(Text, { color: state === 'success' ? 'green' : 'red' }, loadingBar))),
|
|
22
|
+
React.createElement(Text, null, state === 'success' ? (React.createElement(Text, null, "Complete!")) : (React.createElement(Text, null,
|
|
23
|
+
currentTask.title,
|
|
24
|
+
state === 'loading' && ' ...')))));
|
|
25
|
+
};
|
|
26
|
+
export default Tasks;
|
|
27
|
+
//# sourceMappingURL=Tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tasks.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Tasks.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAA;AAChD,OAAO,SAAS,MAAM,wBAAwB,CAAA;AAC9C,OAAO,kBAAkB,MAAM,mCAAmC,CAAA;AAClE,OAAO,EAAC,GAAG,EAAE,IAAI,EAAC,MAAM,KAAK,CAAA;AAC7B,OAAO,KAAK,EAAE,EAAC,QAAQ,EAAC,MAAM,OAAO,CAAA;AAErC,MAAM,cAAc,GAAG,GAAG,CAAA;AAW1B,MAAM,KAAK,GAAoB,CAAC,EAAC,KAAK,EAAC,EAAE,EAAE;IACzC,MAAM,EAAC,KAAK,EAAC,GAAG,SAAS,EAAE,CAAA;IAC3B,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjE,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAO,KAAK,CAAC,CAAC,CAAE,CAAC,CAAA;IAC/D,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAoC,SAAS,CAAC,CAAA;IAEhF,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YACxB,cAAc,CAAC,IAAI,CAAC,CAAA;YACpB,4CAA4C;YAC5C,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;SAClB;IACH,CAAC,CAAA;IAED,kBAAkB,CAAC,QAAQ,EAAE,EAAC,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAC,CAAC,CAAA;IAE7G,OAAO,CACL,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;QACzB,oBAAC,GAAG,QACD,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CACrB,oBAAC,aAAa,IAAC,IAAI,EAAE,UAAU,GAAI,CACpC,CAAC,CAAC,CAAC,CACF,oBAAC,IAAI,IAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAG,UAAU,CAAQ,CACxE,CACG;QACN,oBAAC,IAAI,QACF,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CACrB,oBAAC,IAAI,oBAAiB,CACvB,CAAC,CAAC,CAAC,CACF,oBAAC,IAAI;YACF,WAAW,CAAC,KAAK;YACjB,KAAK,KAAK,SAAS,IAAI,MAAM,CACzB,CACR,CACI,CACH,CACP,CAAA;AACH,CAAC,CAAA;AAED,eAAe,KAAK,CAAA","sourcesContent":["import {TextAnimation} from './TextAnimation.js'\nimport useLayout from '../hooks/use-layout.js'\nimport useAsyncAndUnmount from '../hooks/use-async-and-unmount.js'\nimport {Box, Text} from 'ink'\nimport React, {useState} from 'react'\n\nconst loadingBarChar = '█'\n\nexport interface Task {\n title: string\n task: () => Promise<void>\n}\n\nexport interface Props {\n tasks: Task[]\n}\n\nconst Tasks: React.FC<Props> = ({tasks}) => {\n const {width} = useLayout()\n const loadingBar = new Array(width).fill(loadingBarChar).join('')\n const [currentTask, setCurrentTask] = useState<Task>(tasks[0]!)\n const [state, setState] = useState<'success' | 'failure' | 'loading'>('loading')\n\n const runTasks = async () => {\n for (const task of tasks) {\n setCurrentTask(task)\n // eslint-disable-next-line no-await-in-loop\n await task.task()\n }\n }\n\n useAsyncAndUnmount(runTasks, {onFulfilled: () => setState('success'), onRejected: () => setState('failure')})\n\n return (\n <Box flexDirection=\"column\">\n <Box>\n {state === 'loading' ? (\n <TextAnimation text={loadingBar} />\n ) : (\n <Text color={state === 'success' ? 'green' : 'red'}>{loadingBar}</Text>\n )}\n </Box>\n <Text>\n {state === 'success' ? (\n <Text>Complete!</Text>\n ) : (\n <Text>\n {currentTask.title}\n {state === 'loading' && ' ...'}\n </Text>\n )}\n </Text>\n </Box>\n )\n}\n\nexport default Tasks\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import Tasks from './Tasks.js';
|
|
2
|
+
import { getLastFrame } from '../../../../testing/ui.js';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { describe, expect, test } from 'vitest';
|
|
5
|
+
import { render } from 'ink-testing-library';
|
|
6
|
+
describe('Tasks', () => {
|
|
7
|
+
test('shows a success state at the end', async () => {
|
|
8
|
+
// Given
|
|
9
|
+
const firstTask = {
|
|
10
|
+
title: 'task 1',
|
|
11
|
+
task: async () => { },
|
|
12
|
+
};
|
|
13
|
+
const secondTask = {
|
|
14
|
+
title: 'task 2',
|
|
15
|
+
task: async () => { },
|
|
16
|
+
};
|
|
17
|
+
// When
|
|
18
|
+
const renderInstance = render(React.createElement(Tasks, { tasks: [firstTask, secondTask] }));
|
|
19
|
+
// wait for next tick
|
|
20
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
21
|
+
// Then
|
|
22
|
+
expect(getLastFrame(renderInstance)).toMatchInlineSnapshot(`
|
|
23
|
+
"[32m████████████████████████████████████████████████████████████████████████████████[39m
|
|
24
|
+
Complete!"
|
|
25
|
+
`);
|
|
26
|
+
});
|
|
27
|
+
test('shows a failure state at the end', async () => {
|
|
28
|
+
// Given
|
|
29
|
+
const firstTask = {
|
|
30
|
+
title: 'task 1',
|
|
31
|
+
task: async () => {
|
|
32
|
+
throw new Error('something went wrong');
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
const secondTask = {
|
|
36
|
+
title: 'task 2',
|
|
37
|
+
task: async () => { },
|
|
38
|
+
};
|
|
39
|
+
// When
|
|
40
|
+
const renderInstance = render(React.createElement(Tasks, { tasks: [firstTask, secondTask] }));
|
|
41
|
+
// wait for next tick
|
|
42
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
43
|
+
// Then
|
|
44
|
+
expect(getLastFrame(renderInstance)).toMatchInlineSnapshot(`
|
|
45
|
+
"[31m████████████████████████████████████████████████████████████████████████████████[39m
|
|
46
|
+
task 1"
|
|
47
|
+
`);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=Tasks.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tasks.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Tasks.test.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,EAAC,YAAY,EAAC,MAAM,2BAA2B,CAAA;AACtD,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAC,MAAM,EAAC,MAAM,qBAAqB,CAAA;AAE1C,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,IAAI,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAClD,QAAQ;QACR,MAAM,SAAS,GAAG;YAChB,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;SACrB,CAAA;QAED,MAAM,UAAU,GAAG;YACjB,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;SACrB,CAAA;QACD,OAAO;QAEP,MAAM,cAAc,GAAG,MAAM,CAAC,oBAAC,KAAK,IAAC,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,GAAI,CAAC,CAAA;QAExE,qBAAqB;QACrB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;QAEtD,OAAO;QACP,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;KAG1D,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAClD,QAAQ;QACR,MAAM,SAAS,GAAG;YAChB,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;YACzC,CAAC;SACF,CAAA;QAED,MAAM,UAAU,GAAG;YACjB,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;SACrB,CAAA;QAED,OAAO;QACP,MAAM,cAAc,GAAG,MAAM,CAAC,oBAAC,KAAK,IAAC,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,GAAI,CAAC,CAAA;QAExE,qBAAqB;QACrB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;QAEtD,OAAO;QACP,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;KAG1D,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import Tasks from './Tasks.js'\nimport {getLastFrame} from '../../../../testing/ui.js'\nimport React from 'react'\nimport {describe, expect, test} from 'vitest'\nimport {render} from 'ink-testing-library'\n\ndescribe('Tasks', () => {\n test('shows a success state at the end', async () => {\n // Given\n const firstTask = {\n title: 'task 1',\n task: async () => {},\n }\n\n const secondTask = {\n title: 'task 2',\n task: async () => {},\n }\n // When\n\n const renderInstance = render(<Tasks tasks={[firstTask, secondTask]} />)\n\n // wait for next tick\n await new Promise((resolve) => setTimeout(resolve, 0))\n\n // Then\n expect(getLastFrame(renderInstance)).toMatchInlineSnapshot(`\n \"\u001b[32m████████████████████████████████████████████████████████████████████████████████\u001b[39m\n Complete!\"\n `)\n })\n\n test('shows a failure state at the end', async () => {\n // Given\n const firstTask = {\n title: 'task 1',\n task: async () => {\n throw new Error('something went wrong')\n },\n }\n\n const secondTask = {\n title: 'task 2',\n task: async () => {},\n }\n\n // When\n const renderInstance = render(<Tasks tasks={[firstTask, secondTask]} />)\n\n // wait for next tick\n await new Promise((resolve) => setTimeout(resolve, 0))\n\n // Then\n expect(getLastFrame(renderInstance)).toMatchInlineSnapshot(`\n \"\u001b[31m████████████████████████████████████████████████████████████████████████████████\u001b[39m\n task 1\"\n `)\n })\n})\n"]}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
declare type AnimationName = 'rainbow' | 'pulse' | 'glitch' | 'radar' | 'neon' | 'karaoke';
|
|
3
2
|
interface Props {
|
|
4
|
-
|
|
5
|
-
speed?: number;
|
|
3
|
+
text: string;
|
|
6
4
|
}
|
|
7
5
|
/**
|
|
8
|
-
* `TextAnimation` applies
|
|
6
|
+
* `TextAnimation` applies a rainbow animation to text.
|
|
9
7
|
*/
|
|
10
8
|
declare const TextAnimation: React.FC<Props>;
|
|
11
9
|
export { TextAnimation };
|
|
@@ -1,46 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
import chalkAnimation from 'chalk-animation';
|
|
1
|
+
/* eslint-disable id-length */
|
|
3
2
|
import { Text } from 'ink';
|
|
4
|
-
import React, { useEffect, useState } from 'react';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
};
|
|
3
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
4
|
+
import gradient from 'gradient-string';
|
|
5
|
+
function rainbow(text, frame) {
|
|
6
|
+
const hue = 5 * frame;
|
|
7
|
+
const leftColor = { h: hue % 360, s: 0.8, v: 1 };
|
|
8
|
+
const rightColor = { h: (hue + 1) % 360, s: 0.8, v: 1 };
|
|
9
|
+
return gradient(leftColor, rightColor)(text, { interpolation: 'hsv', hsvSpin: 'long' });
|
|
10
|
+
}
|
|
13
11
|
/**
|
|
14
|
-
* `TextAnimation` applies
|
|
12
|
+
* `TextAnimation` applies a rainbow animation to text.
|
|
15
13
|
*/
|
|
16
|
-
const TextAnimation = ({
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.replace(output ?? '')
|
|
28
|
-
.frame()
|
|
29
|
-
.replace(/^\u001B\[(\d)F\u001B\[G\u001B\[2K/, ''); // eslint-disable-line no-control-regex
|
|
30
|
-
setFrame(frame);
|
|
31
|
-
setAnimationTimeout(setTimeout(() => {
|
|
32
|
-
start();
|
|
33
|
-
}, delays[name] / speed));
|
|
14
|
+
const TextAnimation = ({ text }) => {
|
|
15
|
+
const frame = useRef(0);
|
|
16
|
+
const [renderedFrame, setRenderedFrame] = useState(text);
|
|
17
|
+
const timeout = useRef();
|
|
18
|
+
const renderAnimation = () => {
|
|
19
|
+
const newFrame = frame.current + 1;
|
|
20
|
+
frame.current = newFrame;
|
|
21
|
+
setRenderedFrame(rainbow(text, frame.current));
|
|
22
|
+
timeout.current = setTimeout(() => {
|
|
23
|
+
renderAnimation();
|
|
24
|
+
}, 35);
|
|
34
25
|
};
|
|
35
26
|
useEffect(() => {
|
|
36
|
-
|
|
27
|
+
renderAnimation();
|
|
37
28
|
return () => {
|
|
38
|
-
|
|
39
|
-
clearTimeout(animationTimeout);
|
|
40
|
-
setAnimationTimeout(null);
|
|
29
|
+
clearTimeout(timeout.current);
|
|
41
30
|
};
|
|
42
31
|
}, []);
|
|
43
|
-
return React.createElement(Text, null,
|
|
32
|
+
return React.createElement(Text, null, renderedFrame);
|
|
44
33
|
};
|
|
45
34
|
export { TextAnimation };
|
|
46
35
|
//# sourceMappingURL=TextAnimation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextAnimation.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TextAnimation.tsx"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"TextAnimation.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TextAnimation.tsx"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,OAAO,EAAC,IAAI,EAAC,MAAM,KAAK,CAAA;AACxB,OAAO,KAAK,EAAE,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AACxD,OAAO,QAAQ,MAAM,iBAAiB,CAAA;AAMtC,SAAS,OAAO,CAAC,IAAY,EAAE,KAAa;IAC1C,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK,CAAA;IACrB,MAAM,SAAS,GAAG,EAAC,CAAC,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAC,CAAA;IAC9C,MAAM,UAAU,GAAG,EAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAC,CAAA;IACrD,OAAO,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,EAAC,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAC,CAAC,CAAA;AACvF,CAAC;AAED;;GAEG;AACH,MAAM,aAAa,GAAoB,CAAC,EAAC,IAAI,EAAC,EAAe,EAAE;IAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IACvB,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IACxD,MAAM,OAAO,GAAG,MAAM,EAAkB,CAAA;IAExC,MAAM,eAAe,GAAG,GAAG,EAAE;QAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,GAAG,CAAC,CAAA;QAClC,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAA;QAExB,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;QAE9C,OAAO,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,eAAe,EAAE,CAAA;QACnB,CAAC,EAAE,EAAE,CAAC,CAAA;IACR,CAAC,CAAA;IAED,SAAS,CAAC,GAAG,EAAE;QACb,eAAe,EAAE,CAAA;QAEjB,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC/B,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,oBAAC,IAAI,QAAE,aAAa,CAAQ,CAAA;AACrC,CAAC,CAAA;AAED,OAAO,EAAC,aAAa,EAAC,CAAA","sourcesContent":["/* eslint-disable id-length */\nimport {Text} from 'ink'\nimport React, {useEffect, useRef, useState} from 'react'\nimport gradient from 'gradient-string'\n\ninterface Props {\n text: string\n}\n\nfunction rainbow(text: string, frame: number) {\n const hue = 5 * frame\n const leftColor = {h: hue % 360, s: 0.8, v: 1}\n const rightColor = {h: (hue + 1) % 360, s: 0.8, v: 1}\n return gradient(leftColor, rightColor)(text, {interpolation: 'hsv', hsvSpin: 'long'})\n}\n\n/**\n * `TextAnimation` applies a rainbow animation to text.\n */\nconst TextAnimation: React.FC<Props> = ({text}): JSX.Element => {\n const frame = useRef(0)\n const [renderedFrame, setRenderedFrame] = useState(text)\n const timeout = useRef<NodeJS.Timeout>()\n\n const renderAnimation = () => {\n const newFrame = frame.current + 1\n frame.current = newFrame\n\n setRenderedFrame(rainbow(text, frame.current))\n\n timeout.current = setTimeout(() => {\n renderAnimation()\n }, 35)\n }\n\n useEffect(() => {\n renderAnimation()\n\n return () => {\n clearTimeout(timeout.current)\n }\n }, [])\n\n return <Text>{renderedFrame}</Text>\n}\n\nexport {TextAnimation}\n"]}
|
|
@@ -33,7 +33,7 @@ describe('TokenizedText', async () => {
|
|
|
33
33
|
];
|
|
34
34
|
const { output } = renderString(React.createElement(TokenizedText, { item: item }));
|
|
35
35
|
expect(unstyled(output)).toMatchInlineSnapshot(`
|
|
36
|
-
"Run \`cd verification-app\` Example (https://example.com)! my-app
|
|
36
|
+
"Run \`cd verification-app\` Example ( https://example.com )! my-app
|
|
37
37
|
• Item 1
|
|
38
38
|
• Item 2
|
|
39
39
|
• Item 3
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenizedText.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TokenizedText.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAQ,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;IACnC,IAAI,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,IAAI,GAAG;YACX,KAAK;YACL;gBACE,OAAO,EAAE,qBAAqB;aAC/B;YACD;gBACE,IAAI,EAAE;oBACJ,GAAG,EAAE,qBAAqB;oBAC1B,KAAK,EAAE,SAAS;iBACjB;aACF;YACD;gBACE,IAAI,EAAE,GAAG;aACV;YACD;gBACE,SAAS,EAAE,QAAQ;aACpB;YACD;gBACE,IAAI,EAAE;oBACJ,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;iBACtC;aACF;YACD;gBACE,QAAQ,EAAE,uBAAuB;aAClC;SACF,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,aAAa,IAAC,IAAI,EAAE,IAAI,GAAI,CAAC,CAAA;QAE5D,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;KAM/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {TokenizedText} from './TokenizedText.js'\nimport {renderString} from '../../ui.js'\nimport {unstyled} from '../../../../output.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('TokenizedText', async () => {\n test('renders arrays of items separated by spaces', async () => {\n const item = [\n 'Run',\n {\n command: 'cd verification-app',\n },\n {\n link: {\n url: 'https://example.com',\n label: 'Example',\n },\n },\n {\n char: '!',\n },\n {\n userInput: 'my-app',\n },\n {\n list: {\n items: ['Item 1', 'Item 2', 'Item 3'],\n },\n },\n {\n filePath: 'src/this/is/a/test.js',\n },\n ]\n\n const {output} = renderString(<TokenizedText item={item} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"Run \\`cd verification-app\\` Example (https://example.com)! my-app\n • Item 1\n • Item 2\n • Item 3\n \\\\\"src/this/is/a/test.js\\\\\"\"\n `)\n })\n})\n"]}
|
|
1
|
+
{"version":3,"file":"TokenizedText.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TokenizedText.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAQ,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;IACnC,IAAI,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,IAAI,GAAG;YACX,KAAK;YACL;gBACE,OAAO,EAAE,qBAAqB;aAC/B;YACD;gBACE,IAAI,EAAE;oBACJ,GAAG,EAAE,qBAAqB;oBAC1B,KAAK,EAAE,SAAS;iBACjB;aACF;YACD;gBACE,IAAI,EAAE,GAAG;aACV;YACD;gBACE,SAAS,EAAE,QAAQ;aACpB;YACD;gBACE,IAAI,EAAE;oBACJ,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;iBACtC;aACF;YACD;gBACE,QAAQ,EAAE,uBAAuB;aAClC;SACF,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,aAAa,IAAC,IAAI,EAAE,IAAI,GAAI,CAAC,CAAA;QAE5D,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;KAM/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {TokenizedText} from './TokenizedText.js'\nimport {renderString} from '../../ui.js'\nimport {unstyled} from '../../../../output.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('TokenizedText', async () => {\n test('renders arrays of items separated by spaces', async () => {\n const item = [\n 'Run',\n {\n command: 'cd verification-app',\n },\n {\n link: {\n url: 'https://example.com',\n label: 'Example',\n },\n },\n {\n char: '!',\n },\n {\n userInput: 'my-app',\n },\n {\n list: {\n items: ['Item 1', 'Item 2', 'Item 3'],\n },\n },\n {\n filePath: 'src/this/is/a/test.js',\n },\n ]\n\n const {output} = renderString(<TokenizedText item={item} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"Run \\`cd verification-app\\` Example ( https://example.com )! my-app\n • Item 1\n • Item 2\n • Item 3\n \\\\\"src/this/is/a/test.js\\\\\"\"\n `)\n })\n})\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useApp } from 'ink';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
export default function useEffectAsync(asyncFunction, { onFulfilled = () => { }, onRejected = () => { } }) {
|
|
4
|
+
const { exit: unmountInk } = useApp();
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
asyncFunction()
|
|
7
|
+
.then(() => {
|
|
8
|
+
onFulfilled();
|
|
9
|
+
unmountInk();
|
|
10
|
+
})
|
|
11
|
+
.catch((error) => {
|
|
12
|
+
onRejected(error);
|
|
13
|
+
unmountInk(error);
|
|
14
|
+
});
|
|
15
|
+
}, []);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=use-async-and-unmount.js.map
|
|
@@ -0,0 +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,MAAM,EAAC,MAAM,KAAK,CAAA;AAC1B,OAAO,EAAC,SAAS,EAAC,MAAM,OAAO,CAAA;AAO/B,MAAM,CAAC,OAAO,UAAU,cAAc,CACpC,aAAqC,EACrC,EAAC,WAAW,GAAG,GAAG,EAAE,GAAE,CAAC,EAAE,UAAU,GAAG,GAAG,EAAE,GAAE,CAAC,EAAU;IAExD,MAAM,EAAC,IAAI,EAAE,UAAU,EAAC,GAAG,MAAM,EAAE,CAAA;IAEnC,SAAS,CAAC,GAAG,EAAE;QACb,aAAa,EAAE;aACZ,IAAI,CAAC,GAAG,EAAE;YACT,WAAW,EAAE,CAAA;YACb,UAAU,EAAE,CAAA;QACd,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,UAAU,CAAC,KAAK,CAAC,CAAA;YACjB,UAAU,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;IACN,CAAC,EAAE,EAAE,CAAC,CAAA;AACR,CAAC","sourcesContent":["import {useApp} from 'ink'\nimport {useEffect} from 'react'\n\ninterface Options {\n onFulfilled?: () => unknown\n onRejected?: (error: Error) => void\n}\n\nexport default function useEffectAsync(\n asyncFunction: () => Promise<unknown>,\n {onFulfilled = () => {}, onRejected = () => {}}: Options,\n) {\n const {exit: unmountInk} = useApp()\n\n useEffect(() => {\n asyncFunction()\n .then(() => {\n onFulfilled()\n unmountInk()\n })\n .catch((error) => {\n onRejected(error)\n unmountInk(error)\n })\n }, [])\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useStdout } from 'ink';
|
|
2
|
+
const MIN_WIDTH = 80;
|
|
3
|
+
export default function useLayout() {
|
|
4
|
+
const { stdout } = useStdout();
|
|
5
|
+
const fullWidth = stdout?.columns ?? MIN_WIDTH;
|
|
6
|
+
const twoThirdsOfWidth = Math.floor((fullWidth / 3) * 2);
|
|
7
|
+
let width;
|
|
8
|
+
if (fullWidth <= MIN_WIDTH) {
|
|
9
|
+
width = fullWidth;
|
|
10
|
+
}
|
|
11
|
+
else if (twoThirdsOfWidth < MIN_WIDTH) {
|
|
12
|
+
width = MIN_WIDTH;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
width = twoThirdsOfWidth;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
width,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=use-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-layout.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/hooks/use-layout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,KAAK,CAAA;AAE7B,MAAM,SAAS,GAAG,EAAE,CAAA;AAEpB,MAAM,CAAC,OAAO,UAAU,SAAS;IAC/B,MAAM,EAAC,MAAM,EAAC,GAAG,SAAS,EAAE,CAAA;IAE5B,MAAM,SAAS,GAAG,MAAM,EAAE,OAAO,IAAI,SAAS,CAAA;IAC9C,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACxD,IAAI,KAAK,CAAA;IAET,IAAI,SAAS,IAAI,SAAS,EAAE;QAC1B,KAAK,GAAG,SAAS,CAAA;KAClB;SAAM,IAAI,gBAAgB,GAAG,SAAS,EAAE;QACvC,KAAK,GAAG,SAAS,CAAA;KAClB;SAAM;QACL,KAAK,GAAG,gBAAgB,CAAA;KACzB;IAED,OAAO;QACL,KAAK;KACN,CAAA;AACH,CAAC","sourcesContent":["import {useStdout} from 'ink'\n\nconst MIN_WIDTH = 80\n\nexport default function useLayout() {\n const {stdout} = useStdout()\n\n const fullWidth = stdout?.columns ?? MIN_WIDTH\n const twoThirdsOfWidth = Math.floor((fullWidth / 3) * 2)\n let width\n\n if (fullWidth <= MIN_WIDTH) {\n width = fullWidth\n } else if (twoThirdsOfWidth < MIN_WIDTH) {\n width = MIN_WIDTH\n } else {\n width = twoThirdsOfWidth\n }\n\n return {\n width,\n }\n}\n"]}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { Logger, LogLevel } from '../../output.js';
|
|
2
3
|
import { Props as PromptProps } from '../../private/node/ui/components/Prompt.js';
|
|
3
4
|
import { ReactElement } from 'react';
|
|
4
5
|
import { RenderOptions } from 'ink';
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
5
7
|
export declare function renderOnce(element: JSX.Element, logLevel?: LogLevel, logger?: Logger): void;
|
|
6
8
|
export declare function render(element: JSX.Element, options?: RenderOptions): Promise<void>;
|
|
7
9
|
interface Instance {
|
|
8
10
|
output: string | undefined;
|
|
9
11
|
unmount: () => void;
|
|
10
12
|
}
|
|
13
|
+
export declare class OutputStream extends EventEmitter {
|
|
14
|
+
columns: number;
|
|
15
|
+
private _lastFrame?;
|
|
16
|
+
constructor(options: {
|
|
17
|
+
columns: number;
|
|
18
|
+
});
|
|
19
|
+
write: (frame: string) => void;
|
|
20
|
+
lastFrame: () => string | undefined;
|
|
21
|
+
}
|
|
11
22
|
export declare const renderString: (element: ReactElement) => Instance;
|
|
12
23
|
export declare function prompt<T>(options: Omit<PromptProps<T>, 'onChoose'>): Promise<T>;
|
|
13
24
|
export {};
|
package/dist/private/node/ui.js
CHANGED
|
@@ -18,7 +18,7 @@ export function render(element, options) {
|
|
|
18
18
|
return waitUntilExit();
|
|
19
19
|
}
|
|
20
20
|
const TEST_TERMINAL_WIDTH = 80;
|
|
21
|
-
class OutputStream extends EventEmitter {
|
|
21
|
+
export class OutputStream extends EventEmitter {
|
|
22
22
|
constructor(options) {
|
|
23
23
|
super();
|
|
24
24
|
this.write = (frame) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/private/node/ui.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,4BAA4B,CAAA;AACrD,OAAO,EAAC,UAAU,EAAE,UAAU,EAAoB,sBAAsB,EAAC,MAAM,iBAAiB,CAAA;AAChG,OAAO,MAA8B,MAAM,4CAA4C,CAAA;AACvF,OAAO,KAAqB,MAAM,OAAO,CAAA;AACzC,OAAO,EAAC,MAAM,IAAI,SAAS,EAAgB,MAAM,KAAK,CAAA;AACtD,OAAO,EAAC,YAAY,EAAC,MAAM,QAAQ,CAAA;AAEnC,MAAM,UAAU,UAAU,CAAC,OAAoB,EAAE,WAAqB,MAAM,EAAE,SAAiB,UAAU;IACvG,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;IAE/C,IAAI,MAAM,EAAE;QACV,IAAI,UAAU,EAAE;YAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC9C,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;KACjD;IAED,OAAO,EAAE,CAAA;AACX,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,OAAoB,EAAE,OAAuB;IAClE,MAAM,EAAC,aAAa,EAAC,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACnD,OAAO,aAAa,EAAE,CAAA;AACxB,CAAC;AAOD,MAAM,mBAAmB,GAAG,EAAE,CAAA;AAC9B,MAAM,YAAa,SAAQ,YAAY;
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/private/node/ui.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,4BAA4B,CAAA;AACrD,OAAO,EAAC,UAAU,EAAE,UAAU,EAAoB,sBAAsB,EAAC,MAAM,iBAAiB,CAAA;AAChG,OAAO,MAA8B,MAAM,4CAA4C,CAAA;AACvF,OAAO,KAAqB,MAAM,OAAO,CAAA;AACzC,OAAO,EAAC,MAAM,IAAI,SAAS,EAAgB,MAAM,KAAK,CAAA;AACtD,OAAO,EAAC,YAAY,EAAC,MAAM,QAAQ,CAAA;AAEnC,MAAM,UAAU,UAAU,CAAC,OAAoB,EAAE,WAAqB,MAAM,EAAE,SAAiB,UAAU;IACvG,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;IAE/C,IAAI,MAAM,EAAE;QACV,IAAI,UAAU,EAAE;YAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC9C,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;KACjD;IAED,OAAO,EAAE,CAAA;AACX,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,OAAoB,EAAE,OAAuB;IAClE,MAAM,EAAC,aAAa,EAAC,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACnD,OAAO,aAAa,EAAE,CAAA;AACxB,CAAC;AAOD,MAAM,mBAAmB,GAAG,EAAE,CAAA;AAC9B,MAAM,OAAO,YAAa,SAAQ,YAAY;IAI5C,YAAY,OAA0B;QACpC,KAAK,EAAE,CAAA;QAIT,UAAK,GAAG,CAAC,KAAa,EAAE,EAAE;YACxB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAA;QACzB,CAAC,CAAA;QAED,cAAS,GAAG,GAAG,EAAE;YACf,OAAO,IAAI,CAAC,UAAU,CAAA;QACxB,CAAC,CAAA;QATC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;IAChC,CAAC;CASF;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAqB,EAAY,EAAE;IAC9D,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAC,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAC,CAAC,CAAA;IACvG,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAC,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAC,CAAC,CAAA;IAEvG,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,EAAE;QAClC,8DAA8D;QAC9D,MAAM,EAAE,MAAa;QACrB,8DAA8D;QAC9D,MAAM,EAAE,MAAa;QACrB,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,KAAK;KACpB,CAAC,CAAA;IAEF,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE;QAC1B,OAAO,EAAE,QAAQ,CAAC,OAAO;KAC1B,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAI,OAAyC;IACvE,IAAI,eAAe,GAAwB,GAAG,EAAE,GAAE,CAAC,CAAA;IAEnD,MAAM,eAAe,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,EAAE;QACjD,eAAe,GAAG,OAAO,CAAA;IAC3B,CAAC,CAAC,CAAA;IAEF,MAAM,KAAK,GAAG;QACZ,GAAG,OAAO;QACV,QAAQ,EAAE,eAAe;KAC1B,CAAA;IAED,MAAM,MAAM,CAAC,oBAAC,MAAM,OAAK,KAAK,GAAI,EAAE,EAAC,WAAW,EAAE,KAAK,EAAC,CAAC,CAAA;IAEzD,OAAO,eAAe,CAAA;AACxB,CAAC","sourcesContent":["import {isUnitTest} from '../../environment/local.js'\nimport {collectLog, consoleLog, Logger, LogLevel, outputWhereAppropriate} from '../../output.js'\nimport Prompt, {Props as PromptProps} from '../../private/node/ui/components/Prompt.js'\nimport React, {ReactElement} from 'react'\nimport {render as inkRender, RenderOptions} from 'ink'\nimport {EventEmitter} from 'events'\n\nexport function renderOnce(element: JSX.Element, logLevel: LogLevel = 'info', logger: Logger = consoleLog) {\n const {output, unmount} = renderString(element)\n\n if (output) {\n if (isUnitTest()) collectLog(logLevel, output)\n outputWhereAppropriate(logLevel, logger, output)\n }\n\n unmount()\n}\n\nexport function render(element: JSX.Element, options?: RenderOptions) {\n const {waitUntilExit} = inkRender(element, options)\n return waitUntilExit()\n}\n\ninterface Instance {\n output: string | undefined\n unmount: () => void\n}\n\nconst TEST_TERMINAL_WIDTH = 80\nexport class OutputStream extends EventEmitter {\n columns: number\n private _lastFrame?: string\n\n constructor(options: {columns: number}) {\n super()\n this.columns = options.columns\n }\n\n write = (frame: string) => {\n this._lastFrame = frame\n }\n\n lastFrame = () => {\n return this._lastFrame\n }\n}\n\nexport const renderString = (element: ReactElement): Instance => {\n const stdout = new OutputStream({columns: isUnitTest() ? TEST_TERMINAL_WIDTH : process.stdout.columns})\n const stderr = new OutputStream({columns: isUnitTest() ? TEST_TERMINAL_WIDTH : process.stderr.columns})\n\n const instance = inkRender(element, {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stdout: stdout as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stderr: stderr as any,\n debug: true,\n exitOnCtrlC: false,\n patchConsole: false,\n })\n\n return {\n output: stdout.lastFrame(),\n unmount: instance.unmount,\n }\n}\n\nexport async function prompt<T>(options: Omit<PromptProps<T>, 'onChoose'>) {\n let onChooseResolve: (choice: T) => void = () => {}\n\n const onChoosePromise = new Promise<T>((resolve) => {\n onChooseResolve = resolve\n })\n\n const props = {\n ...options,\n onChoose: onChooseResolve,\n }\n\n await render(<Prompt {...props} />, {exitOnCtrlC: false})\n\n return onChoosePromise\n}\n"]}
|
package/dist/public/node/ui.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { OutputProcess } from '../../output.js';
|
|
|
2
2
|
import { Fatal } from '../../error.js';
|
|
3
3
|
import { AlertProps } from '../../private/node/ui/components/Alert.js';
|
|
4
4
|
import { Props as PromptProps } from '../../private/node/ui/components/Prompt.js';
|
|
5
|
+
import { Task } from '../../private/node/ui/components/Tasks.js';
|
|
5
6
|
import { AbortController } from 'abort-controller';
|
|
6
7
|
import { RenderOptions } from 'ink';
|
|
7
8
|
interface RenderConcurrentOptions {
|
|
@@ -181,4 +182,8 @@ interface ConfirmationProps {
|
|
|
181
182
|
* navigate with arrows, enter to select
|
|
182
183
|
*/
|
|
183
184
|
export declare function renderConfirmation({ question, infoTable }: ConfirmationProps): Promise<boolean>;
|
|
185
|
+
/**
|
|
186
|
+
* Runs async tasks and displays their progress to the console.
|
|
187
|
+
*/
|
|
188
|
+
export declare function renderTasks(tasks: Task[]): Promise<void>;
|
|
184
189
|
export {};
|
package/dist/public/node/ui.js
CHANGED
|
@@ -3,6 +3,7 @@ import { consoleError } from '../../output.js';
|
|
|
3
3
|
import { prompt, render, renderOnce } from '../../private/node/ui.js';
|
|
4
4
|
import { alert } from '../../private/node/ui/alert.js';
|
|
5
5
|
import { FatalError } from '../../private/node/ui/components/FatalError.js';
|
|
6
|
+
import Tasks from '../../private/node/ui/components/Tasks.js';
|
|
6
7
|
import React from 'react';
|
|
7
8
|
import { AbortController } from 'abort-controller';
|
|
8
9
|
/**
|
|
@@ -197,4 +198,10 @@ export async function renderConfirmation({ question, infoTable }) {
|
|
|
197
198
|
];
|
|
198
199
|
return prompt({ message: question, choices, infoTable });
|
|
199
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Runs async tasks and displays their progress to the console.
|
|
203
|
+
*/
|
|
204
|
+
export function renderTasks(tasks) {
|
|
205
|
+
return render(React.createElement(Tasks, { tasks: tasks }));
|
|
206
|
+
}
|
|
200
207
|
//# sourceMappingURL=ui.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/public/node/ui.tsx"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,sDAAsD,CAAA;AACnF,OAAO,EAAC,YAAY,EAAgB,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AAEnE,OAAO,EAAC,KAAK,EAAC,MAAM,gCAAgC,CAAA;AAEpD,OAAO,EAAC,UAAU,EAAC,MAAM,gDAAgD,CAAA;AAEzE,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAA;AAUhD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACrC,SAAS,EACT,eAAe,EACf,cAAc,GAAG,IAAI,EACrB,aAAa,GAAG,EAAE,GACM;IACxB,OAAO,MAAM,CACX,oBAAC,gBAAgB,IACf,SAAS,EAAE,SAAS,EACpB,eAAe,EAAE,eAAe,IAAI,IAAI,eAAe,EAAE,EACzD,cAAc,EAAE,cAAc,GAC9B,EACF,aAAa,CACd,CAAA;AACH,CAAC;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,UAAU,CAAC,OAA2B;IACpD,OAAO,KAAK,CAAC,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAA;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,aAAa,CAAC,OAA2B;IACvD,OAAO,KAAK,CAAC,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAC,CAAC,CAAA;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,aAAa,CAAC,OAA2B;IACvD,OAAO,KAAK,CAAC,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAC,CAAC,CAAA;AAC7C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAY;IAC3C,OAAO,UAAU,CAAC,oBAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;AACxE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,OAAyC;IAC7E,OAAO,MAAM,CAAC,OAAO,CAAC,CAAA;AACxB,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAC,QAAQ,EAAE,SAAS,EAAoB;IAC/E,MAAM,OAAO,GAAG;QACd;YACE,KAAK,EAAE,cAAc;YACrB,KAAK,EAAE,IAAI;YACX,GAAG,EAAE,GAAG;SACT;QACD;YACE,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,KAAK;YACZ,GAAG,EAAE,GAAG;SACT;KACF,CAAA;IAED,OAAO,MAAM,CAAC,EAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAC,CAAC,CAAA;AACxD,CAAC","sourcesContent":["import ConcurrentOutput from '../../private/node/ui/components/ConcurrentOutput.js'\nimport {consoleError, OutputProcess} from '../../output.js'\nimport {prompt, render, renderOnce} from '../../private/node/ui.js'\nimport {Fatal} from '../../error.js'\nimport {alert} from '../../private/node/ui/alert.js'\nimport {AlertProps} from '../../private/node/ui/components/Alert.js'\nimport {FatalError} from '../../private/node/ui/components/FatalError.js'\nimport Prompt, {Props as PromptProps} from '../../private/node/ui/components/Prompt.js'\nimport React from 'react'\nimport {AbortController} from 'abort-controller'\nimport {RenderOptions} from 'ink'\n\ninterface RenderConcurrentOptions {\n processes: OutputProcess[]\n abortController?: AbortController\n showTimestamps?: boolean\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders output from concurrent processes to the terminal with {@link ConcurrentOutput}.\n */\nexport async function renderConcurrent({\n processes,\n abortController,\n showTimestamps = true,\n renderOptions = {},\n}: RenderConcurrentOptions) {\n return render(\n <ConcurrentOutput\n processes={processes}\n abortController={abortController ?? new AbortController()}\n showTimestamps={showTimestamps}\n />,\n renderOptions,\n )\n}\n\ntype RenderAlertOptions = Omit<AlertProps, 'type'>\n\n/**\n * Renders an information banner to the console.\n *\n * Basic:\n *\n * ```\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ Body │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderInfo(options: RenderAlertOptions) {\n return alert({...options, type: 'info'})\n}\n\n/**\n * Renders a success banner to the console.\n *\n * Basic:\n *\n * ```\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderSuccess(options: RenderAlertOptions) {\n return alert({...options, type: 'success'})\n}\n\n/**\n * Renders a warning banner to the console.\n *\n * Basic:\n *\n * ```\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderWarning(options: RenderAlertOptions) {\n return alert({...options, type: 'warning'})\n}\n\n/**\n * Renders a Fatal error to the console inside a banner.\n *\n * ```\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Couldn't connect to the Shopify Partner Dashboard. │\n * │ │\n * │ Check your internet connection and try again. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderFatalError(error: Fatal) {\n return renderOnce(<FatalError error={error} />, 'error', consoleError)\n}\n\n/**\n * Renders a select prompt to the console.\n *\n * ? Associate your project with the org Castile Ventures?\n *\n * Add: • new-ext\n * Remove: • integrated-demand-ext\n * • order-discount\n\n * \\> (f) first\n * (s) second\n * (3) third\n * (4) fourth\n * (5) seventh\n * (6) tenth\n\n * Automations\n * (7) fifth\n * (8) sixth\n\n * Merchant Admin\n * (9) eighth\n * (10) ninth\n\n * navigate with arrows, enter to select\n */\nexport async function renderPrompt<T>(options: Omit<PromptProps<T>, 'onChoose'>) {\n return prompt(options)\n}\n\ninterface ConfirmationProps {\n question: string\n infoTable?: PromptProps<boolean>['infoTable']\n}\n\n/**\n * Renders a confirmation prompt to the console.\n *\n * ? Push the following changes to your Partners Dashboard?\n * \\> (y) Yes, confirm\n * (c) Cancel\n *\n * navigate with arrows, enter to select\n */\nexport async function renderConfirmation({question, infoTable}: ConfirmationProps) {\n const choices = [\n {\n label: 'Yes, confirm',\n value: true,\n key: 'y',\n },\n {\n label: 'Cancel',\n value: false,\n key: 'c',\n },\n ]\n\n return prompt({message: question, choices, infoTable})\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/public/node/ui.tsx"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,sDAAsD,CAAA;AACnF,OAAO,EAAC,YAAY,EAAgB,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AAEnE,OAAO,EAAC,KAAK,EAAC,MAAM,gCAAgC,CAAA;AAEpD,OAAO,EAAC,UAAU,EAAC,MAAM,gDAAgD,CAAA;AAEzE,OAAO,KAAa,MAAM,2CAA2C,CAAA;AACrE,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAA;AAUhD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACrC,SAAS,EACT,eAAe,EACf,cAAc,GAAG,IAAI,EACrB,aAAa,GAAG,EAAE,GACM;IACxB,OAAO,MAAM,CACX,oBAAC,gBAAgB,IACf,SAAS,EAAE,SAAS,EACpB,eAAe,EAAE,eAAe,IAAI,IAAI,eAAe,EAAE,EACzD,cAAc,EAAE,cAAc,GAC9B,EACF,aAAa,CACd,CAAA;AACH,CAAC;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,UAAU,CAAC,OAA2B;IACpD,OAAO,KAAK,CAAC,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAA;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,aAAa,CAAC,OAA2B;IACvD,OAAO,KAAK,CAAC,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAC,CAAC,CAAA;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,aAAa,CAAC,OAA2B;IACvD,OAAO,KAAK,CAAC,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAC,CAAC,CAAA;AAC7C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAY;IAC3C,OAAO,UAAU,CAAC,oBAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;AACxE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,OAAyC;IAC7E,OAAO,MAAM,CAAC,OAAO,CAAC,CAAA;AACxB,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAC,QAAQ,EAAE,SAAS,EAAoB;IAC/E,MAAM,OAAO,GAAG;QACd;YACE,KAAK,EAAE,cAAc;YACrB,KAAK,EAAE,IAAI;YACX,GAAG,EAAE,GAAG;SACT;QACD;YACE,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,KAAK;YACZ,GAAG,EAAE,GAAG;SACT;KACF,CAAA;IAED,OAAO,MAAM,CAAC,EAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAC,CAAC,CAAA;AACxD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,MAAM,CAAC,oBAAC,KAAK,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC,CAAA;AACxC,CAAC","sourcesContent":["import ConcurrentOutput from '../../private/node/ui/components/ConcurrentOutput.js'\nimport {consoleError, OutputProcess} from '../../output.js'\nimport {prompt, render, renderOnce} from '../../private/node/ui.js'\nimport {Fatal} from '../../error.js'\nimport {alert} from '../../private/node/ui/alert.js'\nimport {AlertProps} from '../../private/node/ui/components/Alert.js'\nimport {FatalError} from '../../private/node/ui/components/FatalError.js'\nimport {Props as PromptProps} from '../../private/node/ui/components/Prompt.js'\nimport Tasks, {Task} from '../../private/node/ui/components/Tasks.js'\nimport React from 'react'\nimport {AbortController} from 'abort-controller'\nimport {RenderOptions} from 'ink'\n\ninterface RenderConcurrentOptions {\n processes: OutputProcess[]\n abortController?: AbortController\n showTimestamps?: boolean\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders output from concurrent processes to the terminal with {@link ConcurrentOutput}.\n */\nexport async function renderConcurrent({\n processes,\n abortController,\n showTimestamps = true,\n renderOptions = {},\n}: RenderConcurrentOptions) {\n return render(\n <ConcurrentOutput\n processes={processes}\n abortController={abortController ?? new AbortController()}\n showTimestamps={showTimestamps}\n />,\n renderOptions,\n )\n}\n\ntype RenderAlertOptions = Omit<AlertProps, 'type'>\n\n/**\n * Renders an information banner to the console.\n *\n * Basic:\n *\n * ```\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ Body │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderInfo(options: RenderAlertOptions) {\n return alert({...options, type: 'info'})\n}\n\n/**\n * Renders a success banner to the console.\n *\n * Basic:\n *\n * ```\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderSuccess(options: RenderAlertOptions) {\n return alert({...options, type: 'success'})\n}\n\n/**\n * Renders a warning banner to the console.\n *\n * Basic:\n *\n * ```\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderWarning(options: RenderAlertOptions) {\n return alert({...options, type: 'warning'})\n}\n\n/**\n * Renders a Fatal error to the console inside a banner.\n *\n * ```\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Couldn't connect to the Shopify Partner Dashboard. │\n * │ │\n * │ Check your internet connection and try again. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderFatalError(error: Fatal) {\n return renderOnce(<FatalError error={error} />, 'error', consoleError)\n}\n\n/**\n * Renders a select prompt to the console.\n *\n * ? Associate your project with the org Castile Ventures?\n *\n * Add: • new-ext\n * Remove: • integrated-demand-ext\n * • order-discount\n\n * \\> (f) first\n * (s) second\n * (3) third\n * (4) fourth\n * (5) seventh\n * (6) tenth\n\n * Automations\n * (7) fifth\n * (8) sixth\n\n * Merchant Admin\n * (9) eighth\n * (10) ninth\n\n * navigate with arrows, enter to select\n */\nexport async function renderPrompt<T>(options: Omit<PromptProps<T>, 'onChoose'>) {\n return prompt(options)\n}\n\ninterface ConfirmationProps {\n question: string\n infoTable?: PromptProps<boolean>['infoTable']\n}\n\n/**\n * Renders a confirmation prompt to the console.\n *\n * ? Push the following changes to your Partners Dashboard?\n * \\> (y) Yes, confirm\n * (c) Cancel\n *\n * navigate with arrows, enter to select\n */\nexport async function renderConfirmation({question, infoTable}: ConfirmationProps) {\n const choices = [\n {\n label: 'Yes, confirm',\n value: true,\n key: 'y',\n },\n {\n label: 'Cancel',\n value: false,\n key: 'c',\n },\n ]\n\n return prompt({message: question, choices, infoTable})\n}\n\n/**\n * Runs async tasks and displays their progress to the console.\n */\nexport function renderTasks(tasks: Task[]) {\n return render(<Tasks tasks={tasks} />)\n}\n"]}
|
package/dist/session.js
CHANGED
|
@@ -2,7 +2,7 @@ import { applicationId } from './session/identity.js';
|
|
|
2
2
|
import { Abort, Bug } from './error.js';
|
|
3
3
|
import { validateSession } from './session/validate.js';
|
|
4
4
|
import { allDefaultScopes, apiScopes } from './session/scopes.js';
|
|
5
|
-
import { identity as identityFqdn, partners as partnersFqdn } from './environment/fqdn.js';
|
|
5
|
+
import { identity as identityFqdn, normalizeStoreName, partners as partnersFqdn } from './environment/fqdn.js';
|
|
6
6
|
import { open } from './system.js';
|
|
7
7
|
import { exchangeAccessForApplicationTokens, exchangeCodeForAccessToken, exchangeCustomPartnerToken, refreshAccessToken, InvalidGrantError, InvalidRequestError, } from './session/exchange.js';
|
|
8
8
|
import { content, token, debug } from './output.js';
|
|
@@ -10,7 +10,6 @@ import { keypress } from './ui.js';
|
|
|
10
10
|
import { authorize } from './session/authorize.js';
|
|
11
11
|
import * as secureStore from './session/store.js';
|
|
12
12
|
import constants from './constants.js';
|
|
13
|
-
import { normalizeStoreName } from './string.js';
|
|
14
13
|
import * as output from './output.js';
|
|
15
14
|
import { partners } from './api.js';
|
|
16
15
|
import { RequestClientError } from './api/common.js';
|
|
@@ -90,7 +89,7 @@ export async function ensureAuthenticatedThemes(store, password, scopes = [], fo
|
|
|
90
89
|
${token.json(scopes)}
|
|
91
90
|
`);
|
|
92
91
|
if (password)
|
|
93
|
-
return { token: password, storeFqdn: normalizeStoreName(store) };
|
|
92
|
+
return { token: password, storeFqdn: await normalizeStoreName(store) };
|
|
94
93
|
return ensureAuthenticatedAdmin(store, scopes, forceRefresh);
|
|
95
94
|
}
|
|
96
95
|
/**
|
|
@@ -100,8 +99,12 @@ ${token.json(scopes)}
|
|
|
100
99
|
*/
|
|
101
100
|
export async function ensureAuthenticated(applications, env = process.env, forceRefresh = false) {
|
|
102
101
|
const fqdn = await identityFqdn();
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
const previousStoreFqdn = applications.adminApi?.storeFqdn;
|
|
103
|
+
if (previousStoreFqdn) {
|
|
104
|
+
const normalizedStoreName = await normalizeStoreName(previousStoreFqdn);
|
|
105
|
+
if (previousStoreFqdn === applications.adminApi?.storeFqdn) {
|
|
106
|
+
applications.adminApi.storeFqdn = normalizedStoreName;
|
|
107
|
+
}
|
|
105
108
|
}
|
|
106
109
|
const currentSession = (await secureStore.fetch()) || {};
|
|
107
110
|
const fqdnSession = currentSession[fqdn];
|