@shopify/cli-kit 3.24.1 → 3.26.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/LICENSE +8 -0
- package/assets/favicon.svg +0 -0
- package/dist/analytics.d.ts +1 -1
- package/dist/analytics.js +1 -2
- package/dist/analytics.js.map +1 -1
- package/dist/api/graphql/extension_specifications.d.ts +1 -0
- package/dist/api/graphql/extension_specifications.js +1 -0
- package/dist/api/graphql/extension_specifications.js.map +1 -1
- package/dist/api/graphql/functions/app_function_set.d.ts +1 -0
- package/dist/api/graphql/functions/app_function_set.js +2 -0
- package/dist/api/graphql/functions/app_function_set.js.map +1 -1
- package/dist/git.d.ts +2 -1
- package/dist/git.js +23 -1
- package/dist/git.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/log.js +9 -18
- package/dist/log.js.map +1 -1
- package/dist/output.d.ts +1 -1
- package/dist/output.js +7 -1
- package/dist/output.js.map +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/plugins.js +1 -1
- package/dist/plugins.js.map +1 -1
- package/dist/private/node/ui/components/Alert.d.ts +1 -1
- package/dist/private/node/ui/components/Alert.js +2 -2
- package/dist/private/node/ui/components/Alert.js.map +1 -1
- package/dist/private/node/ui/components/Alert.test.d.ts +1 -0
- package/dist/private/node/ui/components/Alert.test.js +95 -0
- package/dist/private/node/ui/components/Alert.test.js.map +1 -0
- package/dist/private/node/ui/components/Banner.js +8 -9
- package/dist/private/node/ui/components/Banner.js.map +1 -1
- package/dist/private/node/ui/components/Banner.test.d.ts +1 -0
- package/dist/private/node/ui/components/Banner.test.js +52 -0
- package/dist/private/node/ui/components/Banner.test.js.map +1 -0
- package/dist/private/node/ui/components/Command.test.d.ts +1 -0
- package/dist/private/node/ui/components/Command.test.js +11 -0
- package/dist/private/node/ui/components/Command.test.js.map +1 -0
- package/dist/private/node/ui/components/ConcurrentOutput.js +0 -1
- package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
- package/dist/private/node/ui/components/FatalError.js +1 -1
- package/dist/private/node/ui/components/FatalError.js.map +1 -1
- package/dist/private/node/ui/components/FatalError.test.d.ts +1 -0
- package/dist/private/node/ui/components/FatalError.test.js +119 -0
- package/dist/private/node/ui/components/FatalError.test.js.map +1 -0
- package/dist/private/node/ui/components/FilePath.d.ts +9 -0
- package/dist/private/node/ui/components/FilePath.js +13 -0
- package/dist/private/node/ui/components/FilePath.js.map +1 -0
- package/dist/private/node/ui/components/FilePath.test.d.ts +1 -0
- package/dist/private/node/ui/components/FilePath.test.js +11 -0
- package/dist/private/node/ui/components/FilePath.test.js.map +1 -0
- package/dist/private/node/ui/components/Link.js +6 -5
- package/dist/private/node/ui/components/Link.js.map +1 -1
- package/dist/private/node/ui/components/Link.test.d.ts +1 -0
- package/dist/private/node/ui/components/Link.test.js +22 -0
- package/dist/private/node/ui/components/Link.test.js.map +1 -0
- package/dist/private/node/ui/components/List.d.ts +1 -1
- package/dist/private/node/ui/components/List.js +2 -2
- package/dist/private/node/ui/components/List.js.map +1 -1
- package/dist/private/node/ui/components/List.test.d.ts +1 -0
- package/dist/private/node/ui/components/List.test.js +34 -0
- package/dist/private/node/ui/components/List.test.js.map +1 -0
- package/dist/private/node/ui/components/TokenizedText.d.ts +13 -1
- package/dist/private/node/ui/components/TokenizedText.js +47 -6
- package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
- package/dist/private/node/ui/components/TokenizedText.test.d.ts +1 -0
- package/dist/private/node/ui/components/TokenizedText.test.js +44 -0
- package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -0
- package/dist/private/node/ui/components/UserInput.d.ts +10 -0
- package/dist/private/node/ui/components/UserInput.js +11 -0
- package/dist/private/node/ui/components/UserInput.js.map +1 -0
- package/dist/private/node/ui/components/UserInput.test.d.ts +1 -0
- package/dist/private/node/ui/components/UserInput.test.js +11 -0
- package/dist/private/node/ui/components/UserInput.test.js.map +1 -0
- package/dist/public/node/github.d.ts +50 -0
- package/dist/{github.js → public/node/github.js} +29 -14
- package/dist/public/node/github.js.map +1 -0
- package/dist/public/node/plugins/tunnel.d.ts +1 -1
- package/dist/public/node/plugins/tunnel.js +1 -1
- package/dist/public/node/plugins/tunnel.js.map +1 -1
- package/dist/public/{common → node}/result.d.ts +12 -6
- package/dist/public/{common → node}/result.js +28 -5
- package/dist/public/node/result.js.map +1 -0
- package/dist/public/node/ruby.js +8 -1
- package/dist/public/node/ruby.js.map +1 -1
- package/dist/session/exchange.d.ts +1 -1
- package/dist/session/exchange.js +4 -4
- package/dist/session/exchange.js.map +1 -1
- package/dist/system.js +1 -0
- package/dist/system.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -13
- package/CHANGELOG.md +0 -725
- package/dist/github.d.ts +0 -33
- package/dist/github.js.map +0 -1
- package/dist/public/common/result.js.map +0 -1
|
@@ -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
|
|
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
|
|
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,
|
|
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 {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Link } from './Link.js';
|
|
2
|
+
import { renderString } from '../../ui.js';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
describe('Link', async () => {
|
|
6
|
+
test("renders correctly with a fallback for terminals that don't support hyperlinks", async () => {
|
|
7
|
+
const link = {
|
|
8
|
+
url: 'https://example.com',
|
|
9
|
+
label: 'Example',
|
|
10
|
+
};
|
|
11
|
+
const { output } = renderString(React.createElement(Link, { ...link }));
|
|
12
|
+
expect(output).toMatchInlineSnapshot('"Example [2m(https://example.com)[22m"');
|
|
13
|
+
});
|
|
14
|
+
test("it doesn't render a fallback if only url is passed", async () => {
|
|
15
|
+
const link = {
|
|
16
|
+
url: 'https://example.com',
|
|
17
|
+
};
|
|
18
|
+
const { output } = renderString(React.createElement(Link, { ...link }));
|
|
19
|
+
expect(output).toMatchInlineSnapshot('"https://example.com"');
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=Link.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Link.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Link.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,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,MAAM,EAAE,KAAK,IAAI,EAAE;IAC1B,IAAI,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC/F,MAAM,IAAI,GAAG;YACX,GAAG,EAAE,qBAAqB;YAC1B,KAAK,EAAE,SAAS;SACjB,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,IAAI,OAAK,IAAI,GAAI,CAAC,CAAA;QAEjD,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,0CAA0C,CAAC,CAAA;IAClF,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,IAAI,GAAG;YACX,GAAG,EAAE,qBAAqB;SAC3B,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,IAAI,OAAK,IAAI,GAAI,CAAC,CAAA;QAEjD,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,uBAAuB,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {Link} from './Link.js'\nimport {renderString} from '../../ui.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('Link', async () => {\n test(\"renders correctly with a fallback for terminals that don't support hyperlinks\", async () => {\n const link = {\n url: 'https://example.com',\n label: 'Example',\n }\n\n const {output} = renderString(<Link {...link} />)\n\n expect(output).toMatchInlineSnapshot('\"Example \u001b[2m(https://example.com)\u001b[22m\"')\n })\n\n test(\"it doesn't render a fallback if only url is passed\", async () => {\n const link = {\n url: 'https://example.com',\n }\n\n const {output} = renderString(<Link {...link} />)\n\n expect(output).toMatchInlineSnapshot('\"https://example.com\"')\n })\n})\n"]}
|
|
@@ -8,10 +8,10 @@ const DOT = '•';
|
|
|
8
8
|
*/
|
|
9
9
|
const List = ({ title, items, ordered = false }) => {
|
|
10
10
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
11
|
-
React.createElement(Text, {
|
|
11
|
+
title && React.createElement(Text, { bold: true }, title),
|
|
12
12
|
items.map((item, index) => (React.createElement(Box, { key: index },
|
|
13
13
|
React.createElement(Box, null,
|
|
14
|
-
React.createElement(Text,
|
|
14
|
+
React.createElement(Text, null, ` ${ordered ? `${index + 1}.` : DOT}`)),
|
|
15
15
|
React.createElement(Box, { flexGrow: 1, marginLeft: 1 },
|
|
16
16
|
React.createElement(TokenizedText, { item: item })))))));
|
|
17
17
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"List.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/List.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,aAAa,EAAC,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAC,GAAG,EAAE,IAAI,EAAC,MAAM,KAAK,CAAA;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,MAAM,GAAG,GAAG,GAAG,CAAA;AAEf;;;GAGG;AACH,MAAM,IAAI,GAAoB,CAAC,EAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"List.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/List.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,aAAa,EAAC,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAC,GAAG,EAAE,IAAI,EAAC,MAAM,KAAK,CAAA;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,MAAM,GAAG,GAAG,GAAG,CAAA;AAEf;;;GAGG;AACH,MAAM,IAAI,GAAoB,CAAC,EAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,EAAC,EAAe,EAAE;IAC7E,OAAO,CACL,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;QACxB,KAAK,IAAI,oBAAC,IAAI,IAAC,IAAI,UAAE,KAAK,CAAQ;QAClC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,oBAAC,GAAG,IAAC,GAAG,EAAE,KAAK;YACb,oBAAC,GAAG;gBACF,oBAAC,IAAI,QAAE,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAQ,CACjD;YAEN,oBAAC,GAAG,IAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;gBAC7B,oBAAC,aAAa,IAAC,IAAI,EAAE,IAAI,GAAI,CACzB,CACF,CACP,CAAC,CACE,CACP,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAC,IAAI,EAAC,CAAA","sourcesContent":["import {TokenItem, TokenizedText} from './TokenizedText.js'\nimport {Box, Text} from 'ink'\nimport React from 'react'\n\ninterface Props {\n title?: string\n items: TokenItem[]\n ordered?: boolean\n}\n\nconst DOT = '•'\n\n/**\n * `List` displays an unordered or ordered list with text aligned with the bullet point\n * and wrapped to the container width.\n */\nconst List: React.FC<Props> = ({title, items, ordered = false}): JSX.Element => {\n return (\n <Box flexDirection=\"column\">\n {title && <Text bold>{title}</Text>}\n {items.map((item, index) => (\n <Box key={index}>\n <Box>\n <Text>{` ${ordered ? `${index + 1}.` : DOT}`}</Text>\n </Box>\n\n <Box flexGrow={1} marginLeft={1}>\n <TokenizedText item={item} />\n </Box>\n </Box>\n ))}\n </Box>\n )\n}\n\nexport {List}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { List } from './List.js';
|
|
2
|
+
import { renderString } from '../../ui.js';
|
|
3
|
+
import { unstyled } from '../../../../output.js';
|
|
4
|
+
import { describe, expect, test } from 'vitest';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
describe('List', async () => {
|
|
7
|
+
test('renders unordered items', async () => {
|
|
8
|
+
const options = {
|
|
9
|
+
title: 'List title',
|
|
10
|
+
items: ['Item 1', 'Item 2', 'Item 3'],
|
|
11
|
+
ordered: false,
|
|
12
|
+
};
|
|
13
|
+
const { output } = renderString(React.createElement(List, { ...options }));
|
|
14
|
+
expect(unstyled(output)).toMatchInlineSnapshot(`
|
|
15
|
+
"List title
|
|
16
|
+
• Item 1
|
|
17
|
+
• Item 2
|
|
18
|
+
• Item 3"
|
|
19
|
+
`);
|
|
20
|
+
});
|
|
21
|
+
test('renders ordered items', async () => {
|
|
22
|
+
const options = {
|
|
23
|
+
items: ['Item 1', 'Item 2', 'Item 3'],
|
|
24
|
+
ordered: true,
|
|
25
|
+
};
|
|
26
|
+
const { output } = renderString(React.createElement(List, { ...options }));
|
|
27
|
+
expect(unstyled(output)).toMatchInlineSnapshot(`
|
|
28
|
+
" 1. Item 1
|
|
29
|
+
2. Item 2
|
|
30
|
+
3. Item 3"
|
|
31
|
+
`);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=List.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"List.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/List.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,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,MAAM,EAAE,KAAK,IAAI,EAAE;IAC1B,IAAI,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,OAAO,GAAG;YACd,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACrC,OAAO,EAAE,KAAK;SACf,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,IAAI,OAAK,OAAO,GAAI,CAAC,CAAA;QAEpD,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;KAK/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,OAAO,GAAG;YACd,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACrC,OAAO,EAAE,IAAI;SACd,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,IAAI,OAAK,OAAO,GAAI,CAAC,CAAA;QAEpD,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;KAI/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {List} from './List.js'\nimport {renderString} from '../../ui.js'\nimport {unstyled} from '../../../../output.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('List', async () => {\n test('renders unordered items', async () => {\n const options = {\n title: 'List title',\n items: ['Item 1', 'Item 2', 'Item 3'],\n ordered: false,\n }\n\n const {output} = renderString(<List {...options} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"List title\n • Item 1\n • Item 2\n • Item 3\"\n `)\n })\n\n test('renders ordered items', async () => {\n const options = {\n items: ['Item 1', 'Item 2', 'Item 3'],\n ordered: true,\n }\n\n const {output} = renderString(<List {...options} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \" 1. Item 1\n 2. Item 2\n 3. Item 3\"\n `)\n })\n})\n"]}
|
|
@@ -11,7 +11,19 @@ interface LinkToken {
|
|
|
11
11
|
interface CharToken {
|
|
12
12
|
char: string;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
interface UserInputToken {
|
|
15
|
+
userInput: string;
|
|
16
|
+
}
|
|
17
|
+
interface FilePathToken {
|
|
18
|
+
filePath: string;
|
|
19
|
+
}
|
|
20
|
+
interface ListToken {
|
|
21
|
+
list: {
|
|
22
|
+
items: TokenItem[];
|
|
23
|
+
ordered?: boolean;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
declare type Token = string | CommandToken | LinkToken | CharToken | UserInputToken | FilePathToken | ListToken;
|
|
15
27
|
export declare type TokenItem = Token | Token[];
|
|
16
28
|
interface Props {
|
|
17
29
|
item: TokenItem;
|
|
@@ -1,14 +1,38 @@
|
|
|
1
1
|
import { Command } from './Command.js';
|
|
2
2
|
import { Link } from './Link.js';
|
|
3
|
-
import {
|
|
3
|
+
import { List } from './List.js';
|
|
4
|
+
import { UserInput } from './UserInput.js';
|
|
5
|
+
import { FilePath } from './FilePath.js';
|
|
6
|
+
import { Box, Text } from 'ink';
|
|
4
7
|
import React from 'react';
|
|
8
|
+
function tokenToBlock(token) {
|
|
9
|
+
return {
|
|
10
|
+
display: typeof token !== 'string' && 'list' in token ? 'block' : 'inline',
|
|
11
|
+
value: token,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function splitByDisplayType(acc, item) {
|
|
15
|
+
if (item.display === 'block') {
|
|
16
|
+
acc.push([item]);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const last = acc[acc.length - 1];
|
|
20
|
+
if (last && last[0].display === 'inline') {
|
|
21
|
+
last.push(item);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
acc.push([item]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return acc;
|
|
28
|
+
}
|
|
5
29
|
/**
|
|
6
30
|
* `TokenizedText` renders a text string with tokens that can be either strings,
|
|
7
31
|
* links, and commands.
|
|
8
32
|
*/
|
|
9
33
|
const TokenizedText = ({ item }) => {
|
|
10
34
|
if (typeof item === 'string') {
|
|
11
|
-
return React.createElement(Text,
|
|
35
|
+
return React.createElement(Text, null, item);
|
|
12
36
|
}
|
|
13
37
|
else if ('command' in item) {
|
|
14
38
|
return React.createElement(Command, { command: item.command });
|
|
@@ -17,12 +41,29 @@ const TokenizedText = ({ item }) => {
|
|
|
17
41
|
return React.createElement(Link, { ...item.link });
|
|
18
42
|
}
|
|
19
43
|
else if ('char' in item) {
|
|
20
|
-
return React.createElement(Text,
|
|
44
|
+
return React.createElement(Text, null, item.char[0]);
|
|
45
|
+
}
|
|
46
|
+
else if ('userInput' in item) {
|
|
47
|
+
return React.createElement(UserInput, { userInput: item.userInput });
|
|
48
|
+
}
|
|
49
|
+
else if ('filePath' in item) {
|
|
50
|
+
return React.createElement(FilePath, { filePath: item.filePath });
|
|
51
|
+
}
|
|
52
|
+
else if ('list' in item) {
|
|
53
|
+
return React.createElement(List, { ...item.list });
|
|
21
54
|
}
|
|
22
55
|
else {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
56
|
+
const groupedItems = item.map(tokenToBlock).reduce(splitByDisplayType, []);
|
|
57
|
+
return (React.createElement(Box, { flexDirection: "column" }, groupedItems.map((items, groupIndex) => {
|
|
58
|
+
if (items[0].display === 'inline') {
|
|
59
|
+
return (React.createElement(Text, { key: groupIndex }, items.map((item, itemIndex) => (React.createElement(Text, { key: itemIndex },
|
|
60
|
+
itemIndex !== 0 && !(typeof item.value !== 'string' && 'char' in item.value) && React.createElement(Text, null, " "),
|
|
61
|
+
React.createElement(TokenizedText, { item: item.value }))))));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
return React.createElement(List, { key: groupIndex, items: items[0].value.list.items });
|
|
65
|
+
}
|
|
66
|
+
})));
|
|
26
67
|
}
|
|
27
68
|
};
|
|
28
69
|
export { TokenizedText };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenizedText.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TokenizedText.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAA;AACpC,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,IAAI,EAAC,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"TokenizedText.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TokenizedText.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Command} from './Command.js'\nimport {Link} from './Link.js'\nimport {List} from './List.js'\nimport {UserInput} from './UserInput.js'\nimport {FilePath} from './FilePath.js'\nimport {Box, Text} from 'ink'\nimport React from 'react'\n\ninterface CommandToken {\n command: string\n}\n\ninterface LinkToken {\n link: {\n label?: string\n url: string\n }\n}\n\ninterface CharToken {\n char: string\n}\n\ninterface UserInputToken {\n userInput: string\n}\n\ninterface FilePathToken {\n filePath: string\n}\n\ninterface ListToken {\n list: {\n items: TokenItem[]\n ordered?: boolean\n }\n}\n\ntype Token = string | CommandToken | LinkToken | CharToken | UserInputToken | FilePathToken | ListToken\nexport type TokenItem = Token | Token[]\n\ntype DisplayType = 'block' | 'inline'\ninterface Block {\n display: DisplayType\n value: Token\n}\n\nfunction tokenToBlock(token: Token): Block {\n return {\n display: typeof token !== 'string' && 'list' in token ? 'block' : 'inline',\n value: token,\n }\n}\n\nfunction splitByDisplayType(acc: Block[][], item: Block) {\n if (item.display === 'block') {\n acc.push([item])\n } else {\n const last = acc[acc.length - 1]\n if (last && last[0]!.display === 'inline') {\n last.push(item)\n } else {\n acc.push([item])\n }\n }\n return acc\n}\n\ninterface Props {\n item: TokenItem\n}\n\n/**\n * `TokenizedText` renders a text string with tokens that can be either strings,\n * links, and commands.\n */\nconst TokenizedText: React.FC<Props> = ({item}) => {\n if (typeof item === 'string') {\n return <Text>{item}</Text>\n } else if ('command' in item) {\n return <Command command={item.command} />\n } else if ('link' in item) {\n return <Link {...item.link} />\n } else if ('char' in item) {\n return <Text>{item.char[0]}</Text>\n } else if ('userInput' in item) {\n return <UserInput userInput={item.userInput} />\n } else if ('filePath' in item) {\n return <FilePath filePath={item.filePath} />\n } else if ('list' in item) {\n return <List {...item.list} />\n } else {\n const groupedItems = item.map(tokenToBlock).reduce(splitByDisplayType, [])\n\n return (\n <Box flexDirection=\"column\">\n {groupedItems.map((items, groupIndex) => {\n if (items[0]!.display === 'inline') {\n return (\n <Text key={groupIndex}>\n {items.map((item, itemIndex) => (\n <Text key={itemIndex}>\n {itemIndex !== 0 && !(typeof item.value !== 'string' && 'char' in item.value) && <Text> </Text>}\n <TokenizedText item={item.value} />\n </Text>\n ))}\n </Text>\n )\n } else {\n return <List key={groupIndex} items={(items[0]!.value as ListToken).list.items} />\n }\n })}\n </Box>\n )\n }\n}\n\nexport {TokenizedText}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { TokenizedText } from './TokenizedText.js';
|
|
2
|
+
import { renderString } from '../../ui.js';
|
|
3
|
+
import { unstyled } from '../../../../output.js';
|
|
4
|
+
import { describe, expect, test } from 'vitest';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
describe('TokenizedText', async () => {
|
|
7
|
+
test('renders arrays of items separated by spaces', async () => {
|
|
8
|
+
const item = [
|
|
9
|
+
'Run',
|
|
10
|
+
{
|
|
11
|
+
command: 'cd verification-app',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
link: {
|
|
15
|
+
url: 'https://example.com',
|
|
16
|
+
label: 'Example',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
char: '!',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
userInput: 'my-app',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
list: {
|
|
27
|
+
items: ['Item 1', 'Item 2', 'Item 3'],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
filePath: 'src/this/is/a/test.js',
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
const { output } = renderString(React.createElement(TokenizedText, { item: item }));
|
|
35
|
+
expect(unstyled(output)).toMatchInlineSnapshot(`
|
|
36
|
+
"Run \`cd verification-app\` Example (https://example.com)! my-app
|
|
37
|
+
• Item 1
|
|
38
|
+
• Item 2
|
|
39
|
+
• Item 3
|
|
40
|
+
\\"src/this/is/a/test.js\\""
|
|
41
|
+
`);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=TokenizedText.test.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
userInput: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* `UserInput` displays some text that represents input from the user.
|
|
7
|
+
* For example an answer to a selection prompt.
|
|
8
|
+
*/
|
|
9
|
+
declare const UserInput: React.FC<Props>;
|
|
10
|
+
export { UserInput };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Text } from 'ink';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* `UserInput` displays some text that represents input from the user.
|
|
5
|
+
* For example an answer to a selection prompt.
|
|
6
|
+
*/
|
|
7
|
+
const UserInput = ({ userInput }) => {
|
|
8
|
+
return React.createElement(Text, { color: "cyan" }, userInput);
|
|
9
|
+
};
|
|
10
|
+
export { UserInput };
|
|
11
|
+
//# sourceMappingURL=UserInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserInput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/UserInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,KAAK,CAAA;AACxB,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB;;;GAGG;AACH,MAAM,SAAS,GAAoB,CAAC,EAAC,SAAS,EAAiC,EAAe,EAAE;IAC9F,OAAO,oBAAC,IAAI,IAAC,KAAK,EAAC,MAAM,IAAE,SAAS,CAAQ,CAAA;AAC9C,CAAC,CAAA;AAED,OAAO,EAAC,SAAS,EAAC,CAAA","sourcesContent":["import {Text} from 'ink'\nimport React from 'react'\n\ninterface Props {\n userInput: string\n}\n\n/**\n * `UserInput` displays some text that represents input from the user.\n * For example an answer to a selection prompt.\n */\nconst UserInput: React.FC<Props> = ({userInput}: React.PropsWithChildren<Props>): JSX.Element => {\n return <Text color=\"cyan\">{userInput}</Text>\n}\n\nexport {UserInput}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { UserInput } from './UserInput.js';
|
|
2
|
+
import { renderString } from '../../ui.js';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
describe('UserInput', async () => {
|
|
6
|
+
test('renders correctly', async () => {
|
|
7
|
+
const { output } = renderString(React.createElement(UserInput, { userInput: "my-app" }));
|
|
8
|
+
expect(output).toMatchInlineSnapshot('"[36mmy-app[39m"');
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=UserInput.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserInput.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/UserInput.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAA;AACxC,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,WAAW,EAAE,KAAK,IAAI,EAAE;IAC/B,IAAI,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,SAAS,IAAC,SAAS,EAAC,QAAQ,GAAG,CAAC,CAAA;QAE/D,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,oBAAoB,CAAC,CAAA;IAC5D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {UserInput} from './UserInput.js'\nimport {renderString} from '../../ui.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('UserInput', async () => {\n test('renders correctly', async () => {\n const {output} = renderString(<UserInput userInput=\"my-app\" />)\n\n expect(output).toMatchInlineSnapshot('\"\u001b[36mmy-app\u001b[39m\"')\n })\n})\n"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Result } from './result.js';
|
|
2
|
+
export interface GithubRelease {
|
|
3
|
+
id: number;
|
|
4
|
+
url: string;
|
|
5
|
+
tag_name: string;
|
|
6
|
+
name: string;
|
|
7
|
+
body: string;
|
|
8
|
+
draft: boolean;
|
|
9
|
+
prerelease: boolean;
|
|
10
|
+
created_at: string;
|
|
11
|
+
published_at: string;
|
|
12
|
+
tarball_url: string;
|
|
13
|
+
}
|
|
14
|
+
interface GetLatestGitHubReleaseOptions {
|
|
15
|
+
filter: (release: GithubRelease) => boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Given a GitHub repository it obtains the latest release.
|
|
19
|
+
* @param owner - Repository owner (e.g., shopify)
|
|
20
|
+
* @param repo - Repository name (e.g., cli)
|
|
21
|
+
* @param options - Options
|
|
22
|
+
*/
|
|
23
|
+
export declare function getLatestGitHubRelease(owner: string, repo: string, options?: GetLatestGitHubReleaseOptions): Promise<GithubRelease>;
|
|
24
|
+
interface ParseRepositoryURLOutput {
|
|
25
|
+
full: string;
|
|
26
|
+
site: string;
|
|
27
|
+
user: string;
|
|
28
|
+
name: string;
|
|
29
|
+
ref: string;
|
|
30
|
+
subDirectory: string;
|
|
31
|
+
ssh: string;
|
|
32
|
+
http: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Given a GitHub repository URL, it parses it and returns its coomponents.
|
|
36
|
+
* @param url - The GitHub repository URL
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseGitHubRepositoryURL(url: string): Result<ParseRepositoryURLOutput, Error>;
|
|
39
|
+
export interface GithubRepositoryReference {
|
|
40
|
+
baseURL: string;
|
|
41
|
+
branch?: string;
|
|
42
|
+
filePath?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Given a GitHub repository URL it parses it and extracts the branch, file path,
|
|
46
|
+
* and base URL components
|
|
47
|
+
* @param reference - A GitHub repository URL (e.g. https://github.com/Shopify/cli/blob/main/package.json)
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseGitHubRepositoryReference(reference: string): GithubRepositoryReference;
|
|
50
|
+
export {};
|
|
@@ -1,25 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { content, debug } from '
|
|
1
|
+
import { err, ok } from './result.js';
|
|
2
|
+
import { fetch } from '../../http.js';
|
|
3
|
+
import { content, debug } from '../../output.js';
|
|
4
4
|
class GitHubClientError extends Error {
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
6
|
constructor(url, statusCode, bodyJson) {
|
|
7
7
|
super(`The request to GitHub API URL ${url} failed with status code ${statusCode} and the following error message: ${bodyJson.message}`);
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Given a GitHub repository it obtains the latest release.
|
|
12
|
+
* @param owner - Repository owner (e.g., shopify)
|
|
13
|
+
* @param repo - Repository name (e.g., cli)
|
|
14
|
+
* @param options - Options
|
|
15
|
+
*/
|
|
16
|
+
export async function getLatestGitHubRelease(owner, repo, options = { filter: () => true }) {
|
|
17
|
+
debug(content `Getting the latest release of GitHub repository ${owner}/${repo}...`);
|
|
18
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/releases`;
|
|
13
19
|
const fetchResult = await fetch(url);
|
|
14
20
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
21
|
const jsonBody = await fetchResult.json();
|
|
16
22
|
if (fetchResult.status !== 200) {
|
|
17
23
|
throw new GitHubClientError(url, fetchResult.status, jsonBody);
|
|
18
24
|
}
|
|
19
|
-
return jsonBody.find(filter);
|
|
25
|
+
return jsonBody.find(options.filter);
|
|
20
26
|
}
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Given a GitHub repository URL, it parses it and returns its coomponents.
|
|
29
|
+
* @param url - The GitHub repository URL
|
|
30
|
+
*/
|
|
31
|
+
export function parseGitHubRepositoryURL(url) {
|
|
32
|
+
const match = /^(?:(?:https:\/\/)?([^:/]+\.[^:/]+)\/|git@([^:/]+)[:/]|([^/]+):)?([^/\s]+)\/([^/\s#]+)(?:((?:\/[^/\s#]+)+))?(?:\/)?(?:#(.+))?/.exec(url);
|
|
23
33
|
if (!match) {
|
|
24
34
|
const exampleFormats = [
|
|
25
35
|
'github:user/repo',
|
|
@@ -28,7 +38,7 @@ export function parseRepoUrl(src) {
|
|
|
28
38
|
'user/repo#dev',
|
|
29
39
|
'https://github.com/user/repo',
|
|
30
40
|
];
|
|
31
|
-
|
|
41
|
+
return err(new Error(`Parsing the url ${url} failed. Supported formats are ${exampleFormats.join(', ')}.`));
|
|
32
42
|
}
|
|
33
43
|
const site = match[1] || match[2] || match[3] || 'github.com';
|
|
34
44
|
const normalizedSite = site === 'github' ? 'github.com' : site;
|
|
@@ -40,15 +50,20 @@ export function parseRepoUrl(src) {
|
|
|
40
50
|
const ssh = `git@${normalizedSite}:${user}/${name}`;
|
|
41
51
|
const http = `https://${normalizedSite}/${user}/${name}`;
|
|
42
52
|
const full = ['https:/', normalizedSite, user, name, subDirectory].join('/').concat(branch);
|
|
43
|
-
return { full, site: normalizedSite, user, name, ref, subDirectory, ssh, http };
|
|
53
|
+
return ok({ full, site: normalizedSite, user, name, ref, subDirectory, ssh, http });
|
|
44
54
|
}
|
|
45
|
-
|
|
46
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Given a GitHub repository URL it parses it and extracts the branch, file path,
|
|
57
|
+
* and base URL components
|
|
58
|
+
* @param reference - A GitHub repository URL (e.g. https://github.com/Shopify/cli/blob/main/package.json)
|
|
59
|
+
*/
|
|
60
|
+
export function parseGitHubRepositoryReference(reference) {
|
|
61
|
+
const url = new URL(reference);
|
|
47
62
|
const branch = url.hash ? url.hash.slice(1) : undefined;
|
|
48
63
|
const [_, user, repo, ...repoPath] = url.pathname.split('/');
|
|
49
64
|
const filePath = repoPath.length > 0 ? repoPath.join('/') : undefined;
|
|
50
65
|
return {
|
|
51
|
-
|
|
66
|
+
baseURL: `${url.origin}/${user}/${repo}`,
|
|
52
67
|
branch,
|
|
53
68
|
filePath,
|
|
54
69
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../../src/public/node/github.ts"],"names":[],"mappings":"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","sourcesContent":["import {err, ok, Result} from './result.js'\nimport {fetch} from '../../http.js'\nimport {content, debug} from '../../output.js'\n\nclass GitHubClientError extends Error {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n constructor(url: string, statusCode: number, bodyJson: any) {\n super(\n `The request to GitHub API URL ${url} failed with status code ${statusCode} and the following error message: ${bodyJson.message}`,\n )\n }\n}\n\nexport interface GithubRelease {\n id: number\n url: string\n tag_name: string\n name: string\n body: string\n draft: boolean\n prerelease: boolean\n created_at: string\n published_at: string\n tarball_url: string\n}\n\ninterface GetLatestGitHubReleaseOptions {\n filter: (release: GithubRelease) => boolean\n}\n\n/**\n * Given a GitHub repository it obtains the latest release.\n * @param owner - Repository owner (e.g., shopify)\n * @param repo - Repository name (e.g., cli)\n * @param options - Options\n */\nexport async function getLatestGitHubRelease(\n owner: string,\n repo: string,\n options: GetLatestGitHubReleaseOptions = {filter: () => true},\n): Promise<GithubRelease> {\n debug(content`Getting the latest release of GitHub repository ${owner}/${repo}...`)\n const url = `https://api.github.com/repos/${owner}/${repo}/releases`\n const fetchResult = await fetch(url)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const jsonBody: any = await fetchResult.json()\n\n if (fetchResult.status !== 200) {\n throw new GitHubClientError(url, fetchResult.status, jsonBody)\n }\n\n return jsonBody.find(options.filter)\n}\n\ninterface ParseRepositoryURLOutput {\n full: string\n site: string\n user: string\n name: string\n ref: string\n subDirectory: string\n ssh: string\n http: string\n}\n\n/**\n * Given a GitHub repository URL, it parses it and returns its coomponents.\n * @param url - The GitHub repository URL\n */\nexport function parseGitHubRepositoryURL(url: string): Result<ParseRepositoryURLOutput, Error> {\n const match =\n /^(?:(?:https:\\/\\/)?([^:/]+\\.[^:/]+)\\/|git@([^:/]+)[:/]|([^/]+):)?([^/\\s]+)\\/([^/\\s#]+)(?:((?:\\/[^/\\s#]+)+))?(?:\\/)?(?:#(.+))?/.exec(\n url,\n )\n\n if (!match) {\n const exampleFormats = [\n 'github:user/repo',\n 'user/repo/subdirectory',\n 'git@github.com:user/repo',\n 'user/repo#dev',\n 'https://github.com/user/repo',\n ]\n\n return err(new Error(`Parsing the url ${url} failed. Supported formats are ${exampleFormats.join(', ')}.`))\n }\n\n const site = match[1] || match[2] || match[3] || 'github.com'\n const normalizedSite = site === 'github' ? 'github.com' : site\n const user = match[4]!\n const name = match[5]!.replace(/\\.git$/, '')\n const subDirectory = match[6]?.slice(1)!\n const ref = match[7]!\n const branch = ref ? `#${ref}` : ''\n const ssh = `git@${normalizedSite}:${user}/${name}`\n const http = `https://${normalizedSite}/${user}/${name}`\n const full = ['https:/', normalizedSite, user, name, subDirectory].join('/').concat(branch)\n\n return ok({full, site: normalizedSite, user, name, ref, subDirectory, ssh, http})\n}\n\nexport interface GithubRepositoryReference {\n baseURL: string\n branch?: string\n filePath?: string\n}\n\n/**\n * Given a GitHub repository URL it parses it and extracts the branch, file path,\n * and base URL components\n * @param reference - A GitHub repository URL (e.g. https://github.com/Shopify/cli/blob/main/package.json)\n */\nexport function parseGitHubRepositoryReference(reference: string): GithubRepositoryReference {\n const url = new URL(reference)\n const branch = url.hash ? url.hash.slice(1) : undefined\n const [_, user, repo, ...repoPath] = url.pathname.split('/')\n const filePath = repoPath.length > 0 ? repoPath.join('/') : undefined\n\n return {\n baseURL: `${url.origin}/${user}/${repo}`,\n branch,\n filePath,\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Result } from '
|
|
1
|
+
import { Result } from '../result.js';
|
|
2
2
|
import { FanoutHookFunction, PluginReturnsForHook } from '../../../plugins.js';
|
|
3
3
|
import { ExtendableError } from '../../../error.js';
|
|
4
4
|
export declare type TunnelErrorType = 'invalid-provider' | 'tunnel-already-running' | 'wrong-credentials' | 'unknown';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../../../src/public/node/plugins/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAS,MAAM,
|
|
1
|
+
{"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../../../src/public/node/plugins/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAS,MAAM,cAAc,CAAA;AAExC,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AAGjD,MAAM,OAAO,WAAY,SAAQ,eAAe;IAE9C,YAAY,IAAqB,EAAE,OAAgB;QACjD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AA2BD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAqB,EAA0B,EAAE;IAC9E,OAAO,KAAK,IAAI,EAAE,CAAC,KAAK,CAAA;AAC1B,CAAC,CAAA;AACD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAsD,EAAuB,EAAE;IACzG,OAAO,KAAK,EAAE,MAAwC,EAA8B,EAAE;QACpF,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ;YAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAA;QACzF,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {err, Result} from '../result.js'\nimport {FanoutHookFunction, PluginReturnsForHook} from '../../../plugins.js'\nimport {ExtendableError} from '../../../error.js'\n\nexport type TunnelErrorType = 'invalid-provider' | 'tunnel-already-running' | 'wrong-credentials' | 'unknown'\nexport class TunnelError extends ExtendableError {\n type: TunnelErrorType\n constructor(type: TunnelErrorType, message?: string) {\n super(message)\n this.type = type\n }\n}\n\n/**\n * Tunnel Plugins types\n *\n * Any plugin that provides tunnel functionality should implement `defineProvider`and `startTunnel`\n */\nexport interface HookReturnPerTunnelPlugin {\n tunnel_start: {\n options: {port: number; provider: string}\n pluginReturns: {\n [pluginName: string]: Result<{url: string}, TunnelError>\n }\n }\n tunnel_provider: {\n options: {[key: string]: never}\n pluginReturns: {\n [pluginName: string]: {name: string}\n }\n }\n}\n\nexport type TunnelProviderFunction = FanoutHookFunction<'tunnel_provider', ''>\nexport type TunnelStartFunction = FanoutHookFunction<'tunnel_start', ''>\nexport type TunnelStartReturn = PluginReturnsForHook<'tunnel_start', ''>\nexport type TunnelStartAction = (port: number) => Promise<TunnelStartReturn>\n\nexport const defineProvider = (input: {name: string}): TunnelProviderFunction => {\n return async () => input\n}\nexport const startTunnel = (options: {provider: string; action: TunnelStartAction}): TunnelStartFunction => {\n return async (inputs: {provider: string; port: number}): Promise<TunnelStartReturn> => {\n if (inputs.provider !== options.provider) return err(new TunnelError('invalid-provider'))\n return options.action(inputs.port)\n }\n}\n"]}
|