@shopify/cli-kit 3.23.0 → 3.25.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.
Files changed (110) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +1 -1
  3. package/dist/api/graphql/functions/app_function_set.d.ts +1 -0
  4. package/dist/api/graphql/functions/app_function_set.js +2 -0
  5. package/dist/api/graphql/functions/app_function_set.js.map +1 -1
  6. package/dist/error.d.ts +9 -7
  7. package/dist/error.js +5 -4
  8. package/dist/error.js.map +1 -1
  9. package/dist/index.d.ts +0 -1
  10. package/dist/index.js +0 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/output.d.ts +1 -0
  13. package/dist/output.js +2 -15
  14. package/dist/output.js.map +1 -1
  15. package/dist/path.d.ts +0 -1
  16. package/dist/plugins.d.ts +3 -3
  17. package/dist/plugins.js +1 -1
  18. package/dist/plugins.js.map +1 -1
  19. package/dist/private/node/ui/components/Alert.d.ts +5 -5
  20. package/dist/private/node/ui/components/Alert.js +3 -3
  21. package/dist/private/node/ui/components/Alert.js.map +1 -1
  22. package/dist/private/node/ui/components/Alert.test.d.ts +1 -0
  23. package/dist/private/node/ui/components/Alert.test.js +95 -0
  24. package/dist/private/node/ui/components/Alert.test.js.map +1 -0
  25. package/dist/private/node/ui/components/Banner.d.ts +1 -0
  26. package/dist/private/node/ui/components/Banner.js +12 -13
  27. package/dist/private/node/ui/components/Banner.js.map +1 -1
  28. package/dist/private/node/ui/components/Banner.test.d.ts +1 -0
  29. package/dist/private/node/ui/components/Banner.test.js +52 -0
  30. package/dist/private/node/ui/components/Banner.test.js.map +1 -0
  31. package/dist/private/node/ui/components/Command.test.d.ts +1 -0
  32. package/dist/private/node/ui/components/Command.test.js +11 -0
  33. package/dist/private/node/ui/components/Command.test.js.map +1 -0
  34. package/dist/private/node/ui/components/ConcurrentOutput.js +11 -17
  35. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  36. package/dist/private/node/ui/components/FatalError.js +5 -2
  37. package/dist/private/node/ui/components/FatalError.js.map +1 -1
  38. package/dist/private/node/ui/components/FatalError.test.d.ts +1 -0
  39. package/dist/private/node/ui/components/FatalError.test.js +119 -0
  40. package/dist/private/node/ui/components/FatalError.test.js.map +1 -0
  41. package/dist/private/node/ui/components/FilePath.d.ts +9 -0
  42. package/dist/private/node/ui/components/FilePath.js +13 -0
  43. package/dist/private/node/ui/components/FilePath.js.map +1 -0
  44. package/dist/private/node/ui/components/FilePath.test.d.ts +1 -0
  45. package/dist/private/node/ui/components/FilePath.test.js +11 -0
  46. package/dist/private/node/ui/components/FilePath.test.js.map +1 -0
  47. package/dist/private/node/ui/components/Link.js +6 -5
  48. package/dist/private/node/ui/components/Link.js.map +1 -1
  49. package/dist/private/node/ui/components/Link.test.d.ts +1 -0
  50. package/dist/private/node/ui/components/Link.test.js +22 -0
  51. package/dist/private/node/ui/components/Link.test.js.map +1 -0
  52. package/dist/private/node/ui/components/List.d.ts +3 -3
  53. package/dist/private/node/ui/components/List.js +2 -2
  54. package/dist/private/node/ui/components/List.js.map +1 -1
  55. package/dist/private/node/ui/components/List.test.d.ts +1 -0
  56. package/dist/private/node/ui/components/List.test.js +34 -0
  57. package/dist/private/node/ui/components/List.test.js.map +1 -0
  58. package/dist/private/node/ui/components/TokenizedText.d.ts +18 -3
  59. package/dist/private/node/ui/components/TokenizedText.js +49 -5
  60. package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
  61. package/dist/private/node/ui/components/TokenizedText.test.d.ts +1 -0
  62. package/dist/private/node/ui/components/TokenizedText.test.js +44 -0
  63. package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -0
  64. package/dist/private/node/ui/components/UserInput.d.ts +10 -0
  65. package/dist/private/node/ui/components/UserInput.js +11 -0
  66. package/dist/private/node/ui/components/UserInput.js.map +1 -0
  67. package/dist/private/node/ui/components/UserInput.test.d.ts +1 -0
  68. package/dist/private/node/ui/components/UserInput.test.js +11 -0
  69. package/dist/private/node/ui/components/UserInput.test.js.map +1 -0
  70. package/dist/private/node/ui/error.d.ts +0 -2
  71. package/dist/private/node/ui/error.js +0 -4
  72. package/dist/private/node/ui/error.js.map +1 -1
  73. package/dist/private/node/ui.d.ts +2 -1
  74. package/dist/private/node/ui.js +3 -2
  75. package/dist/private/node/ui.js.map +1 -1
  76. package/dist/public/common/string.d.ts +4 -2
  77. package/dist/public/common/string.js +54 -5
  78. package/dist/public/common/string.js.map +1 -1
  79. package/dist/public/node/fs.d.ts +3 -0
  80. package/dist/public/node/fs.js +2 -2
  81. package/dist/public/node/fs.js.map +1 -1
  82. package/dist/public/node/github.d.ts +50 -0
  83. package/dist/{github.js → public/node/github.js} +29 -14
  84. package/dist/public/node/github.js.map +1 -0
  85. package/dist/public/node/node-package-manager.d.ts +4 -1
  86. package/dist/public/node/node-package-manager.js +3 -1
  87. package/dist/public/node/node-package-manager.js.map +1 -1
  88. package/dist/public/node/plugins/tunnel.d.ts +1 -1
  89. package/dist/public/node/plugins/tunnel.js +1 -1
  90. package/dist/public/node/plugins/tunnel.js.map +1 -1
  91. package/dist/public/{common → node}/result.d.ts +12 -6
  92. package/dist/public/{common → node}/result.js +28 -5
  93. package/dist/public/node/result.js.map +1 -0
  94. package/dist/public/node/ui.d.ts +3 -16
  95. package/dist/public/node/ui.js +3 -20
  96. package/dist/public/node/ui.js.map +1 -1
  97. package/dist/session/exchange.d.ts +1 -1
  98. package/dist/session/exchange.js +4 -4
  99. package/dist/session/exchange.js.map +1 -1
  100. package/dist/tsconfig.tsbuildinfo +1 -1
  101. package/dist/ui.d.ts +13 -2
  102. package/dist/ui.js.map +1 -1
  103. package/dist/version.d.ts +0 -1
  104. package/package.json +56 -55
  105. package/dist/github.d.ts +0 -33
  106. package/dist/github.js.map +0 -1
  107. package/dist/private/node/ui/components/Error.d.ts +0 -8
  108. package/dist/private/node/ui/components/Error.js +0 -13
  109. package/dist/private/node/ui/components/Error.js.map +0 -1
  110. package/dist/public/common/result.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Alert.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Alert.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAA;AAChC,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,OAAO,EAAE,KAAK,IAAI,EAAE;IAC3B,IAAI,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAC,EAAE,iCAAiC,CAAC;YACpE,IAAI,EAAE,CAAC,sCAAsC,EAAE,EAAC,QAAQ,EAAE,MAAM,EAAC,EAAE,SAAS,CAAC;YAC7E,SAAS,EAAE;gBACT;oBACE,KAAK;oBACL;wBACE,OAAO,EAAE,oBAAoB;qBAC9B;iBACF;gBACD;oBACE,8BAA8B;oBAC9B;wBACE,OAAO,EAAE,aAAa;qBACvB;iBACF;gBACD;oBACE,wBAAwB;oBACxB;wBACE,OAAO,EAAE,wBAAwB;qBAClC;iBACF;aACF;YACD,SAAS,EAAE;gBACT;oBACE,KAAK;oBACL;wBACE,OAAO,EAAE,kBAAkB;qBAC5B;iBACF;gBACD;oBACE,iCAAiC;oBACjC,qDAAqD;oBACrD;wBACE,IAAI,EAAE;4BACJ,KAAK,EAAE,UAAU;4BACjB,GAAG,EAAE,qBAAqB;yBAC3B;qBACF;iBACF;aACF;YACD,IAAI,EAAE;gBACJ,KAAK,EAAE,MAAM;gBACb,GAAG,EAAE,qBAAqB;aAC3B;SACF,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,KAAK,IAAC,IAAI,EAAC,MAAM,KAAK,OAAO,GAAI,CAAC,CAAA;QAEjE,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;;;;;;;;;KAsB/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,OAAO;SAClB,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,KAAK,IAAC,IAAI,EAAC,MAAM,KAAK,OAAO,GAAI,CAAC,CAAA;QAEjE,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;KAQ/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {Alert} from './Alert.js'\nimport {renderString} from '../../ui.js'\nimport {unstyled} from '../../../../output.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('Alert', async () => {\n test('renders correctly with all the options', async () => {\n const options = {\n headline: [{userInput: 'my-app'}, 'initialized and ready to build.'],\n body: ['You can find the build files in the ', {filePath: 'dist'}, 'folder.'],\n nextSteps: [\n [\n 'Run',\n {\n command: 'cd santorini-goods',\n },\n ],\n [\n 'To preview your project, run',\n {\n command: 'npm app dev',\n },\n ],\n [\n 'To add extensions, run',\n {\n command: 'npm generate extension',\n },\n ],\n ],\n reference: [\n [\n 'Run',\n {\n command: 'npm shopify help',\n },\n ],\n [\n // testing link wrapping behavior\n \"Press 'return' to open the really amazing and clean\",\n {\n link: {\n label: 'dev docs',\n url: 'https://shopify.dev',\n },\n },\n ],\n ],\n link: {\n label: 'Link',\n url: 'https://shopify.com',\n },\n }\n\n const {output} = renderString(<Alert type=\"info\" {...options} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"\n ╭─ info ───────────────────────────────────────────────────────────────────────╮\n │ │\n │ my-app initialized and ready to build. │\n │ │\n │ You can find the build files in the \\\\\"dist\\\\\" folder. │\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 really amazing and clean dev docs │\n │ (https://shopify.dev) │\n │ │\n │ Link (https://shopify.com) │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('renders correctly with only required options', async () => {\n const options = {\n headline: 'Title',\n }\n\n const {output} = renderString(<Alert type=\"info\" {...options} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"\n ╭─ info ───────────────────────────────────────────────────────────────────────╮\n │ │\n │ Title │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n})\n"]}
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  export declare type BannerType = 'success' | 'error' | 'warning' | 'info' | 'external_error';
3
3
  interface Props {
4
4
  type: BannerType;
5
+ marginY?: number;
5
6
  }
6
7
  declare const Banner: React.FC<Props>;
7
8
  export { Banner };
@@ -25,34 +25,33 @@ function calculateWidth(stdout) {
25
25
  }
26
26
  return width;
27
27
  }
28
- const BoxWithBorder = ({ type, children }) => {
28
+ const BoxWithBorder = ({ type, marginY, children }) => {
29
29
  const { stdout } = useStdout();
30
- return (React.createElement(Box, { width: calculateWidth(stdout), paddingY: 1, paddingX: 2, borderStyle: "round", flexDirection: "column", borderColor: typeToColor(type) },
30
+ return (React.createElement(Box, { width: calculateWidth(stdout), paddingY: 1, paddingX: 2, marginY: marginY, borderStyle: "round", flexDirection: "column", borderColor: typeToColor(type) },
31
31
  React.createElement(Box, { marginTop: -2, marginBottom: 1, marginLeft: -1 },
32
- React.createElement(Text, { dimColor: true, bold: true }, ` ${type.replace(/_/g, ' ')} `)),
32
+ React.createElement(Text, null, ` ${type.replace(/_/g, ' ')} `)),
33
33
  children));
34
34
  };
35
- const BoxWithTopLine = ({ type, children }) => {
35
+ const BoxWithTopBottomLines = ({ type, marginY, children }) => {
36
36
  const { stdout } = useStdout();
37
37
  const width = calculateWidth(stdout);
38
- return (React.createElement(Box, { marginY: 1, flexDirection: "column" },
38
+ return (React.createElement(Box, { marginY: marginY, flexDirection: "column" },
39
39
  React.createElement(Box, { marginBottom: 1 },
40
40
  React.createElement(Text, null,
41
41
  React.createElement(Text, { color: typeToColor(type) }, '─'.repeat(2)),
42
- React.createElement(Text, { dimColor: true, bold: true }, ` ${type.replace(/_/g, ' ')} `),
42
+ React.createElement(Text, null, ` ${type.replace(/_/g, ' ')} `),
43
43
  React.createElement(Text, { color: typeToColor(type) }, '─'.repeat(width - 2 - type.length - 2)))),
44
44
  children,
45
45
  React.createElement(Box, { marginTop: 1 },
46
46
  React.createElement(Text, { color: typeToColor(type) }, '─'.repeat(width)))));
47
47
  };
48
- const BannerBox = ({ type, children }) => {
49
- if (type === 'external_error') {
50
- return React.createElement(BoxWithTopLine, { type: type }, children);
48
+ const Banner = ({ children, ...props }) => {
49
+ if (props.type === 'external_error') {
50
+ return React.createElement(BoxWithTopBottomLines, props, children);
51
+ }
52
+ else {
53
+ return React.createElement(BoxWithBorder, props, children);
51
54
  }
52
- return React.createElement(BoxWithBorder, { type: type }, children);
53
- };
54
- const Banner = ({ type, children }) => {
55
- return React.createElement(BannerBox, { type: type }, children);
56
55
  };
57
56
  export { Banner };
58
57
  //# sourceMappingURL=Banner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Banner.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Box, Text, useStdout} from 'ink'\nimport React from 'react'\n\nexport type BannerType = 'success' | 'error' | 'warning' | 'info' | 'external_error'\n\ninterface Props {\n type: BannerType\n}\n\nfunction typeToColor(type: Props['type']) {\n return {\n success: 'green',\n error: 'red',\n warning: 'yellow',\n info: 'dim',\n external_error: 'red',\n }[type]\n}\n\nconst BANNER_MIN_WIDTH = 80\n\nfunction calculateWidth(stdout: NodeJS.WriteStream | undefined) {\n const fullWidth = stdout?.columns ?? BANNER_MIN_WIDTH\n const twoThirdsOfWidth = Math.floor((fullWidth / 3) * 2)\n let width\n\n if (fullWidth <= BANNER_MIN_WIDTH) {\n width = fullWidth\n } else if (twoThirdsOfWidth < BANNER_MIN_WIDTH) {\n width = BANNER_MIN_WIDTH\n } else {\n width = twoThirdsOfWidth\n }\n\n return width\n}\n\nconst BoxWithBorder: React.FC<Props> = ({type, children}) => {\n const {stdout} = useStdout()\n\n return (\n <Box\n width={calculateWidth(stdout)}\n paddingY={1}\n paddingX={2}\n borderStyle=\"round\"\n flexDirection=\"column\"\n borderColor={typeToColor(type)}\n >\n <Box marginTop={-2} marginBottom={1} marginLeft={-1}>\n <Text dimColor bold>{` ${type.replace(/_/g, ' ')} `}</Text>\n </Box>\n {children}\n </Box>\n )\n}\n\nconst BoxWithTopLine: React.FC<Props> = ({type, children}) => {\n const {stdout} = useStdout()\n const width = calculateWidth(stdout)\n\n return (\n <Box marginY={1} flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text>\n <Text color={typeToColor(type)}>{'─'.repeat(2)}</Text>\n <Text dimColor bold>{` ${type.replace(/_/g, ' ')} `}</Text>\n {/* 2 initial dashes + 2 spaces surrounding the type */}\n <Text color={typeToColor(type)}>{'─'.repeat(width - 2 - type.length - 2)}</Text>\n </Text>\n </Box>\n\n {children}\n\n <Box marginTop={1}>\n <Text color={typeToColor(type)}>{'─'.repeat(width)}</Text>\n </Box>\n </Box>\n )\n}\n\nconst BannerBox: React.FC<Props> = ({type, children}) => {\n if (type === 'external_error') {\n return <BoxWithTopLine type={type}>{children}</BoxWithTopLine>\n }\n\n return <BoxWithBorder type={type}>{children}</BoxWithBorder>\n}\n\nconst Banner: React.FC<Props> = ({type, children}) => {\n return <BannerBox type={type}>{children}</BannerBox>\n}\n\nexport {Banner}\n"]}
1
+ {"version":3,"file":"Banner.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Banner.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Box, Text, useStdout} from 'ink'\nimport React from 'react'\n\nexport type BannerType = 'success' | 'error' | 'warning' | 'info' | 'external_error'\n\ninterface Props {\n type: BannerType\n marginY?: number\n}\n\nfunction typeToColor(type: Props['type']) {\n return {\n success: 'green',\n error: 'red',\n warning: 'yellow',\n info: 'dim',\n external_error: 'red',\n }[type]\n}\n\nconst BANNER_MIN_WIDTH = 80\n\nfunction calculateWidth(stdout: NodeJS.WriteStream | undefined) {\n const fullWidth = stdout?.columns ?? BANNER_MIN_WIDTH\n const twoThirdsOfWidth = Math.floor((fullWidth / 3) * 2)\n let width\n\n if (fullWidth <= BANNER_MIN_WIDTH) {\n width = fullWidth\n } else if (twoThirdsOfWidth < BANNER_MIN_WIDTH) {\n width = BANNER_MIN_WIDTH\n } else {\n width = twoThirdsOfWidth\n }\n\n return width\n}\n\nconst BoxWithBorder: React.FC<Props> = ({type, marginY, children}) => {\n const {stdout} = useStdout()\n\n return (\n <Box\n width={calculateWidth(stdout)}\n paddingY={1}\n paddingX={2}\n marginY={marginY}\n borderStyle=\"round\"\n flexDirection=\"column\"\n borderColor={typeToColor(type)}\n >\n <Box marginTop={-2} marginBottom={1} marginLeft={-1}>\n <Text>{` ${type.replace(/_/g, ' ')} `}</Text>\n </Box>\n {children}\n </Box>\n )\n}\n\nconst BoxWithTopBottomLines: React.FC<Props> = ({type, marginY, children}) => {\n const {stdout} = useStdout()\n const width = calculateWidth(stdout)\n\n return (\n <Box marginY={marginY} flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text>\n <Text color={typeToColor(type)}>{'─'.repeat(2)}</Text>\n <Text>{` ${type.replace(/_/g, ' ')} `}</Text>\n {/* 2 initial dashes + 2 spaces surrounding the type */}\n <Text color={typeToColor(type)}>{'─'.repeat(width - 2 - type.length - 2)}</Text>\n </Text>\n </Box>\n\n {children}\n\n <Box marginTop={1}>\n <Text color={typeToColor(type)}>{'─'.repeat(width)}</Text>\n </Box>\n </Box>\n )\n}\n\nconst Banner: React.FC<Props> = ({children, ...props}) => {\n if (props.type === 'external_error') {\n return React.createElement(BoxWithTopBottomLines, props, children)\n } else {\n return React.createElement(BoxWithBorder, props, children)\n }\n}\n\nexport {Banner}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,52 @@
1
+ import { Banner } from './Banner.js';
2
+ import { renderString } from '../../ui.js';
3
+ import { describe, expect, test } from 'vitest';
4
+ import React from 'react';
5
+ describe('Banner', async () => {
6
+ test('renders with a border for success', async () => {
7
+ const { output } = renderString(React.createElement(Banner, { type: "success" }));
8
+ expect(output).toMatchInlineSnapshot(`
9
+ "╭─ success ────────────────────────────────────────────────────────────────────╮
10
+ │ │
11
+ │ │
12
+ ╰──────────────────────────────────────────────────────────────────────────────╯"
13
+ `);
14
+ });
15
+ test('renders with a border for info', async () => {
16
+ const { output } = renderString(React.createElement(Banner, { type: "info" }));
17
+ expect(output).toMatchInlineSnapshot(`
18
+ "╭─ info ───────────────────────────────────────────────────────────────────────╮
19
+ │ │
20
+ │ │
21
+ ╰──────────────────────────────────────────────────────────────────────────────╯"
22
+ `);
23
+ });
24
+ test('renders with a border for warning', async () => {
25
+ const { output } = renderString(React.createElement(Banner, { type: "warning" }));
26
+ expect(output).toMatchInlineSnapshot(`
27
+ "╭─ warning ────────────────────────────────────────────────────────────────────╮
28
+ │ │
29
+ │ │
30
+ ╰──────────────────────────────────────────────────────────────────────────────╯"
31
+ `);
32
+ });
33
+ test('renders with a border for error', async () => {
34
+ const { output } = renderString(React.createElement(Banner, { type: "error" }));
35
+ expect(output).toMatchInlineSnapshot(`
36
+ "╭─ error ──────────────────────────────────────────────────────────────────────╮
37
+ │ │
38
+ │ │
39
+ ╰──────────────────────────────────────────────────────────────────────────────╯"
40
+ `);
41
+ });
42
+ test('renders with a top and bottom lines only for external errors', async () => {
43
+ const { output } = renderString(React.createElement(Banner, { type: "external_error" }));
44
+ expect(output).toMatchInlineSnapshot(`
45
+ "── external error ──────────────────────────────────────────────────────────────
46
+
47
+
48
+ ────────────────────────────────────────────────────────────────────────────────"
49
+ `);
50
+ });
51
+ });
52
+ //# sourceMappingURL=Banner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Banner.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Banner.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAClC,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAQ,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;IAC5B,IAAI,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,SAAS,GAAG,CAAC,CAAA;QAExD,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC;;;;;KAKpC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,MAAM,GAAG,CAAC,CAAA;QACrD,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC;;;;;KAKpC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,SAAS,GAAG,CAAC,CAAA;QACxD,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC;;;;;KAKpC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,OAAO,GAAG,CAAC,CAAA;QACtD,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC;;;;;KAKpC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,gBAAgB,GAAG,CAAC,CAAA;QAE/D,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC;;;;;KAKpC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {Banner} from './Banner.js'\nimport {renderString} from '../../ui.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('Banner', async () => {\n test('renders with a border for success', async () => {\n const {output} = renderString(<Banner type=\"success\" />)\n\n expect(output).toMatchInlineSnapshot(`\n \"\u001b[32m╭─\u001b[39m success \u001b[32m────────────────────────────────────────────────────────────────────╮\u001b[39m\n \u001b[32m│\u001b[39m \u001b[32m│\u001b[39m\n \u001b[32m│\u001b[39m \u001b[32m│\u001b[39m\n \u001b[32m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[39m\"\n `)\n })\n\n test('renders with a border for info', async () => {\n const {output} = renderString(<Banner type=\"info\" />)\n expect(output).toMatchInlineSnapshot(`\n \"\u001b[2m╭─\u001b[22m info \u001b[2m───────────────────────────────────────────────────────────────────────╮\u001b[22m\n \u001b[2m│\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m│\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[22m\"\n `)\n })\n\n test('renders with a border for warning', async () => {\n const {output} = renderString(<Banner type=\"warning\" />)\n expect(output).toMatchInlineSnapshot(`\n \"\u001b[33m╭─\u001b[39m warning \u001b[33m────────────────────────────────────────────────────────────────────╮\u001b[39m\n \u001b[33m│\u001b[39m \u001b[33m│\u001b[39m\n \u001b[33m│\u001b[39m \u001b[33m│\u001b[39m\n \u001b[33m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[39m\"\n `)\n })\n\n test('renders with a border for error', async () => {\n const {output} = renderString(<Banner type=\"error\" />)\n expect(output).toMatchInlineSnapshot(`\n \"\u001b[31m╭─\u001b[39m error \u001b[31m──────────────────────────────────────────────────────────────────────╮\u001b[39m\n \u001b[31m│\u001b[39m \u001b[31m│\u001b[39m\n \u001b[31m│\u001b[39m \u001b[31m│\u001b[39m\n \u001b[31m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[39m\"\n `)\n })\n\n test('renders with a top and bottom lines only for external errors', async () => {\n const {output} = renderString(<Banner type=\"external_error\" />)\n\n expect(output).toMatchInlineSnapshot(`\n \"\u001b[31m──\u001b[39m external error \u001b[31m──────────────────────────────────────────────────────────────\u001b[39m\n\n\n \u001b[31m────────────────────────────────────────────────────────────────────────────────\u001b[39m\"\n `)\n })\n})\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { Command } from './Command.js';
2
+ import { renderString } from '../../ui.js';
3
+ import { describe, expect, test } from 'vitest';
4
+ import React from 'react';
5
+ describe('Command', async () => {
6
+ test('renders correctly', async () => {
7
+ const { output } = renderString(React.createElement(Command, { command: "npm install" }));
8
+ expect(output).toMatchInlineSnapshot('"`npm install`"');
9
+ });
10
+ });
11
+ //# sourceMappingURL=Command.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Command.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Command.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAA;AACpC,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAQ,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;IAC7B,IAAI,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,OAAO,IAAC,OAAO,EAAC,aAAa,GAAG,CAAC,CAAA;QAEhE,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {Command} from './Command.js'\nimport {renderString} from '../../ui.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('Command', async () => {\n test('renders correctly', async () => {\n const {output} = renderString(<Command command=\"npm install\" />)\n\n expect(output).toMatchInlineSnapshot('\"`npm install`\"')\n })\n})\n"]}
@@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react';
2
2
  import { Box, Static, Text, useApp } from 'ink';
3
3
  import stripAnsi from 'strip-ansi';
4
4
  import { Writable } from 'node:stream';
5
- const OUTPUT_MIN_WIDTH = 80;
6
5
  /**
7
6
  * Renders output from concurrent processes to the terminal.
8
7
  * Output will be divided in a three column layout
@@ -49,7 +48,7 @@ const ConcurrentOutput = ({ processes, abortController, showTimestamps = true })
49
48
  const writableStream = (process, index) => {
50
49
  return new Writable({
51
50
  write(chunk, _encoding, next) {
52
- const lines = stripAnsi(chunk.toString('ascii')).split(/\n/);
51
+ const lines = stripAnsi(chunk.toString('ascii').replace(/(\n)$/, '')).split(/\n/);
53
52
  setProcessOutput((previousProcessOutput) => [
54
53
  ...previousProcessOutput,
55
54
  {
@@ -63,23 +62,18 @@ const ConcurrentOutput = ({ processes, abortController, showTimestamps = true })
63
62
  });
64
63
  };
65
64
  const runProcesses = async () => {
66
- try {
67
- await Promise.all(processes.map(async (process, index) => {
68
- const stdout = writableStream(process, index);
69
- const stderr = writableStream(process, index);
70
- await process.action(stdout, stderr, abortController.signal);
71
- }));
72
- unmountInk();
73
- }
74
- catch (error) {
75
- abortController.abort();
76
- unmountInk();
77
- throw error;
78
- }
65
+ await Promise.all(processes.map(async (process, index) => {
66
+ const stdout = writableStream(process, index);
67
+ const stderr = writableStream(process, index);
68
+ await process.action(stdout, stderr, abortController.signal);
69
+ }));
70
+ unmountInk();
79
71
  };
80
72
  useEffect(() => {
81
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
82
- runProcesses();
73
+ runProcesses().catch((error) => {
74
+ abortController.abort();
75
+ unmountInk(error);
76
+ });
83
77
  }, []);
84
78
  return (React.createElement(Static, { items: processOutput }, (chunk, index) => {
85
79
  return (React.createElement(Box, { flexDirection: "column", key: index }, chunk.lines.map((line, index) => (React.createElement(Box, { key: index, flexDirection: "row" },
@@ -1 +1 @@
1
- {"version":3,"file":"ConcurrentOutput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/ConcurrentOutput.tsx"],"names":[],"mappings":"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","sourcesContent":["import {OutputProcess} from '../../../../output.js'\nimport React, {FunctionComponent, useEffect, useState} from 'react'\nimport {Box, Static, Text, useApp} from 'ink'\nimport stripAnsi from 'strip-ansi'\nimport AbortController from 'abort-controller'\nimport {Writable} from 'node:stream'\n\nexport type WritableStream = (process: OutputProcess, index: number) => Writable\nexport type RunProcesses = (\n writableStream: WritableStream,\n unmountInk: (error?: Error | undefined) => void,\n) => Promise<void>\n\ninterface Props {\n processes: OutputProcess[]\n abortController: AbortController\n showTimestamps?: boolean\n}\ninterface Chunk {\n color: string\n prefix: string\n lines: string[]\n}\n\nconst OUTPUT_MIN_WIDTH = 80\n\n/**\n * Renders output from concurrent processes to the terminal.\n * Output will be divided in a three column layout\n * with the left column containing the timestamp,\n * the right column containing the output,\n * and the middle column containing the process prefix.\n * Every process will be rendered with a different color, up to 4 colors.\n *\n * For example running `shopify app dev`:\n *\n * ```shell\n * 2022-10-10 13:11:03 | backend | npm\n * 2022-10-10 13:11:03 | backend | WARN ignoring workspace config at ...\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | > shopify-app-template-node@0.1.0 dev\n * 2022-10-10 13:11:03 | backend | > cross-env NODE_ENV=development nodemon backend/index.js --watch ./backend\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend | > starter-react-frontend-app@0.1.0 dev\n * 2022-10-10 13:11:03 | frontend | > cross-env NODE_ENV=development node vite-server.js\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | backend | [nodemon] 2.0.19\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | [nodemon] to restart at any time, enter `rs`\n * 2022-10-10 13:11:03 | backend | [nodemon] watching path(s): backend/\n * 2022-10-10 13:11:03 | backend | [nodemon] watching extensions: js,mjs,json\n * 2022-10-10 13:11:03 | backend | [nodemon] starting `node backend/index.js`\n * 2022-10-10 13:11:03 | backend |\n *\n * ```\n */\nconst ConcurrentOutput: FunctionComponent<Props> = ({processes, abortController, showTimestamps = true}) => {\n const [processOutput, setProcessOutput] = useState<Chunk[]>([])\n const concurrentColors = ['yellow', 'cyan', 'magenta', 'green', 'blue']\n const prefixColumnSize = Math.max(...processes.map((process) => process.prefix.length))\n const {exit: unmountInk} = useApp()\n\n function lineColor(index: number) {\n const colorIndex = index < concurrentColors.length ? index : index % concurrentColors.length\n return concurrentColors[colorIndex]!\n }\n\n const writableStream = (process: OutputProcess, index: number) => {\n return new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsi(chunk.toString('ascii')).split(/\\n/)\n\n setProcessOutput((previousProcessOutput) => [\n ...previousProcessOutput,\n {\n color: lineColor(index),\n prefix: process.prefix,\n lines,\n },\n ])\n\n next()\n },\n })\n }\n\n const runProcesses = async () => {\n try {\n await Promise.all(\n processes.map(async (process, index) => {\n const stdout = writableStream(process, index)\n const stderr = writableStream(process, index)\n\n await process.action(stdout, stderr, abortController.signal)\n }),\n )\n\n unmountInk()\n } catch (error) {\n abortController.abort()\n unmountInk()\n throw error\n }\n }\n\n useEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n runProcesses()\n }, [])\n\n return (\n <Static items={processOutput}>\n {(chunk, index) => {\n return (\n <Box flexDirection=\"column\" key={index}>\n {chunk.lines.map((line, index) => (\n <Box key={index} flexDirection=\"row\">\n {showTimestamps && (\n <Box>\n <Box marginRight={1}>\n <Text color={chunk.color}>{new Date().toISOString().replace(/T/, ' ').replace(/\\..+/, '')}</Text>\n </Box>\n\n <Text bold color={chunk.color}>\n |\n </Text>\n </Box>\n )}\n\n <Box width={prefixColumnSize} marginX={1}>\n <Text color={chunk.color}>{chunk.prefix}</Text>\n </Box>\n\n <Text bold color={chunk.color}>\n |\n </Text>\n\n <Box flexGrow={1} paddingLeft={1}>\n <Text color={chunk.color}>{line}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )\n }}\n </Static>\n )\n}\n\nexport default ConcurrentOutput\n"]}
1
+ {"version":3,"file":"ConcurrentOutput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/ConcurrentOutput.tsx"],"names":[],"mappings":"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","sourcesContent":["import {OutputProcess} from '../../../../output.js'\nimport React, {FunctionComponent, useEffect, useState} from 'react'\nimport {Box, Static, Text, useApp} from 'ink'\nimport stripAnsi from 'strip-ansi'\nimport AbortController from 'abort-controller'\nimport {Writable} from 'node:stream'\n\nexport type WritableStream = (process: OutputProcess, index: number) => Writable\nexport type RunProcesses = (\n writableStream: WritableStream,\n unmountInk: (error?: Error | undefined) => void,\n) => Promise<void>\n\ninterface Props {\n processes: OutputProcess[]\n abortController: AbortController\n showTimestamps?: boolean\n}\ninterface Chunk {\n color: string\n prefix: string\n lines: string[]\n}\n\n/**\n * Renders output from concurrent processes to the terminal.\n * Output will be divided in a three column layout\n * with the left column containing the timestamp,\n * the right column containing the output,\n * and the middle column containing the process prefix.\n * Every process will be rendered with a different color, up to 4 colors.\n *\n * For example running `shopify app dev`:\n *\n * ```shell\n * 2022-10-10 13:11:03 | backend | npm\n * 2022-10-10 13:11:03 | backend | WARN ignoring workspace config at ...\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | > shopify-app-template-node@0.1.0 dev\n * 2022-10-10 13:11:03 | backend | > cross-env NODE_ENV=development nodemon backend/index.js --watch ./backend\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend | > starter-react-frontend-app@0.1.0 dev\n * 2022-10-10 13:11:03 | frontend | > cross-env NODE_ENV=development node vite-server.js\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | backend | [nodemon] 2.0.19\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | [nodemon] to restart at any time, enter `rs`\n * 2022-10-10 13:11:03 | backend | [nodemon] watching path(s): backend/\n * 2022-10-10 13:11:03 | backend | [nodemon] watching extensions: js,mjs,json\n * 2022-10-10 13:11:03 | backend | [nodemon] starting `node backend/index.js`\n * 2022-10-10 13:11:03 | backend |\n *\n * ```\n */\nconst ConcurrentOutput: FunctionComponent<Props> = ({processes, abortController, showTimestamps = true}) => {\n const [processOutput, setProcessOutput] = useState<Chunk[]>([])\n const concurrentColors = ['yellow', 'cyan', 'magenta', 'green', 'blue']\n const prefixColumnSize = Math.max(...processes.map((process) => process.prefix.length))\n const {exit: unmountInk} = useApp()\n\n function lineColor(index: number) {\n const colorIndex = index < concurrentColors.length ? index : index % concurrentColors.length\n return concurrentColors[colorIndex]!\n }\n\n const writableStream = (process: OutputProcess, index: number) => {\n return new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsi(chunk.toString('ascii').replace(/(\\n)$/, '')).split(/\\n/)\n\n setProcessOutput((previousProcessOutput) => [\n ...previousProcessOutput,\n {\n color: lineColor(index),\n prefix: process.prefix,\n lines,\n },\n ])\n\n next()\n },\n })\n }\n\n const runProcesses = async () => {\n await Promise.all(\n processes.map(async (process, index) => {\n const stdout = writableStream(process, index)\n const stderr = writableStream(process, index)\n\n await process.action(stdout, stderr, abortController.signal)\n }),\n )\n\n unmountInk()\n }\n\n useEffect(() => {\n runProcesses().catch((error) => {\n abortController.abort()\n unmountInk(error)\n })\n }, [])\n\n return (\n <Static items={processOutput}>\n {(chunk, index) => {\n return (\n <Box flexDirection=\"column\" key={index}>\n {chunk.lines.map((line, index) => (\n <Box key={index} flexDirection=\"row\">\n {showTimestamps && (\n <Box>\n <Box marginRight={1}>\n <Text color={chunk.color}>{new Date().toISOString().replace(/T/, ' ').replace(/\\..+/, '')}</Text>\n </Box>\n\n <Text bold color={chunk.color}>\n |\n </Text>\n </Box>\n )}\n\n <Box width={prefixColumnSize} marginX={1}>\n <Text color={chunk.color}>{chunk.prefix}</Text>\n </Box>\n\n <Text bold color={chunk.color}>\n |\n </Text>\n\n <Box flexGrow={1} paddingLeft={1}>\n <Text color={chunk.color}>{line}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )\n }}\n </Static>\n )\n}\n\nexport default ConcurrentOutput\n"]}
@@ -1,6 +1,7 @@
1
1
  import { Banner } from './Banner.js';
2
2
  import { TokenizedText } from './TokenizedText.js';
3
3
  import { Command } from './Command.js';
4
+ import { List } from './List.js';
4
5
  import { Bug, cleanSingleStackTracePath, ExternalError } from '../../../../error.js';
5
6
  import { Box, Text } from 'ink';
6
7
  import React from 'react';
@@ -28,7 +29,7 @@ const FatalError = ({ error }) => {
28
29
  if (error instanceof ExternalError) {
29
30
  tool = `${error.command} ${error.args.join(' ')}`;
30
31
  }
31
- return (React.createElement(Banner, { type: tool ? 'external_error' : 'error' },
32
+ return (React.createElement(Banner, { type: tool ? 'external_error' : 'error', marginY: 1 },
32
33
  tool && (React.createElement(Box, { marginBottom: 1 },
33
34
  React.createElement(Text, null,
34
35
  "Error coming from ",
@@ -37,8 +38,10 @@ const FatalError = ({ error }) => {
37
38
  React.createElement(Text, null, error.message)),
38
39
  error.tryMessage && (React.createElement(Box, { marginTop: 1 },
39
40
  React.createElement(TokenizedText, { item: error.tryMessage }))),
41
+ error.nextSteps && (React.createElement(Box, { marginTop: 1 },
42
+ React.createElement(List, { title: "Next steps", items: error.nextSteps }))),
40
43
  stack && stack.items.length !== 0 && (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
41
- React.createElement(Text, { dimColor: true }, "To investigate the issue, examine this stack trace:"),
44
+ React.createElement(Text, null, "To investigate the issue, examine this stack trace:"),
42
45
  stack.items.map((item, index) => (React.createElement(Box, { flexDirection: "column", key: index },
43
46
  React.createElement(Text, null,
44
47
  "at",
@@ -1 +1 @@
1
- {"version":3,"file":"FatalError.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/FatalError.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Banner} from './Banner.js'\nimport {TokenizedText} from './TokenizedText.js'\nimport {Command} from './Command.js'\nimport {Bug, cleanSingleStackTracePath, ExternalError, Fatal} from '../../../../error.js'\nimport {Box, Text} from 'ink'\nimport React from 'react'\nimport StackTracey from 'stacktracey'\n\nexport interface FatalErrorProps {\n error: Fatal\n}\n\nconst FatalError: React.FC<FatalErrorProps> = ({error}) => {\n let stack\n let tool\n\n if (error instanceof Bug) {\n stack = new StackTracey(error)\n stack.items.forEach((item) => {\n item.file = cleanSingleStackTracePath(item.file)\n })\n\n stack = stack.withSources()\n stack = stack\n .filter((entry) => {\n return !entry.file.includes('@oclif/core')\n })\n .map((item) => {\n /** We make the paths relative to the packages/ directory */\n const fileShortComponents = item.fileShort.split('packages/')\n item.fileShort = fileShortComponents.length === 2 ? fileShortComponents[1]! : fileShortComponents[0]!\n return item\n })\n }\n\n if (error instanceof ExternalError) {\n tool = `${error.command} ${error.args.join(' ')}`\n }\n\n return (\n <Banner type={tool ? 'external_error' : 'error'}>\n {tool && (\n <Box marginBottom={1}>\n <Text>\n Error coming from <Command command={tool} />\n </Text>\n </Box>\n )}\n\n <Box>\n <Text>{error.message}</Text>\n </Box>\n\n {error.tryMessage && (\n <Box marginTop={1}>\n <TokenizedText item={error.tryMessage} />\n </Box>\n )}\n {stack && stack.items.length !== 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>To investigate the issue, examine this stack trace:</Text>\n {stack.items.map((item, index) => (\n <Box flexDirection=\"column\" key={index}>\n <Text>\n at{item.calleeShort && <Text color=\"yellow\">{` ${item.calleeShort}`}</Text>}\n {item.fileShort && ` (${item.fileShort}:${item.line})`}\n </Text>\n <Box paddingLeft={1}>\n <Text dimColor>{item.sourceLine?.trim()}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )}\n </Banner>\n )\n}\n\nexport {FatalError}\n"]}
1
+ {"version":3,"file":"FatalError.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/FatalError.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Banner} from './Banner.js'\nimport {TokenizedText} from './TokenizedText.js'\nimport {Command} from './Command.js'\nimport {List} from './List.js'\nimport {Bug, cleanSingleStackTracePath, ExternalError, Fatal} from '../../../../error.js'\nimport {Box, Text} from 'ink'\nimport React from 'react'\nimport StackTracey from 'stacktracey'\n\nexport interface FatalErrorProps {\n error: Fatal\n}\n\nconst FatalError: React.FC<FatalErrorProps> = ({error}) => {\n let stack\n let tool\n\n if (error instanceof Bug) {\n stack = new StackTracey(error)\n stack.items.forEach((item) => {\n item.file = cleanSingleStackTracePath(item.file)\n })\n\n stack = stack.withSources()\n stack = stack\n .filter((entry) => {\n return !entry.file.includes('@oclif/core')\n })\n .map((item) => {\n /** We make the paths relative to the packages/ directory */\n const fileShortComponents = item.fileShort.split('packages/')\n item.fileShort = fileShortComponents.length === 2 ? fileShortComponents[1]! : fileShortComponents[0]!\n return item\n })\n }\n\n if (error instanceof ExternalError) {\n tool = `${error.command} ${error.args.join(' ')}`\n }\n\n return (\n <Banner type={tool ? 'external_error' : 'error'} marginY={1}>\n {tool && (\n <Box marginBottom={1}>\n <Text>\n Error coming from <Command command={tool} />\n </Text>\n </Box>\n )}\n\n <Box>\n <Text>{error.message}</Text>\n </Box>\n\n {error.tryMessage && (\n <Box marginTop={1}>\n <TokenizedText item={error.tryMessage} />\n </Box>\n )}\n\n {error.nextSteps && (\n <Box marginTop={1}>\n <List title=\"Next steps\" items={error.nextSteps} />\n </Box>\n )}\n\n {stack && stack.items.length !== 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text>To investigate the issue, examine this stack trace:</Text>\n {stack.items.map((item, index) => (\n <Box flexDirection=\"column\" key={index}>\n <Text>\n at{item.calleeShort && <Text color=\"yellow\">{` ${item.calleeShort}`}</Text>}\n {item.fileShort && ` (${item.fileShort}:${item.line})`}\n </Text>\n <Box paddingLeft={1}>\n <Text dimColor>{item.sourceLine?.trim()}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )}\n </Banner>\n )\n}\n\nexport {FatalError}\n"]}
@@ -0,0 +1,119 @@
1
+ import { FatalError } from './FatalError.js';
2
+ import { renderString } from '../../ui.js';
3
+ import { unstyled } from '../../../../output.js';
4
+ import { Abort, Bug, ExternalError } from '../../../../error.js';
5
+ import { describe, expect, test } from 'vitest';
6
+ import React from 'react';
7
+ describe('FatalError', async () => {
8
+ test('renders correctly with a just a message and tryMessage', async () => {
9
+ const error = new Abort('test', 'try this');
10
+ const { output } = renderString(React.createElement(FatalError, { error: error }));
11
+ expect(unstyled(output)).toMatchInlineSnapshot(`
12
+ "
13
+ ╭─ error ──────────────────────────────────────────────────────────────────────╮
14
+ │ │
15
+ │ test │
16
+ │ │
17
+ │ try this │
18
+ │ │
19
+ ╰──────────────────────────────────────────────────────────────────────────────╯
20
+ "
21
+ `);
22
+ });
23
+ test('renders correctly with a message and a stack', async () => {
24
+ const error = new Bug('Unexpected error');
25
+ error.stack = `
26
+ Error: Unexpected error
27
+ at Module._compile (internal/modules/cjs/loader.js:1137:30)
28
+ at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
29
+ at Module.load (internal/modules/cjs/loader.js:985:32)
30
+ at Function.Module._load (internal/modules/cjs/loader.js:878:14)
31
+ `;
32
+ const { output } = renderString(React.createElement(FatalError, { error: error }));
33
+ expect(unstyled(output)).toMatchInlineSnapshot(`
34
+ "
35
+ ╭─ error ──────────────────────────────────────────────────────────────────────╮
36
+ │ │
37
+ │ Unexpected error │
38
+ │ │
39
+ │ To investigate the issue, examine this stack trace: │
40
+ │ at _compile (internal/modules/cjs/loader.js:1137) │
41
+ │ at js (internal/modules/cjs/loader.js:1157) │
42
+ │ at load (internal/modules/cjs/loader.js:985) │
43
+ │ at _load (internal/modules/cjs/loader.js:878) │
44
+ │ │
45
+ ╰──────────────────────────────────────────────────────────────────────────────╯
46
+ "
47
+ `);
48
+ });
49
+ test('renders correctly with a message, a stack, and next steps', async () => {
50
+ const error = new Bug('Unexpected error');
51
+ error.stack = `
52
+ Error: Unexpected error
53
+ at Module._compile (internal/modules/cjs/loader.js:1137:30)
54
+ at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
55
+ at Module.load (internal/modules/cjs/loader.js:985:32)
56
+ at Function.Module._load (internal/modules/cjs/loader.js:878:14)
57
+ `;
58
+ error.nextSteps = [
59
+ [
60
+ 'Have you',
61
+ {
62
+ link: {
63
+ label: 'created a Shopify Partners organization',
64
+ url: 'https://partners.shopify.com/signup',
65
+ },
66
+ },
67
+ {
68
+ char: '?',
69
+ },
70
+ ],
71
+ 'Have you confirmed your accounts from the emails you received?',
72
+ [
73
+ 'Need to connect to a different App or organization? Run the command again with',
74
+ {
75
+ command: '--reset',
76
+ },
77
+ ],
78
+ ];
79
+ const { output } = renderString(React.createElement(FatalError, { error: error }));
80
+ expect(unstyled(output)).toMatchInlineSnapshot(`
81
+ "
82
+ ╭─ error ──────────────────────────────────────────────────────────────────────╮
83
+ │ │
84
+ │ Unexpected error │
85
+ │ │
86
+ │ Next steps │
87
+ │ • Have you created a Shopify Partners organization │
88
+ │ (https://partners.shopify.com/signup)? │
89
+ │ • Have you confirmed your accounts from the emails you received? │
90
+ │ • Need to connect to a different App or organization? Run the command │
91
+ │ again with \`--reset\` │
92
+ │ │
93
+ │ To investigate the issue, examine this stack trace: │
94
+ │ at _compile (internal/modules/cjs/loader.js:1137) │
95
+ │ at js (internal/modules/cjs/loader.js:1157) │
96
+ │ at load (internal/modules/cjs/loader.js:985) │
97
+ │ at _load (internal/modules/cjs/loader.js:878) │
98
+ │ │
99
+ ╰──────────────────────────────────────────────────────────────────────────────╯
100
+ "
101
+ `);
102
+ });
103
+ test('renders correctly an external error', async () => {
104
+ const error = new ExternalError('Unexpected error', 'yarn', ['install']);
105
+ const { output } = renderString(React.createElement(FatalError, { error: error }));
106
+ expect(unstyled(output)).toMatchInlineSnapshot(`
107
+ "
108
+ ── external error ──────────────────────────────────────────────────────────────
109
+
110
+ Error coming from \`yarn install\`
111
+
112
+ Unexpected error
113
+
114
+ ────────────────────────────────────────────────────────────────────────────────
115
+ "
116
+ `);
117
+ });
118
+ });
119
+ //# sourceMappingURL=FatalError.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FatalError.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/FatalError.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAC,KAAK,EAAE,GAAG,EAAE,aAAa,EAAC,MAAM,sBAAsB,CAAA;AAC9D,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAQ,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;IAChC,IAAI,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;QAC3C,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC,CAAA;QAE3D,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;KAU/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAA;QACzC,KAAK,CAAC,KAAK,GAAG;;;;;;KAMb,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC,CAAA;QAE3D,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;KAc/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAA;QACzC,KAAK,CAAC,KAAK,GAAG;;;;;;KAMb,CAAA;QAED,KAAK,CAAC,SAAS,GAAG;YAChB;gBACE,UAAU;gBACV;oBACE,IAAI,EAAE;wBACJ,KAAK,EAAE,yCAAyC;wBAChD,GAAG,EAAE,qCAAqC;qBAC3C;iBACF;gBACD;oBACE,IAAI,EAAE,GAAG;iBACV;aACF;YACD,gEAAgE;YAChE;gBACE,gFAAgF;gBAChF;oBACE,OAAO,EAAE,SAAS;iBACnB;aACF;SACF,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC,CAAA;QAE3D,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;;;;;;;;KAqB/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,CAAA;QAExE,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC,CAAA;QAE3D,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;KAU/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {FatalError} from './FatalError.js'\nimport {renderString} from '../../ui.js'\nimport {unstyled} from '../../../../output.js'\nimport {Abort, Bug, ExternalError} from '../../../../error.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('FatalError', async () => {\n test('renders correctly with a just a message and tryMessage', async () => {\n const error = new Abort('test', 'try this')\n const {output} = renderString(<FatalError error={error} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"\n ╭─ error ──────────────────────────────────────────────────────────────────────╮\n │ │\n │ test │\n │ │\n │ try this │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('renders correctly with a message and a stack', async () => {\n const error = new Bug('Unexpected error')\n error.stack = `\n Error: Unexpected error\n at Module._compile (internal/modules/cjs/loader.js:1137:30)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)\n at Module.load (internal/modules/cjs/loader.js:985:32)\n at Function.Module._load (internal/modules/cjs/loader.js:878:14)\n `\n\n const {output} = renderString(<FatalError error={error} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"\n ╭─ error ──────────────────────────────────────────────────────────────────────╮\n │ │\n │ Unexpected error │\n │ │\n │ To investigate the issue, examine this stack trace: │\n │ at _compile (internal/modules/cjs/loader.js:1137) │\n │ at js (internal/modules/cjs/loader.js:1157) │\n │ at load (internal/modules/cjs/loader.js:985) │\n │ at _load (internal/modules/cjs/loader.js:878) │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('renders correctly with a message, a stack, and next steps', async () => {\n const error = new Bug('Unexpected error')\n error.stack = `\n Error: Unexpected error\n at Module._compile (internal/modules/cjs/loader.js:1137:30)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)\n at Module.load (internal/modules/cjs/loader.js:985:32)\n at Function.Module._load (internal/modules/cjs/loader.js:878:14)\n `\n\n error.nextSteps = [\n [\n 'Have you',\n {\n link: {\n label: 'created a Shopify Partners organization',\n url: 'https://partners.shopify.com/signup',\n },\n },\n {\n char: '?',\n },\n ],\n 'Have you confirmed your accounts from the emails you received?',\n [\n 'Need to connect to a different App or organization? Run the command again with',\n {\n command: '--reset',\n },\n ],\n ]\n\n const {output} = renderString(<FatalError error={error} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"\n ╭─ error ──────────────────────────────────────────────────────────────────────╮\n │ │\n │ Unexpected error │\n │ │\n │ Next steps │\n │ • Have you created a Shopify Partners organization │\n │ (https://partners.shopify.com/signup)? │\n │ • Have you confirmed your accounts from the emails you received? │\n │ • Need to connect to a different App or organization? Run the command │\n │ again with \\`--reset\\` │\n │ │\n │ To investigate the issue, examine this stack trace: │\n │ at _compile (internal/modules/cjs/loader.js:1137) │\n │ at js (internal/modules/cjs/loader.js:1157) │\n │ at load (internal/modules/cjs/loader.js:985) │\n │ at _load (internal/modules/cjs/loader.js:878) │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('renders correctly an external error', async () => {\n const error = new ExternalError('Unexpected error', 'yarn', ['install'])\n\n const {output} = renderString(<FatalError error={error} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"\n ── external error ──────────────────────────────────────────────────────────────\n\n Error coming from \\`yarn install\\`\n\n Unexpected error\n\n ────────────────────────────────────────────────────────────────────────────────\n \"\n `)\n })\n})\n"]}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface Props {
3
+ filePath: string;
4
+ }
5
+ /**
6
+ * `FilePath` displays a path to a file.
7
+ */
8
+ declare const FilePath: React.FC<Props>;
9
+ export { FilePath };
@@ -0,0 +1,13 @@
1
+ import { Text } from 'ink';
2
+ import React from 'react';
3
+ /**
4
+ * `FilePath` displays a path to a file.
5
+ */
6
+ const FilePath = ({ filePath }) => {
7
+ return React.createElement(Text, null,
8
+ "\"",
9
+ filePath,
10
+ "\"");
11
+ };
12
+ export { FilePath };
13
+ //# sourceMappingURL=FilePath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilePath.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/FilePath.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,KAAK,CAAA;AACxB,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB;;GAEG;AACH,MAAM,QAAQ,GAAoB,CAAC,EAAC,QAAQ,EAAiC,EAAe,EAAE;IAC5F,OAAO,oBAAC,IAAI;;QAAG,QAAQ;aAAS,CAAA;AAClC,CAAC,CAAA;AAED,OAAO,EAAC,QAAQ,EAAC,CAAA","sourcesContent":["import {Text} from 'ink'\nimport React from 'react'\n\ninterface Props {\n filePath: string\n}\n\n/**\n * `FilePath` displays a path to a file.\n */\nconst FilePath: React.FC<Props> = ({filePath}: React.PropsWithChildren<Props>): JSX.Element => {\n return <Text>\"{filePath}\"</Text>\n}\n\nexport {FilePath}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { FilePath } from './FilePath.js';
2
+ import { renderString } from '../../ui.js';
3
+ import { describe, expect, test } from 'vitest';
4
+ import React from 'react';
5
+ describe('FilePath', async () => {
6
+ test('renders correctly', async () => {
7
+ const { output } = renderString(React.createElement(FilePath, { filePath: "src/this/is/a/test.js" }));
8
+ expect(output).toMatchInlineSnapshot('"\\"src/this/is/a/test.js\\""');
9
+ });
10
+ });
11
+ //# sourceMappingURL=FilePath.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilePath.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/FilePath.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AACtC,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAQ,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE;IAC9B,IAAI,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,QAAQ,IAAC,QAAQ,EAAC,uBAAuB,GAAG,CAAC,CAAA;QAE5E,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,+BAA+B,CAAC,CAAA;IACvE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {FilePath} from './FilePath.js'\nimport {renderString} from '../../ui.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('FilePath', async () => {\n test('renders correctly', async () => {\n const {output} = renderString(<FilePath filePath=\"src/this/is/a/test.js\" />)\n\n expect(output).toMatchInlineSnapshot('\"\\\\\"src/this/is/a/test.js\\\\\"\"')\n })\n})\n"]}
@@ -1,14 +1,15 @@
1
- import { Text, Transform } from 'ink';
1
+ import chalk from 'chalk';
2
+ import { Text } from 'ink';
2
3
  import React from 'react';
3
4
  import terminalLink from 'terminal-link';
5
+ function fallback(text, url) {
6
+ return `${text} ${chalk.dim(`(${url})`)}`;
7
+ }
4
8
  /**
5
9
  * `Link` displays a clickable link when supported by the terminal.
6
10
  */
7
11
  const Link = ({ url, label }) => {
8
- return (React.createElement(Text, null,
9
- label && React.createElement(Text, { dimColor: true }, `${label}: `),
10
- React.createElement(Transform, { transform: (children) => terminalLink(children, url, { fallback: false }) },
11
- React.createElement(Text, { underline: true }, url))));
12
+ return React.createElement(Text, null, terminalLink(label ?? url, url, { fallback: label ? fallback : false }));
12
13
  };
13
14
  export { Link };
14
15
  //# sourceMappingURL=Link.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Link.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,SAAS,EAAC,MAAM,KAAK,CAAA;AACnC,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,YAAY,MAAM,eAAe,CAAA;AAOxC;;GAEG;AACH,MAAM,IAAI,GAAoB,CAAC,EAAC,GAAG,EAAE,KAAK,EAAiC,EAAe,EAAE;IAC1F,OAAO,CACL,oBAAC,IAAI;QACF,KAAK,IAAI,oBAAC,IAAI,IAAC,QAAQ,UAAE,GAAG,KAAK,IAAI,CAAQ;QAC9C,oBAAC,SAAS,IAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAC,QAAQ,EAAE,KAAK,EAAC,CAAC;YAChF,oBAAC,IAAI,IAAC,SAAS,UAAE,GAAG,CAAQ,CAClB,CACP,CACR,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAC,IAAI,EAAC,CAAA","sourcesContent":["import {Text, Transform} from 'ink'\nimport React from 'react'\nimport terminalLink from 'terminal-link'\n\ninterface Props {\n url: string\n label?: string\n}\n\n/**\n * `Link` displays a clickable link when supported by the terminal.\n */\nconst Link: React.FC<Props> = ({url, label}: React.PropsWithChildren<Props>): JSX.Element => {\n return (\n <Text>\n {label && <Text dimColor>{`${label}: `}</Text>}\n <Transform transform={(children) => terminalLink(children, url, {fallback: false})}>\n <Text underline>{url}</Text>\n </Transform>\n </Text>\n )\n}\n\nexport {Link}\n"]}
1
+ {"version":3,"file":"Link.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,KAAK,CAAA;AACxB,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,YAAY,MAAM,eAAe,CAAA;AAOxC,SAAS,QAAQ,CAAC,IAAY,EAAE,GAAW;IACzC,OAAO,GAAG,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAA;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,IAAI,GAAoB,CAAC,EAAC,GAAG,EAAE,KAAK,EAAiC,EAAe,EAAE;IAC1F,OAAO,oBAAC,IAAI,QAAE,YAAY,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAC,CAAC,CAAQ,CAAA;AAC7F,CAAC,CAAA;AAED,OAAO,EAAC,IAAI,EAAC,CAAA","sourcesContent":["import chalk from 'chalk'\nimport {Text} from 'ink'\nimport React from 'react'\nimport terminalLink from 'terminal-link'\n\ninterface Props {\n url: string\n label?: string\n}\n\nfunction fallback(text: string, url: string) {\n return `${text} ${chalk.dim(`(${url})`)}`\n}\n\n/**\n * `Link` displays a clickable link when supported by the terminal.\n */\nconst Link: React.FC<Props> = ({url, label}: React.PropsWithChildren<Props>): JSX.Element => {\n return <Text>{terminalLink(label ?? url, url, {fallback: label ? fallback : false})}</Text>\n}\n\nexport {Link}\n"]}
@@ -0,0 +1 @@
1
+ export {};