@shopify/cli-kit 4.0.0 → 4.2.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/README.md +2 -2
- package/assets/graphiql/favicon.ico +0 -0
- package/assets/graphiql/style.css +58 -0
- package/dist/private/common/array.js +2 -1
- package/dist/private/common/array.js.map +1 -1
- package/dist/private/node/api/headers.js +6 -3
- package/dist/private/node/api/headers.js.map +1 -1
- package/dist/private/node/constants.d.ts +0 -1
- package/dist/private/node/constants.js +0 -1
- package/dist/private/node/constants.js.map +1 -1
- package/dist/private/node/session/device-authorization.js +4 -16
- package/dist/private/node/session/device-authorization.js.map +1 -1
- package/dist/private/node/ui.js +4 -1
- package/dist/private/node/ui.js.map +1 -1
- package/dist/public/common/gid.d.ts +24 -0
- package/dist/public/common/gid.js +32 -0
- package/dist/public/common/gid.js.map +1 -0
- package/dist/public/common/string.js +7 -6
- package/dist/public/common/string.js.map +1 -1
- package/dist/public/common/url.d.ts +16 -0
- package/dist/public/common/url.js +30 -0
- package/dist/public/common/url.js.map +1 -1
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/analytics.js +3 -5
- package/dist/public/node/analytics.js.map +1 -1
- package/dist/public/node/cli.d.ts +13 -0
- package/dist/public/node/cli.js +12 -0
- package/dist/public/node/cli.js.map +1 -1
- package/dist/public/node/context/local.d.ts +0 -7
- package/dist/public/node/context/local.js +18 -9
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/error-handler.js +1 -1
- package/dist/public/node/error-handler.js.map +1 -1
- package/dist/public/node/git.js +8 -1
- package/dist/public/node/git.js.map +1 -1
- package/dist/public/node/graphiql/server.d.ts +80 -0
- package/dist/public/node/graphiql/server.js +234 -0
- package/dist/public/node/graphiql/server.js.map +1 -0
- package/dist/public/node/graphiql/templates/graphiql.d.ts +12 -0
- package/dist/public/node/graphiql/templates/graphiql.js +314 -0
- package/dist/public/node/graphiql/templates/graphiql.js.map +1 -0
- package/dist/public/node/graphiql/templates/unauthorized.d.ts +5 -0
- package/dist/public/node/graphiql/templates/unauthorized.js +111 -0
- package/dist/public/node/graphiql/templates/unauthorized.js.map +1 -0
- package/dist/public/node/graphiql/utilities.d.ts +12 -0
- package/dist/public/node/graphiql/utilities.js +44 -0
- package/dist/public/node/graphiql/utilities.js.map +1 -0
- package/dist/public/node/graphql.d.ts +19 -0
- package/dist/public/node/graphql.js +41 -0
- package/dist/public/node/graphql.js.map +1 -0
- package/dist/public/node/hooks/postrun.js +12 -2
- package/dist/public/node/hooks/postrun.js.map +1 -1
- package/dist/public/node/http.js +27 -31
- package/dist/public/node/http.js.map +1 -1
- package/dist/public/node/import-extractor.js +4 -3
- package/dist/public/node/import-extractor.js.map +1 -1
- package/dist/public/node/metadata.d.ts +3 -0
- package/dist/public/node/metadata.js.map +1 -1
- package/dist/public/node/monorail.d.ts +2 -1
- package/dist/public/node/monorail.js +1 -1
- package/dist/public/node/monorail.js.map +1 -1
- package/dist/public/node/output.js +22 -11
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/system.js +5 -42
- package/dist/public/node/system.js.map +1 -1
- package/dist/public/node/tcp.js +11 -3
- package/dist/public/node/tcp.js.map +1 -1
- package/dist/public/node/themes/api.js +76 -4
- package/dist/public/node/themes/api.js.map +1 -1
- package/dist/public/node/toml/toml-file.d.ts +3 -2
- package/dist/public/node/toml/toml-file.js +3 -2
- package/dist/public/node/toml/toml-file.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +34 -29
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License">
|
|
6
6
|
<a href="https://github.com/Shopify/cli/actions/workflows/shopify-cli.yml"></a>
|
|
7
7
|
|
|
8
|
-
With the Shopify command line interface (Shopify CLI
|
|
8
|
+
With the Shopify command line interface (Shopify CLI), you can:
|
|
9
9
|
- initialize, build, dev, and deploy Shopify apps, extensions, functions and themes
|
|
10
10
|
- build custom storefronts and manage their hosting
|
|
11
11
|
|
|
@@ -39,7 +39,7 @@ To work with themes, the CLI needs to be installed globally with:
|
|
|
39
39
|
|
|
40
40
|
- `npm install -g @shopify/cli`
|
|
41
41
|
|
|
42
|
-
You can also
|
|
42
|
+
You can also install it through Homebrew on macOS: `brew tap shopify/shopify && brew install shopify-cli`
|
|
43
43
|
|
|
44
44
|
Learn more in the docs: [Shopify CLI for themes](https://shopify.dev/docs/storefronts/themes/tools/cli)
|
|
45
45
|
|
|
Binary file
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
html {
|
|
2
|
+
font-family: -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif;
|
|
3
|
+
text-size-adjust: 100%;
|
|
4
|
+
text-rendering: optimizeLegibility;
|
|
5
|
+
-webkit-font-smoothing: antialiased;
|
|
6
|
+
-moz-osx-font-smoothing: grayscale;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
body {
|
|
10
|
+
font-size: 26px;
|
|
11
|
+
line-height: normal;
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
button, input, optgroup, select, textarea {
|
|
17
|
+
font-family: inherit;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
h1 {
|
|
21
|
+
font-weight: 600;
|
|
22
|
+
font-size: 1em;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
p {
|
|
26
|
+
font-weight: 400;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.body-success {
|
|
30
|
+
color: #F6F6F7;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.body-error {
|
|
34
|
+
color: #202223;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.app-success {
|
|
38
|
+
width: 100vw;
|
|
39
|
+
height: 100vh;
|
|
40
|
+
background-color: #054A49;
|
|
41
|
+
display: flex;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.app-error {
|
|
45
|
+
width: 100vw;
|
|
46
|
+
height: 100vh;
|
|
47
|
+
background-color: #F6F6F7;
|
|
48
|
+
display: flex;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.container {
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
justify-content: center;
|
|
55
|
+
width: 100%;
|
|
56
|
+
height: 100%;
|
|
57
|
+
padding-left: 7.5em;
|
|
58
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { uniq } from '../../public/common/array.js';
|
|
1
2
|
export function unionArrayStrategy(destinationArray, sourceArray) {
|
|
2
|
-
return
|
|
3
|
+
return uniq([...destinationArray, ...sourceArray]);
|
|
3
4
|
}
|
|
4
5
|
//# sourceMappingURL=array.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.js","sourceRoot":"","sources":["../../../src/private/common/array.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,gBAA2B,EAAE,WAAsB;IACpF,OAAO,
|
|
1
|
+
{"version":3,"file":"array.js","sourceRoot":"","sources":["../../../src/private/common/array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,8BAA8B,CAAA;AAEjD,MAAM,UAAU,kBAAkB,CAAC,gBAA2B,EAAE,WAAsB;IACpF,OAAO,IAAI,CAAC,CAAC,GAAG,gBAAgB,EAAE,GAAG,WAAW,CAAC,CAAC,CAAA;AACpD,CAAC","sourcesContent":["import {uniq} from '../../public/common/array.js'\n\nexport function unionArrayStrategy(destinationArray: unknown[], sourceArray: unknown[]): unknown[] {\n return uniq([...destinationArray, ...sourceArray])\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CLI_KIT_VERSION } from '../../../public/common/version.js';
|
|
2
|
-
import { firstPartyDev } from '../../../public/node/context/local.js';
|
|
2
|
+
import { firstPartyDev, isUnitTest, isVerbose } from '../../../public/node/context/local.js';
|
|
3
3
|
import { AbortError } from '../../../public/node/error.js';
|
|
4
4
|
import https from 'https';
|
|
5
5
|
class RequestClientError extends AbortError {
|
|
@@ -19,16 +19,19 @@ export class GraphQLClientError extends RequestClientError {
|
|
|
19
19
|
this.stack = undefined;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
const SENSITIVE_HEADERS = ['token', 'authorization', 'subject_token', 'cookie'];
|
|
22
23
|
/**
|
|
23
24
|
* Removes the sensitive data from the headers and outputs them as a string.
|
|
24
25
|
* @param headers - HTTP headers.
|
|
25
26
|
* @returns A sanitized version of the headers as a string.
|
|
26
27
|
*/
|
|
27
28
|
export function sanitizedHeadersOutput(headers) {
|
|
29
|
+
if (!isVerbose() && !isUnitTest()) {
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
28
32
|
const sanitized = {};
|
|
29
|
-
const keywords = ['token', 'authorization', 'subject_token', 'cookie'];
|
|
30
33
|
Object.keys(headers).forEach((header) => {
|
|
31
|
-
if (
|
|
34
|
+
if (SENSITIVE_HEADERS.find((keyword) => header.toLowerCase().includes(keyword)) === undefined) {
|
|
32
35
|
sanitized[header] = headers[header];
|
|
33
36
|
}
|
|
34
37
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../../src/private/node/api/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,mCAAmC,CAAA;AACjE,OAAO,EAAC,aAAa,EAAC,MAAM,uCAAuC,CAAA;
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../../src/private/node/api/headers.ts"],"names":[],"mappings":"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","sourcesContent":["import {CLI_KIT_VERSION} from '../../../public/common/version.js'\nimport {firstPartyDev, isUnitTest, isVerbose} from '../../../public/node/context/local.js'\nimport {AbortError} from '../../../public/node/error.js'\nimport https from 'https'\n\nclass RequestClientError extends AbortError {\n statusCode: number\n public constructor(message: string, statusCode: number) {\n const tryMessage =\n statusCode === 403\n ? 'Ensure you are using the correct account. You can switch with `shopify auth login`'\n : undefined\n super(message, tryMessage)\n this.statusCode = statusCode\n }\n}\nexport class GraphQLClientError extends RequestClientError {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n errors?: any[]\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public constructor(message: string, statusCode: number, errors?: any[]) {\n super(message, statusCode)\n this.errors = errors\n this.stack = undefined\n }\n}\n\nconst SENSITIVE_HEADERS = ['token', 'authorization', 'subject_token', 'cookie']\n\n/**\n * Removes the sensitive data from the headers and outputs them as a string.\n * @param headers - HTTP headers.\n * @returns A sanitized version of the headers as a string.\n */\nexport function sanitizedHeadersOutput(headers: Record<string, string>): string {\n if (!isVerbose() && !isUnitTest()) {\n return ''\n }\n\n const sanitized: Record<string, string> = {}\n Object.keys(headers).forEach((header) => {\n if (SENSITIVE_HEADERS.find((keyword) => header.toLowerCase().includes(keyword)) === undefined) {\n sanitized[header] = headers[header]!\n }\n })\n return Object.keys(sanitized)\n .map((header) => {\n return ` - ${header}: ${sanitized[header]}`\n })\n .join('\\n')\n}\n\nexport function buildHeaders(token?: string): Record<string, string> {\n const userAgent = `Shopify CLI; v=${CLI_KIT_VERSION}`\n\n const headers: Record<string, string> = {\n 'User-Agent': userAgent,\n 'Keep-Alive': 'timeout=30',\n // 'Sec-CH-UA': secCHUA, This header requires the Git sha.\n 'Sec-CH-UA-PLATFORM': process.platform,\n 'Content-Type': 'application/json',\n ...(firstPartyDev() && {'X-Shopify-Cli-Employee': '1'}),\n }\n if (token) {\n const authString = token.match(/^shp(at|ua|ca|tka)/) ? token : `Bearer ${token}`\n\n headers.authorization = authString\n headers['X-Shopify-Access-Token'] = authString\n }\n\n return headers\n}\n\n/**\n * This utility function returns the https.Agent to use for a given service.\n */\nexport async function httpsAgent(): Promise<https.Agent> {\n return new https.Agent({\n rejectUnauthorized: true,\n keepAlive: true,\n })\n}\n"]}
|
|
@@ -17,7 +17,6 @@ export const environmentVariables = {
|
|
|
17
17
|
enableCliRedirect: 'SHOPIFY_CLI_ENABLE_CLI_REDIRECT',
|
|
18
18
|
env: 'SHOPIFY_CLI_ENV',
|
|
19
19
|
firstPartyDev: 'SHOPIFY_CLI_1P_DEV',
|
|
20
|
-
hostedApps: 'HOSTED_APPS',
|
|
21
20
|
noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS',
|
|
22
21
|
optOutInstrumentation: 'OPT_OUT_INSTRUMENTATION',
|
|
23
22
|
appAutomationToken: 'SHOPIFY_APP_AUTOMATION_TOKEN',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/private/node/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAA;AAClD,OAAO,QAAQ,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,GAAG,aAAa,CAAA;AAEhC,MAAM,WAAW,GAAG,GAAG,EAAE;IACvB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IACjE,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,KAAK,CAAA;AACnC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE;IAC7B,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,GAAG,CAAA;AACjC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,kBAAkB,EAAE,kCAAkC;IACtD,gBAAgB,EAAE,gCAAgC;IAClD,UAAU,EAAE,yBAAyB;IACrC,MAAM,EAAE,oBAAoB;IAC5B,iBAAiB,EAAE,iCAAiC;IACpD,GAAG,EAAE,iBAAiB;IACtB,aAAa,EAAE,oBAAoB;IACnC,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/private/node/constants.ts"],"names":[],"mappings":"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","sourcesContent":["import {joinPath} from '../../public/node/path.js'\nimport envPaths from 'env-paths'\n\nconst identifier = 'shopify-cli'\n\nconst cacheFolder = () => {\n if (process.env.XDG_CACHE_HOME) return process.env.XDG_CACHE_HOME\n return envPaths(identifier).cache\n}\n\nexport const logsFolder = () => {\n return envPaths(identifier).log\n}\n\nexport const environmentVariables = {\n alwaysLogAnalytics: 'SHOPIFY_CLI_ALWAYS_LOG_ANALYTICS',\n alwaysLogMetrics: 'SHOPIFY_CLI_ALWAYS_LOG_METRICS',\n deviceAuth: 'SHOPIFY_CLI_DEVICE_AUTH',\n doctor: 'SHOPIFY_CLI_DOCTOR',\n enableCliRedirect: 'SHOPIFY_CLI_ENABLE_CLI_REDIRECT',\n env: 'SHOPIFY_CLI_ENV',\n firstPartyDev: 'SHOPIFY_CLI_1P_DEV',\n noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS',\n optOutInstrumentation: 'OPT_OUT_INSTRUMENTATION',\n appAutomationToken: 'SHOPIFY_APP_AUTOMATION_TOKEN',\n partnersToken: 'SHOPIFY_CLI_PARTNERS_TOKEN',\n runAsUser: 'SHOPIFY_RUN_AS_USER',\n serviceEnv: 'SHOPIFY_SERVICE_ENV',\n skipCliRedirect: 'SHOPIFY_CLI_SKIP_CLI_REDIRECT',\n spinInstance: 'SPIN_INSTANCE',\n themeToken: 'SHOPIFY_CLI_THEME_TOKEN',\n unitTest: 'SHOPIFY_UNIT_TEST',\n verbose: 'SHOPIFY_FLAG_VERBOSE',\n // Variables to detect if the CLI is running in a cloud environment\n codespaces: 'CODESPACES',\n codespaceName: 'CODESPACE_NAME',\n codespacePortForwardingDomain: 'GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN',\n gitpod: 'GITPOD_WORKSPACE_URL',\n cloudShell: 'CLOUD_SHELL',\n spinAppPort: 'SERVER_PORT',\n spinAppHost: 'SPIN_APP_HOST',\n organization: 'SHOPIFY_CLI_ORGANIZATION',\n identityToken: 'SHOPIFY_CLI_IDENTITY_TOKEN',\n refreshToken: 'SHOPIFY_CLI_REFRESH_TOKEN',\n otelURL: 'SHOPIFY_CLI_OTEL_EXPORTER_OTLP_ENDPOINT',\n themeKitAccessDomain: 'SHOPIFY_CLI_THEME_KIT_ACCESS_DOMAIN',\n json: 'SHOPIFY_FLAG_JSON',\n neverUsePartnersApi: 'SHOPIFY_CLI_NEVER_USE_PARTNERS_API',\n skipNetworkLevelRetry: 'SHOPIFY_CLI_SKIP_NETWORK_LEVEL_RETRY',\n maxRequestTimeForNetworkCalls: 'SHOPIFY_CLI_MAX_REQUEST_TIME_FOR_NETWORK_CALLS',\n disableImportScanning: 'SHOPIFY_CLI_DISABLE_IMPORT_SCANNING',\n}\n\nexport const defaultThemeKitAccessDomain = 'theme-kit-access.shopifyapps.com'\n\nexport const systemEnvironmentVariables = {\n backendPort: 'BACKEND_PORT',\n}\n\nexport const pathConstants = {\n executables: {\n dev: '/opt/dev/bin/dev',\n },\n directories: {\n cache: {\n path: () => {\n return cacheFolder()\n },\n vendor: {\n path: () => {\n return joinPath(cacheFolder(), 'vendor')\n },\n binaries: () => {\n return joinPath(cacheFolder(), 'vendor', 'binaries')\n },\n },\n },\n },\n}\n\nexport const sessionConstants = {\n expirationTimeMarginInMinutes: 4,\n}\n\nexport const bugsnagApiKey = '9e1e6889176fd0c795d5c659225e0fae'\n\nexport const reportingRateLimit = {limit: 300, timeout: {days: 1}}\n\nexport const themeKitAccessDomain =\n process.env[environmentVariables.themeKitAccessDomain] ?? defaultThemeKitAccessDomain\n"]}
|
|
@@ -4,9 +4,7 @@ import { identityFqdn } from '../../../public/node/context/fqdn.js';
|
|
|
4
4
|
import { shopifyFetch } from '../../../public/node/http.js';
|
|
5
5
|
import { outputContent, outputDebug, outputInfo, outputToken } from '../../../public/node/output.js';
|
|
6
6
|
import { AbortError, BugError } from '../../../public/node/error.js';
|
|
7
|
-
import { isCloudEnvironment } from '../../../public/node/context/local.js';
|
|
8
7
|
import { isCI, openURL } from '../../../public/node/system.js';
|
|
9
|
-
import { isTTY, keypress } from '../../../public/node/ui.js';
|
|
10
8
|
/**
|
|
11
9
|
* Initiate a device authorization flow.
|
|
12
10
|
* This will return a DeviceAuthorizationResponse containing the URL where user
|
|
@@ -56,22 +54,12 @@ export async function requestDeviceAuthorization(scopes) {
|
|
|
56
54
|
}
|
|
57
55
|
outputInfo(outputContent `User verification code: ${jsonResult.user_code}`);
|
|
58
56
|
const linkToken = outputToken.link(jsonResult.verification_uri_complete);
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (isCloudEnvironment() || !isTTY()) {
|
|
63
|
-
cloudMessage();
|
|
57
|
+
const opened = await openURL(jsonResult.verification_uri_complete);
|
|
58
|
+
if (opened) {
|
|
59
|
+
outputInfo(outputContent `Opened link to start the auth process: ${linkToken}`);
|
|
64
60
|
}
|
|
65
61
|
else {
|
|
66
|
-
outputInfo(
|
|
67
|
-
await keypress();
|
|
68
|
-
const opened = await openURL(jsonResult.verification_uri_complete);
|
|
69
|
-
if (opened) {
|
|
70
|
-
outputInfo(outputContent `Opened link to start the auth process: ${linkToken}`);
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
cloudMessage();
|
|
74
|
-
}
|
|
62
|
+
outputInfo(outputContent `👉 Open this link to start the auth process: ${linkToken}`);
|
|
75
63
|
}
|
|
76
64
|
return {
|
|
77
65
|
deviceCode: jsonResult.device_code,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-authorization.js","sourceRoot":"","sources":["../../../../src/private/node/session/device-authorization.ts"],"names":[],"mappings":"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","sourcesContent":["import {clientId} from './identity.js'\nimport {exchangeDeviceCodeForAccessToken} from './exchange.js'\nimport {IdentityToken} from './schema.js'\nimport {identityFqdn} from '../../../public/node/context/fqdn.js'\nimport {shopifyFetch} from '../../../public/node/http.js'\nimport {outputContent, outputDebug, outputInfo, outputToken} from '../../../public/node/output.js'\nimport {AbortError, BugError} from '../../../public/node/error.js'\nimport {isCloudEnvironment} from '../../../public/node/context/local.js'\nimport {isCI, openURL} from '../../../public/node/system.js'\nimport {isTTY, keypress} from '../../../public/node/ui.js'\n\nimport {Response} from 'node-fetch'\n\nexport interface DeviceAuthorizationResponse {\n deviceCode: string\n userCode: string\n verificationUri: string\n expiresIn: number\n verificationUriComplete?: string\n interval?: number\n}\n\n/**\n * Initiate a device authorization flow.\n * This will return a DeviceAuthorizationResponse containing the URL where user\n * should go to authorize the device without the need of a callback to the CLI.\n *\n * Also returns a `deviceCode` used for polling the token endpoint in the next step.\n *\n * @param scopes - The scopes to request\n * @returns An object with the device authorization response.\n */\nexport async function requestDeviceAuthorization(scopes: string[]): Promise<DeviceAuthorizationResponse> {\n const fqdn = await identityFqdn()\n const identityClientId = clientId()\n const queryParams = {client_id: identityClientId, scope: scopes.join(' ')}\n const url = `https://${fqdn}/oauth/device_authorization`\n\n const response = await shopifyFetch(url, {\n method: 'POST',\n headers: {'Content-type': 'application/x-www-form-urlencoded'},\n body: convertRequestToParams(queryParams),\n })\n\n // First read the response body as text so we have it for debugging\n let responseText: string\n try {\n responseText = await response.text()\n } catch (error) {\n throw new BugError(\n `Failed to read response from authorization service (HTTP ${response.status}). Network or streaming error occurred.`,\n 'Check your network connection and try again.',\n )\n }\n\n // Now try to parse the text as JSON\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let jsonResult: any\n try {\n jsonResult = JSON.parse(responseText)\n } catch {\n // JSON.parse failed, handle the parsing error\n const errorMessage = buildAuthorizationParseErrorMessage(response, responseText)\n throw new BugError(errorMessage)\n }\n\n outputDebug(outputContent`Received device authorization code: ${outputToken.json(jsonResult)}`)\n if (!jsonResult.device_code || !jsonResult.verification_uri_complete) {\n throw new BugError('Failed to start authorization process')\n }\n\n outputInfo('\\nTo run this command, log in to Shopify.')\n\n if (isCI()) {\n throw new AbortError(\n 'Authorization is required to continue, but the current environment does not support interactive prompts.',\n 'To resolve this, specify credentials in your environment, or run the command in an interactive environment such as your local terminal.',\n )\n }\n\n outputInfo(outputContent`User verification code: ${jsonResult.user_code}`)\n const linkToken = outputToken.link(jsonResult.verification_uri_complete)\n\n const cloudMessage = () => {\n outputInfo(outputContent`👉 Open this link to start the auth process: ${linkToken}`)\n }\n\n if (isCloudEnvironment() || !isTTY()) {\n cloudMessage()\n } else {\n outputInfo('👉 Press any key to open the login page on your browser')\n await keypress()\n const opened = await openURL(jsonResult.verification_uri_complete)\n if (opened) {\n outputInfo(outputContent`Opened link to start the auth process: ${linkToken}`)\n } else {\n cloudMessage()\n }\n }\n\n return {\n deviceCode: jsonResult.device_code,\n userCode: jsonResult.user_code,\n verificationUri: jsonResult.verification_uri,\n expiresIn: jsonResult.expires_in,\n verificationUriComplete: jsonResult.verification_uri_complete,\n interval: jsonResult.interval,\n }\n}\n\n/**\n * Poll the Oauth token endpoint with the device code obtained from a DeviceAuthorizationResponse.\n * The endpoint will return `authorization_pending` until the user completes the auth flow in the browser.\n * Once the user completes the auth flow, the endpoint will return the identity token.\n *\n * Timeout for the polling is defined by the server and is around 600 seconds.\n *\n * @param code - The device code obtained after starting a device identity flow\n * @param interval - The interval to poll the token endpoint\n * @returns The identity token\n */\nexport async function pollForDeviceAuthorization(code: string, interval = 5): Promise<IdentityToken> {\n let currentIntervalInSeconds = interval\n\n return new Promise<IdentityToken>((resolve, reject) => {\n const onPoll = async () => {\n const result = await exchangeDeviceCodeForAccessToken(code)\n if (!result.isErr()) {\n resolve(result.value)\n return\n }\n\n const error = result.error ?? 'unknown_failure'\n\n outputDebug(outputContent`Polling for device authorization... status: ${error}`)\n switch (error) {\n case 'authorization_pending': {\n startPolling()\n return\n }\n case 'slow_down':\n currentIntervalInSeconds += 5\n startPolling()\n return\n case 'access_denied':\n reject(new AbortError(`Device authorization failed: Access denied.`))\n return\n case 'expired_token':\n reject(new AbortError(`Device authorization failed: Token expired. Please try again.`))\n return\n case 'unknown_failure': {\n reject(new Error(`Device authorization failed: ${error}`))\n }\n }\n }\n\n const startPolling = () => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(onPoll, currentIntervalInSeconds * 1000)\n }\n\n startPolling()\n })\n}\n\nfunction convertRequestToParams(queryParams: {client_id: string; scope: string}): string {\n return Object.entries(queryParams)\n .map(([key, value]) => value && `${key}=${value}`)\n .filter((hasValue) => Boolean(hasValue))\n .join('&')\n}\n\n/**\n * Build a detailed error message for JSON parsing failures from the authorization service.\n * Provides context-specific error messages based on response status and content.\n *\n * @param response - The HTTP response object\n * @param responseText - The raw response body text\n * @returns Detailed error message about the failure\n */\nfunction buildAuthorizationParseErrorMessage(response: Response, responseText: string): string {\n // Build helpful error message based on response status and content\n let errorMessage = `Received invalid response from authorization service (HTTP ${response.status}).`\n\n // Add status-based context\n if (response.status >= 500) {\n errorMessage += ' The service may be experiencing issues.'\n } else if (response.status >= 400) {\n errorMessage += ' The request may be malformed or unauthorized.'\n }\n\n // Add content-based context (check these regardless of status)\n if (responseText.trim().startsWith('<!DOCTYPE') || responseText.trim().startsWith('<html')) {\n errorMessage += ' Received HTML instead of JSON - the service endpoint may have changed.'\n } else if (responseText.trim() === '') {\n errorMessage += ' Received empty response body.'\n } else {\n errorMessage += ' Response could not be parsed as valid JSON.'\n }\n\n return `${errorMessage} If this issue persists, please contact support at https://help.shopify.com`\n}\n"]}
|
|
1
|
+
{"version":3,"file":"device-authorization.js","sourceRoot":"","sources":["../../../../src/private/node/session/device-authorization.ts"],"names":[],"mappings":"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","sourcesContent":["import {clientId} from './identity.js'\nimport {exchangeDeviceCodeForAccessToken} from './exchange.js'\nimport {IdentityToken} from './schema.js'\nimport {identityFqdn} from '../../../public/node/context/fqdn.js'\nimport {shopifyFetch} from '../../../public/node/http.js'\nimport {outputContent, outputDebug, outputInfo, outputToken} from '../../../public/node/output.js'\nimport {AbortError, BugError} from '../../../public/node/error.js'\nimport {isCI, openURL} from '../../../public/node/system.js'\n\nimport {Response} from 'node-fetch'\n\nexport interface DeviceAuthorizationResponse {\n deviceCode: string\n userCode: string\n verificationUri: string\n expiresIn: number\n verificationUriComplete?: string\n interval?: number\n}\n\n/**\n * Initiate a device authorization flow.\n * This will return a DeviceAuthorizationResponse containing the URL where user\n * should go to authorize the device without the need of a callback to the CLI.\n *\n * Also returns a `deviceCode` used for polling the token endpoint in the next step.\n *\n * @param scopes - The scopes to request\n * @returns An object with the device authorization response.\n */\nexport async function requestDeviceAuthorization(scopes: string[]): Promise<DeviceAuthorizationResponse> {\n const fqdn = await identityFqdn()\n const identityClientId = clientId()\n const queryParams = {client_id: identityClientId, scope: scopes.join(' ')}\n const url = `https://${fqdn}/oauth/device_authorization`\n\n const response = await shopifyFetch(url, {\n method: 'POST',\n headers: {'Content-type': 'application/x-www-form-urlencoded'},\n body: convertRequestToParams(queryParams),\n })\n\n // First read the response body as text so we have it for debugging\n let responseText: string\n try {\n responseText = await response.text()\n } catch (error) {\n throw new BugError(\n `Failed to read response from authorization service (HTTP ${response.status}). Network or streaming error occurred.`,\n 'Check your network connection and try again.',\n )\n }\n\n // Now try to parse the text as JSON\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let jsonResult: any\n try {\n jsonResult = JSON.parse(responseText)\n } catch {\n // JSON.parse failed, handle the parsing error\n const errorMessage = buildAuthorizationParseErrorMessage(response, responseText)\n throw new BugError(errorMessage)\n }\n\n outputDebug(outputContent`Received device authorization code: ${outputToken.json(jsonResult)}`)\n if (!jsonResult.device_code || !jsonResult.verification_uri_complete) {\n throw new BugError('Failed to start authorization process')\n }\n\n outputInfo('\\nTo run this command, log in to Shopify.')\n\n if (isCI()) {\n throw new AbortError(\n 'Authorization is required to continue, but the current environment does not support interactive prompts.',\n 'To resolve this, specify credentials in your environment, or run the command in an interactive environment such as your local terminal.',\n )\n }\n\n outputInfo(outputContent`User verification code: ${jsonResult.user_code}`)\n const linkToken = outputToken.link(jsonResult.verification_uri_complete)\n\n const opened = await openURL(jsonResult.verification_uri_complete)\n if (opened) {\n outputInfo(outputContent`Opened link to start the auth process: ${linkToken}`)\n } else {\n outputInfo(outputContent`👉 Open this link to start the auth process: ${linkToken}`)\n }\n\n return {\n deviceCode: jsonResult.device_code,\n userCode: jsonResult.user_code,\n verificationUri: jsonResult.verification_uri,\n expiresIn: jsonResult.expires_in,\n verificationUriComplete: jsonResult.verification_uri_complete,\n interval: jsonResult.interval,\n }\n}\n\n/**\n * Poll the Oauth token endpoint with the device code obtained from a DeviceAuthorizationResponse.\n * The endpoint will return `authorization_pending` until the user completes the auth flow in the browser.\n * Once the user completes the auth flow, the endpoint will return the identity token.\n *\n * Timeout for the polling is defined by the server and is around 600 seconds.\n *\n * @param code - The device code obtained after starting a device identity flow\n * @param interval - The interval to poll the token endpoint\n * @returns The identity token\n */\nexport async function pollForDeviceAuthorization(code: string, interval = 5): Promise<IdentityToken> {\n let currentIntervalInSeconds = interval\n\n return new Promise<IdentityToken>((resolve, reject) => {\n const onPoll = async () => {\n const result = await exchangeDeviceCodeForAccessToken(code)\n if (!result.isErr()) {\n resolve(result.value)\n return\n }\n\n const error = result.error ?? 'unknown_failure'\n\n outputDebug(outputContent`Polling for device authorization... status: ${error}`)\n switch (error) {\n case 'authorization_pending': {\n startPolling()\n return\n }\n case 'slow_down':\n currentIntervalInSeconds += 5\n startPolling()\n return\n case 'access_denied':\n reject(new AbortError(`Device authorization failed: Access denied.`))\n return\n case 'expired_token':\n reject(new AbortError(`Device authorization failed: Token expired. Please try again.`))\n return\n case 'unknown_failure': {\n reject(new Error(`Device authorization failed: ${error}`))\n }\n }\n }\n\n const startPolling = () => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(onPoll, currentIntervalInSeconds * 1000)\n }\n\n startPolling()\n })\n}\n\nfunction convertRequestToParams(queryParams: {client_id: string; scope: string}): string {\n return Object.entries(queryParams)\n .map(([key, value]) => value && `${key}=${value}`)\n .filter((hasValue) => Boolean(hasValue))\n .join('&')\n}\n\n/**\n * Build a detailed error message for JSON parsing failures from the authorization service.\n * Provides context-specific error messages based on response status and content.\n *\n * @param response - The HTTP response object\n * @param responseText - The raw response body text\n * @returns Detailed error message about the failure\n */\nfunction buildAuthorizationParseErrorMessage(response: Response, responseText: string): string {\n // Build helpful error message based on response status and content\n let errorMessage = `Received invalid response from authorization service (HTTP ${response.status}).`\n\n // Add status-based context\n if (response.status >= 500) {\n errorMessage += ' The service may be experiencing issues.'\n } else if (response.status >= 400) {\n errorMessage += ' The request may be malformed or unauthorized.'\n }\n\n // Add content-based context (check these regardless of status)\n if (responseText.trim().startsWith('<!DOCTYPE') || responseText.trim().startsWith('<html')) {\n errorMessage += ' Received HTML instead of JSON - the service endpoint may have changed.'\n } else if (responseText.trim() === '') {\n errorMessage += ' Received empty response body.'\n } else {\n errorMessage += ' Response could not be parsed as valid JSON.'\n }\n\n return `${errorMessage} If this issue persists, please contact support at https://help.shopify.com`\n}\n"]}
|
package/dist/private/node/ui.js
CHANGED
|
@@ -45,7 +45,10 @@ export function renderOnce(element, { logLevel = 'info', renderOptions }) {
|
|
|
45
45
|
return renderedString;
|
|
46
46
|
}
|
|
47
47
|
export async function render(element, options) {
|
|
48
|
-
const { waitUntilExit } = inkRender(React.createElement(InkLifecycleRoot, null, element),
|
|
48
|
+
const { waitUntilExit } = inkRender(React.createElement(InkLifecycleRoot, null, element), {
|
|
49
|
+
patchConsole: !isUnitTest(),
|
|
50
|
+
...options,
|
|
51
|
+
});
|
|
49
52
|
await waitUntilExit();
|
|
50
53
|
}
|
|
51
54
|
export class Stdout extends EventEmitter {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/private/node/ui.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAElC,OAAO,EAAC,UAAU,EAAC,MAAM,oCAAoC,CAAA;AAC7D,OAAO,EAAC,QAAQ,EAAC,MAAM,gCAAgC,CAAA;AAEvD,OAAO,KAAK,EAAE,EAAe,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AACtG,OAAO,EAAM,MAAM,IAAI,SAAS,EAAiB,MAAM,EAAC,MAAM,KAAK,CAAA;AAEnE,OAAO,EAAC,YAAY,EAAC,MAAM,QAAQ,CAAA;AAEnC,MAAM,iBAAiB,GAAG,aAAa,CAAmC,IAAI,CAAC,CAAA;AAE/E;;;;GAIG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,QAAQ,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAA;IAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAClE,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAC,QAAQ,EAA8B;IACtE,MAAM,EAAC,IAAI,EAAC,GAAG,MAAM,EAAE,CAAA;IACvB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAyB,IAAI,CAAC,CAAA;IAE1E,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,KAAa,EAAE,EAAE;QAC7C,aAAa,CAAC,EAAC,KAAK,EAAC,CAAC,CAAA;IACxB,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;QACxB,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAA;IAEtB,OAAO,oBAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,QAAQ,IAAG,QAAQ,CAA8B,CAAA;AAC7F,CAAC;AAQD,MAAM,UAAU,UAAU,CAAC,OAAoB,EAAE,EAAC,QAAQ,GAAG,MAAM,EAAE,aAAa,EAAoB;IACpG,MAAM,EAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAC,GAAG,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC,CAAA;IAE9E,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAA;IAClC,CAAC;IAED,OAAO,EAAE,CAAA;IAET,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAoB,EAAE,OAAuB;IACxE,MAAM,EAAC,aAAa,EAAC,GAAG,SAAS,CAAC,oBAAC,gBAAgB,QAAE,OAAO,CAAoB,EAAE,OAAO,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/private/node/ui.tsx"],"names":[],"mappings":"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","sourcesContent":["import {output} from './output.js'\nimport {Logger, LogLevel} from '../../public/node/output.js'\nimport {isUnitTest} from '../../public/node/context/local.js'\nimport {treeKill} from '../../public/node/tree-kill.js'\n\nimport React, {ReactElement, createContext, useCallback, useContext, useEffect, useState} from 'react'\nimport {Key, render as inkRender, RenderOptions, useApp} from 'ink'\n\nimport {EventEmitter} from 'events'\n\nconst CompletionContext = createContext<((error?: Error) => void) | null>(null)\n\n/**\n * Signal that the current Ink tree is done. Must be called within an\n * InkLifecycleRoot — throws if the provider is missing so lifecycle\n * bugs surface immediately instead of silently hanging.\n */\nexport function useComplete(): (error?: Error) => void {\n const complete = useContext(CompletionContext)\n if (!complete) {\n throw new Error('useComplete() called outside InkLifecycleRoot')\n }\n return complete\n}\n\n/**\n * Root wrapper for Ink trees. Owns the single `exit()` call site — children\n * signal completion via `useComplete()`, which sets state here. The `useEffect`\n * fires post-render, guaranteeing all batched state updates have been flushed\n * before the tree is torn down.\n */\nexport function InkLifecycleRoot({children}: {children: React.ReactNode}) {\n const {exit} = useApp()\n const [exitResult, setExitResult] = useState<{error?: Error} | null>(null)\n\n const complete = useCallback((error?: Error) => {\n setExitResult({error})\n }, [])\n\n useEffect(() => {\n if (exitResult !== null) {\n exit(exitResult.error)\n }\n }, [exitResult, exit])\n\n return <CompletionContext.Provider value={complete}>{children}</CompletionContext.Provider>\n}\n\ninterface RenderOnceOptions {\n logLevel?: LogLevel\n logger?: Logger\n renderOptions?: RenderOptions\n}\n\nexport function renderOnce(element: JSX.Element, {logLevel = 'info', renderOptions}: RenderOnceOptions) {\n const {output: renderedString, unmount} = renderString(element, renderOptions)\n\n if (renderedString) {\n output(renderedString, logLevel)\n }\n\n unmount()\n\n return renderedString\n}\n\nexport async function render(element: JSX.Element, options?: RenderOptions) {\n const {waitUntilExit} = inkRender(<InkLifecycleRoot>{element}</InkLifecycleRoot>, {\n patchConsole: !isUnitTest(),\n ...options,\n })\n await waitUntilExit()\n}\n\ninterface Instance {\n output: string | undefined\n unmount: () => void\n}\n\nexport class Stdout extends EventEmitter {\n columns: number\n rows: number\n readonly frames: string[] = []\n private _lastFrame?: string\n\n constructor(options: {columns?: number; rows?: number}) {\n super()\n this.columns = options.columns ?? 80\n this.rows = options.rows ?? 80\n }\n\n write = (frame: string) => {\n this.frames.push(frame)\n // Ink writes `this.lastOutput + '\\n'` to stdout during unmount when\n // running in a CI environment (detected via `is-in-ci`). In debug\n // mode (which tests use), `lastOutput` is never updated, so the write\n // is just '\\n', clobbering the last real rendered frame. Skip it so\n // that `lastFrame()` keeps returning the final rendered content.\n if (frame !== '\\n') {\n this._lastFrame = frame\n }\n }\n\n lastFrame = () => {\n return this._lastFrame\n }\n}\n\nconst renderString = (element: ReactElement, renderOptions?: RenderOptions): Instance => {\n const columns = isUnitTest() ? 80 : process.stdout.columns\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stdout = (renderOptions?.stdout as any) ?? new Stdout({columns})\n\n const instance = inkRender(element, {\n stdout,\n debug: true,\n exitOnCtrlC: false,\n patchConsole: false,\n })\n\n return {\n output: stdout.lastFrame(),\n unmount: instance.unmount,\n }\n}\n\nexport function handleCtrlC(\n input: string,\n key: Key,\n exit = () => {\n treeKill(process.pid, 'SIGINT')\n },\n) {\n if (input === 'c' && key.ctrl) {\n // Exceptions thrown in hooks aren't caught by our errorHandler.\n exit()\n }\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts the trailing numeric id from a plain GraphQL global id like
|
|
3
|
+
* `gid://shopify/Product/123`.
|
|
4
|
+
*
|
|
5
|
+
* @param gid - A plain GraphQL global id string.
|
|
6
|
+
* @returns The trailing numeric id, or undefined when the string does not end with `/<digits>`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function numericIdFromGid(gid: string): string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Decodes a base64-encoded GraphQL global id (for example, the form
|
|
11
|
+
* Business Platform APIs return) and returns the trailing numeric id.
|
|
12
|
+
*
|
|
13
|
+
* @param gid - A base64-encoded GraphQL global id.
|
|
14
|
+
* @returns The trailing numeric id, or undefined when the decoded string does not end with `/<digits>`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function numericIdFromEncodedGid(gid: string): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Encodes a plain GraphQL global id (`gid://...`) as base64, which is the
|
|
19
|
+
* form some Business Platform endpoints require.
|
|
20
|
+
*
|
|
21
|
+
* @param gid - A plain GraphQL global id string to encode.
|
|
22
|
+
* @returns The base64-encoded gid.
|
|
23
|
+
*/
|
|
24
|
+
export declare function encodeGid(gid: string): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts the trailing numeric id from a plain GraphQL global id like
|
|
3
|
+
* `gid://shopify/Product/123`.
|
|
4
|
+
*
|
|
5
|
+
* @param gid - A plain GraphQL global id string.
|
|
6
|
+
* @returns The trailing numeric id, or undefined when the string does not end with `/<digits>`.
|
|
7
|
+
*/
|
|
8
|
+
export function numericIdFromGid(gid) {
|
|
9
|
+
const match = gid.match(/\/(\d+)$/);
|
|
10
|
+
return match ? match[1] : undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Decodes a base64-encoded GraphQL global id (for example, the form
|
|
14
|
+
* Business Platform APIs return) and returns the trailing numeric id.
|
|
15
|
+
*
|
|
16
|
+
* @param gid - A base64-encoded GraphQL global id.
|
|
17
|
+
* @returns The trailing numeric id, or undefined when the decoded string does not end with `/<digits>`.
|
|
18
|
+
*/
|
|
19
|
+
export function numericIdFromEncodedGid(gid) {
|
|
20
|
+
return numericIdFromGid(Buffer.from(gid, 'base64').toString('utf8'));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Encodes a plain GraphQL global id (`gid://...`) as base64, which is the
|
|
24
|
+
* form some Business Platform endpoints require.
|
|
25
|
+
*
|
|
26
|
+
* @param gid - A plain GraphQL global id string to encode.
|
|
27
|
+
* @returns The base64-encoded gid.
|
|
28
|
+
*/
|
|
29
|
+
export function encodeGid(gid) {
|
|
30
|
+
return Buffer.from(gid).toString('base64');
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=gid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gid.js","sourceRoot":"","sources":["../../../src/public/common/gid.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IACnC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AACrC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,OAAO,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;AACtE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC5C,CAAC","sourcesContent":["/**\n * Extracts the trailing numeric id from a plain GraphQL global id like\n * `gid://shopify/Product/123`.\n *\n * @param gid - A plain GraphQL global id string.\n * @returns The trailing numeric id, or undefined when the string does not end with `/<digits>`.\n */\nexport function numericIdFromGid(gid: string): string | undefined {\n const match = gid.match(/\\/(\\d+)$/)\n return match ? match[1] : undefined\n}\n\n/**\n * Decodes a base64-encoded GraphQL global id (for example, the form\n * Business Platform APIs return) and returns the trailing numeric id.\n *\n * @param gid - A base64-encoded GraphQL global id.\n * @returns The trailing numeric id, or undefined when the decoded string does not end with `/<digits>`.\n */\nexport function numericIdFromEncodedGid(gid: string): string | undefined {\n return numericIdFromGid(Buffer.from(gid, 'base64').toString('utf8'))\n}\n\n/**\n * Encodes a plain GraphQL global id (`gid://...`) as base64, which is the\n * form some Business Platform endpoints require.\n *\n * @param gid - A plain GraphQL global id string to encode.\n * @returns The base64-encoded gid.\n */\nexport function encodeGid(gid: string): string {\n return Buffer.from(gid).toString('base64')\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { takeRandomFromArray } from './array.js';
|
|
1
|
+
import { takeRandomFromArray, uniq } from './array.js';
|
|
2
2
|
import { unstyled } from '../node/output.js';
|
|
3
3
|
import { camelCase, capitalCase, constantCase, paramCase, snakeCase, pascalCase } from 'change-case';
|
|
4
4
|
const SAFE_RANDOM_BUSINESS_ADJECTIVES = [
|
|
@@ -368,11 +368,12 @@ export function pascalize(str) {
|
|
|
368
368
|
export function normalizeDelimitedString(delimitedString, delimiter = ',') {
|
|
369
369
|
if (!delimitedString)
|
|
370
370
|
return;
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
371
|
+
return uniq(delimitedString
|
|
372
|
+
.split(delimiter)
|
|
373
|
+
.map((item) => item.trim())
|
|
374
|
+
.filter((item) => item !== ''))
|
|
375
|
+
.sort()
|
|
376
|
+
.join(delimiter);
|
|
376
377
|
}
|
|
377
378
|
/**
|
|
378
379
|
* Given two dates, it returns a human-readable string representing the time elapsed between them.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string.js","sourceRoot":"","sources":["../../../src/public/common/string.ts"],"names":[],"mappings":"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","sourcesContent":["import {takeRandomFromArray} from './array.js'\nimport {unstyled} from '../node/output.js'\nimport {Token, TokenItem} from '../../private/node/ui/components/TokenizedText.js'\n\nimport {camelCase, capitalCase, constantCase, paramCase, snakeCase, pascalCase} from 'change-case'\n\nconst SAFE_RANDOM_BUSINESS_ADJECTIVES = [\n 'commercial',\n 'profitable',\n 'amortizable',\n 'branded',\n 'integrated',\n 'synergistic',\n 'consolidated',\n 'diversified',\n 'lean',\n 'niche',\n 'premium',\n 'luxury',\n 'scalable',\n 'optimized',\n 'empowered',\n 'international',\n 'beneficial',\n 'fruitful',\n 'extensive',\n 'lucrative',\n 'modern',\n 'stable',\n 'strategic',\n 'adaptive',\n 'efficient',\n 'growing',\n 'sustainable',\n 'innovative',\n 'regional',\n 'specialized',\n 'focused',\n 'pragmatic',\n 'ethical',\n 'flexible',\n 'competitive',\n]\n\nconst SAFE_RANDOM_CREATIVE_ADJECTIVES = [\n 'bright',\n 'impactful',\n 'stylish',\n 'colorful',\n 'modern',\n 'minimal',\n 'trendy',\n 'creative',\n 'artistic',\n 'spectacular',\n 'glamorous',\n 'luxury',\n 'retro',\n 'nostalgic',\n 'comfy',\n 'polished',\n 'fabulous',\n 'balanced',\n 'monochrome',\n 'glitched',\n 'contrasted',\n 'elegant',\n 'textured',\n 'vibrant',\n 'harmonious',\n 'versatile',\n 'eclectic',\n 'futuristic',\n 'idealistic',\n 'intricate',\n 'bohemian',\n 'abstract',\n 'meticulous',\n 'refined',\n 'flamboyant',\n]\n\nconst SAFE_RANDOM_BUSINESS_NOUNS = [\n 'account',\n 'consumer',\n 'customer',\n 'enterprise',\n 'business',\n 'venture',\n 'marketplace',\n 'revenue',\n 'vertical',\n 'portfolio',\n 'negotiation',\n 'shipping',\n 'demand',\n 'supply',\n 'growth',\n 'merchant',\n 'investment',\n 'shareholder',\n 'conversion',\n 'capital',\n 'projection',\n 'upside',\n 'trade',\n 'deal',\n 'merchandise',\n 'transaction',\n 'sale',\n 'franchise',\n 'subsidiary',\n 'logistics',\n 'sponsorship',\n 'partnership',\n 'tax',\n 'policy',\n 'outsource',\n 'equity',\n 'strategy',\n 'valuation',\n 'benchmark',\n 'metrics',\n 'duplication',\n]\n\nconst SAFE_RANDOM_CREATIVE_NOUNS = [\n 'vibe',\n 'style',\n 'moment',\n 'mood',\n 'flavor',\n 'look',\n 'appearance',\n 'perspective',\n 'aspect',\n 'ambience',\n 'quality',\n 'backdrop',\n 'focus',\n 'tone',\n 'inspiration',\n 'imagery',\n 'aesthetics',\n 'palette',\n 'ornamentation',\n 'contrast',\n 'colorway',\n 'visuals',\n 'typography',\n 'composition',\n 'scale',\n 'symmetry',\n 'gradients',\n 'proportions',\n 'textures',\n 'harmony',\n 'shapes',\n 'patterns',\n]\n\nexport type RandomNameFamily = 'business' | 'creative'\n\nconst NAME_FAMILIES: Record<RandomNameFamily, {adjectives: string[]; nouns: string[]}> = {\n business: {\n adjectives: SAFE_RANDOM_BUSINESS_ADJECTIVES,\n nouns: SAFE_RANDOM_BUSINESS_NOUNS,\n },\n creative: {\n adjectives: SAFE_RANDOM_CREATIVE_ADJECTIVES,\n nouns: SAFE_RANDOM_CREATIVE_NOUNS,\n },\n}\n\n/**\n * Generates a random name by combining an adjective and noun.\n *\n * @param family - Theme to use for the random name (business or creative).\n * @returns A random name generated by combining an adjective and noun.\n */\nexport function getRandomName(family: RandomNameFamily = 'business'): string {\n return `${takeRandomFromArray(NAME_FAMILIES[family].adjectives)}-${takeRandomFromArray(NAME_FAMILIES[family].nouns)}`\n}\n\n/**\n * Given a string, it returns it with the first letter capitalized.\n *\n * @param str - String to capitalize.\n * @returns String with the first letter capitalized.\n */\nexport function capitalize(str: string): string {\n return str.substring(0, 1).toUpperCase() + str.substring(1)\n}\n\n/**\n * Given a list of items, it returns a pluralized string based on the amount of items.\n *\n * @param items - List of items.\n * @param plural - Supplier used when the list of items has more than one item.\n * @param singular - Supplier used when the list of items has a single item.\n * @param none - Supplier used when the list has no items.\n * @returns The {@link TokenItem} supplied by the {@link plural}, {@link singular}, or {@link none} functions.\n */\nexport function pluralize<\n T,\n TToken extends Token = Token,\n TPluralToken extends TToken = TToken,\n TSingularToken extends TToken = TToken,\n TNoneToken extends TToken = TToken,\n>(\n items: T[],\n plural: (items: T[]) => TokenItem<TPluralToken>,\n singular: (item: T) => TokenItem<TSingularToken>,\n none?: () => TokenItem<TNoneToken>,\n): TokenItem<TPluralToken | TSingularToken | TNoneToken> | string {\n if (items.length === 1) {\n return singular(items[0]!)\n }\n\n if (items.length > 1) {\n return plural(items)\n }\n\n if (none) {\n return none()\n }\n\n return ''\n}\n\n/**\n * Try to convert a string to an int, falling back to undefined if unable to.\n *\n * @param maybeInt - String to convert to an int.\n * @returns The int if it was able to convert, otherwise undefined.\n */\nexport function tryParseInt(maybeInt: string | undefined): number | undefined {\n if (maybeInt === undefined) return undefined\n const asInt = Number.parseInt(maybeInt, 10)\n return Number.isNaN(asInt) ? undefined : asInt\n}\n\n/**\n * Transforms a matrix of strings into a single string with the columns aligned.\n *\n * @param lines - Array of rows, where each row is an array of strings (representing columns).\n * @returns A string with the columns aligned.\n */\nexport function linesToColumns(lines: string[][]): string {\n const widths: number[] = []\n for (let i = 0; lines[0] && i < lines[0].length; i++) {\n const columnRows = lines.map((line) => line[i]!)\n widths.push(Math.max(...columnRows.map((row) => unstyled(row).length)))\n }\n const paddedLines = lines\n .map((line) => {\n return line\n .map((col, index) => {\n return `${col}${' '.repeat(widths[index]! - unstyled(col).length)}`\n })\n .join(' ')\n .trimEnd()\n })\n .join('\\n')\n return paddedLines\n}\n\n/**\n * Given a string, it transforms it to a slug (lowercase, hyphenated, no special chars, trimmed...).\n *\n * @param str - String to slugify.\n * @returns The slugified string.\n */\nexport function slugify(str: string): string {\n return str\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * Given a string, it returns it with the special regex characters escaped.\n * More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping.\n *\n * @param str - String to escape.\n * @returns The escaped string.\n */\nexport function escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Transform a string to camelCase.\n *\n * @param input - String to escape.\n * @returns The escaped string.\n */\nexport function camelize(input: string): string {\n return camelCase(input)\n}\n\n/**\n * Transform a string to capitalCase.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function capitalizeWords(input: string): string {\n return capitalCase(input)\n}\n\n/**\n * Transform a string to param-case.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function hyphenate(input: string): string {\n return paramCase(input)\n}\n\n/**\n * Transform a string to snake_case.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function underscore(input: string): string {\n return snakeCase(input)\n}\n\n/**\n * Transform a string to CONSTANT_CASE.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function constantize(input: string): string {\n return constantCase(input)\n}\n\n/**\n * Given a date, return a formatted string like \"2021-01-01 12:00:00\".\n *\n * @param date - Date to format.\n * @returns The transformed string.\n */\nexport function formatDate(date: Date): string {\n const components = date.toISOString().split('T')\n const dateString = components[0] ?? date.toDateString()\n const timeString = components[1]?.split('.')[0] ?? date.toTimeString()\n return `${dateString} ${timeString}`\n}\n\n/**\n * Given a date in UTC ISO String format, return a formatted string in local time like \"2021-01-01 12:00:00\".\n *\n * @param dateString - UTC ISO Date String.\n * @returns The transformed string in local system time.\n */\nexport function formatLocalDate(dateString: string): string {\n const dateObj = new Date(dateString)\n const localDate = new Date(\n Date.UTC(\n dateObj.getFullYear(),\n dateObj.getMonth(),\n dateObj.getDate(),\n dateObj.getHours(),\n dateObj.getMinutes(),\n dateObj.getSeconds(),\n ),\n )\n return formatDate(localDate)\n}\n\n/**\n * Given a list of items, it returns a string with the items joined by commas and the last item joined by \"and\".\n * All items are wrapped in double quotes.\n * For example: [\"a\", \"b\", \"c\"] returns \"a\", \"b\" and \"c\".\n *\n * @param items - List of items.\n * @returns The joined string.\n */\nexport function joinWithAnd(items: string[]): string {\n if (items.length === 0) return ''\n if (items.length === 1) return `\"${items[0]}\"`\n\n return `${items\n .slice(0, -1)\n .map((item) => `\"${item}\"`)\n .join(', ')} and \"${items[items.length - 1]}\"`\n}\n\n/**\n * Given a string, it returns the PascalCase form of it.\n * Eg: \"pascal_case\" returns \"PascalCase\".\n *\n * @param str - String to PascalCase.\n * @returns String with all the first letter capitalized with no spaces.\n */\nexport function pascalize(str: string): string {\n return pascalCase(str)\n}\n\n/**\n * Given a string that represents a list of delimited tokens, it returns the normalized string representing the same\n * list, without empty elements, sorted, and with no duplicates.\n *\n * @param delimitedString - String to normalize.\n * @param delimiter - Delimiter used to split the string into tokens.\n * @returns String with the normalized list of tokens.\n */\nexport function normalizeDelimitedString(delimitedString?: string, delimiter = ','): string | undefined {\n if (!delimitedString) return\n\n const items = delimitedString.split(delimiter).map((value) => value.trim())\n const nonEmptyItems = items.filter((value) => value !== '')\n const sortedItems = nonEmptyItems.sort()\n const uniqueSortedItems = [...new Set(sortedItems)]\n\n return uniqueSortedItems.join(delimiter)\n}\n\n/**\n * Given two dates, it returns a human-readable string representing the time elapsed between them.\n *\n * @param from - Start date.\n * @param to - End date.\n * @returns A string like \"5 minutes ago\" or \"2 days ago\".\n */\nexport function timeAgo(from: Date, to: Date): string {\n const seconds = Math.floor((to.getTime() - from.getTime()) / 1000)\n if (seconds < 60) return `${formatTimeUnit(seconds, 'second')} ago`\n\n const minutes = Math.floor(seconds / 60)\n if (minutes < 60) return `${formatTimeUnit(minutes, 'minute')} ago`\n\n const hours = Math.floor(minutes / 60)\n if (hours < 24) return `${formatTimeUnit(hours, 'hour')} ago`\n\n const days = Math.floor(hours / 24)\n return `${formatTimeUnit(days, 'day')} ago`\n}\n\nfunction formatTimeUnit(count: number, unit: string): string {\n return `${count} ${unit}${count === 1 ? '' : 's'}`\n}\n"]}
|
|
1
|
+
{"version":3,"file":"string.js","sourceRoot":"","sources":["../../../src/public/common/string.ts"],"names":[],"mappings":"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","sourcesContent":["import {takeRandomFromArray, uniq} from './array.js'\nimport {unstyled} from '../node/output.js'\nimport {Token, TokenItem} from '../../private/node/ui/components/TokenizedText.js'\n\nimport {camelCase, capitalCase, constantCase, paramCase, snakeCase, pascalCase} from 'change-case'\n\nconst SAFE_RANDOM_BUSINESS_ADJECTIVES = [\n 'commercial',\n 'profitable',\n 'amortizable',\n 'branded',\n 'integrated',\n 'synergistic',\n 'consolidated',\n 'diversified',\n 'lean',\n 'niche',\n 'premium',\n 'luxury',\n 'scalable',\n 'optimized',\n 'empowered',\n 'international',\n 'beneficial',\n 'fruitful',\n 'extensive',\n 'lucrative',\n 'modern',\n 'stable',\n 'strategic',\n 'adaptive',\n 'efficient',\n 'growing',\n 'sustainable',\n 'innovative',\n 'regional',\n 'specialized',\n 'focused',\n 'pragmatic',\n 'ethical',\n 'flexible',\n 'competitive',\n]\n\nconst SAFE_RANDOM_CREATIVE_ADJECTIVES = [\n 'bright',\n 'impactful',\n 'stylish',\n 'colorful',\n 'modern',\n 'minimal',\n 'trendy',\n 'creative',\n 'artistic',\n 'spectacular',\n 'glamorous',\n 'luxury',\n 'retro',\n 'nostalgic',\n 'comfy',\n 'polished',\n 'fabulous',\n 'balanced',\n 'monochrome',\n 'glitched',\n 'contrasted',\n 'elegant',\n 'textured',\n 'vibrant',\n 'harmonious',\n 'versatile',\n 'eclectic',\n 'futuristic',\n 'idealistic',\n 'intricate',\n 'bohemian',\n 'abstract',\n 'meticulous',\n 'refined',\n 'flamboyant',\n]\n\nconst SAFE_RANDOM_BUSINESS_NOUNS = [\n 'account',\n 'consumer',\n 'customer',\n 'enterprise',\n 'business',\n 'venture',\n 'marketplace',\n 'revenue',\n 'vertical',\n 'portfolio',\n 'negotiation',\n 'shipping',\n 'demand',\n 'supply',\n 'growth',\n 'merchant',\n 'investment',\n 'shareholder',\n 'conversion',\n 'capital',\n 'projection',\n 'upside',\n 'trade',\n 'deal',\n 'merchandise',\n 'transaction',\n 'sale',\n 'franchise',\n 'subsidiary',\n 'logistics',\n 'sponsorship',\n 'partnership',\n 'tax',\n 'policy',\n 'outsource',\n 'equity',\n 'strategy',\n 'valuation',\n 'benchmark',\n 'metrics',\n 'duplication',\n]\n\nconst SAFE_RANDOM_CREATIVE_NOUNS = [\n 'vibe',\n 'style',\n 'moment',\n 'mood',\n 'flavor',\n 'look',\n 'appearance',\n 'perspective',\n 'aspect',\n 'ambience',\n 'quality',\n 'backdrop',\n 'focus',\n 'tone',\n 'inspiration',\n 'imagery',\n 'aesthetics',\n 'palette',\n 'ornamentation',\n 'contrast',\n 'colorway',\n 'visuals',\n 'typography',\n 'composition',\n 'scale',\n 'symmetry',\n 'gradients',\n 'proportions',\n 'textures',\n 'harmony',\n 'shapes',\n 'patterns',\n]\n\nexport type RandomNameFamily = 'business' | 'creative'\n\nconst NAME_FAMILIES: Record<RandomNameFamily, {adjectives: string[]; nouns: string[]}> = {\n business: {\n adjectives: SAFE_RANDOM_BUSINESS_ADJECTIVES,\n nouns: SAFE_RANDOM_BUSINESS_NOUNS,\n },\n creative: {\n adjectives: SAFE_RANDOM_CREATIVE_ADJECTIVES,\n nouns: SAFE_RANDOM_CREATIVE_NOUNS,\n },\n}\n\n/**\n * Generates a random name by combining an adjective and noun.\n *\n * @param family - Theme to use for the random name (business or creative).\n * @returns A random name generated by combining an adjective and noun.\n */\nexport function getRandomName(family: RandomNameFamily = 'business'): string {\n return `${takeRandomFromArray(NAME_FAMILIES[family].adjectives)}-${takeRandomFromArray(NAME_FAMILIES[family].nouns)}`\n}\n\n/**\n * Given a string, it returns it with the first letter capitalized.\n *\n * @param str - String to capitalize.\n * @returns String with the first letter capitalized.\n */\nexport function capitalize(str: string): string {\n return str.substring(0, 1).toUpperCase() + str.substring(1)\n}\n\n/**\n * Given a list of items, it returns a pluralized string based on the amount of items.\n *\n * @param items - List of items.\n * @param plural - Supplier used when the list of items has more than one item.\n * @param singular - Supplier used when the list of items has a single item.\n * @param none - Supplier used when the list has no items.\n * @returns The {@link TokenItem} supplied by the {@link plural}, {@link singular}, or {@link none} functions.\n */\nexport function pluralize<\n T,\n TToken extends Token = Token,\n TPluralToken extends TToken = TToken,\n TSingularToken extends TToken = TToken,\n TNoneToken extends TToken = TToken,\n>(\n items: T[],\n plural: (items: T[]) => TokenItem<TPluralToken>,\n singular: (item: T) => TokenItem<TSingularToken>,\n none?: () => TokenItem<TNoneToken>,\n): TokenItem<TPluralToken | TSingularToken | TNoneToken> | string {\n if (items.length === 1) {\n return singular(items[0]!)\n }\n\n if (items.length > 1) {\n return plural(items)\n }\n\n if (none) {\n return none()\n }\n\n return ''\n}\n\n/**\n * Try to convert a string to an int, falling back to undefined if unable to.\n *\n * @param maybeInt - String to convert to an int.\n * @returns The int if it was able to convert, otherwise undefined.\n */\nexport function tryParseInt(maybeInt: string | undefined): number | undefined {\n if (maybeInt === undefined) return undefined\n const asInt = Number.parseInt(maybeInt, 10)\n return Number.isNaN(asInt) ? undefined : asInt\n}\n\n/**\n * Transforms a matrix of strings into a single string with the columns aligned.\n *\n * @param lines - Array of rows, where each row is an array of strings (representing columns).\n * @returns A string with the columns aligned.\n */\nexport function linesToColumns(lines: string[][]): string {\n const widths: number[] = []\n for (let i = 0; lines[0] && i < lines[0].length; i++) {\n const columnRows = lines.map((line) => line[i]!)\n widths.push(Math.max(...columnRows.map((row) => unstyled(row).length)))\n }\n const paddedLines = lines\n .map((line) => {\n return line\n .map((col, index) => {\n return `${col}${' '.repeat(widths[index]! - unstyled(col).length)}`\n })\n .join(' ')\n .trimEnd()\n })\n .join('\\n')\n return paddedLines\n}\n\n/**\n * Given a string, it transforms it to a slug (lowercase, hyphenated, no special chars, trimmed...).\n *\n * @param str - String to slugify.\n * @returns The slugified string.\n */\nexport function slugify(str: string): string {\n return str\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\n/**\n * Given a string, it returns it with the special regex characters escaped.\n * More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping.\n *\n * @param str - String to escape.\n * @returns The escaped string.\n */\nexport function escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Transform a string to camelCase.\n *\n * @param input - String to escape.\n * @returns The escaped string.\n */\nexport function camelize(input: string): string {\n return camelCase(input)\n}\n\n/**\n * Transform a string to capitalCase.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function capitalizeWords(input: string): string {\n return capitalCase(input)\n}\n\n/**\n * Transform a string to param-case.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function hyphenate(input: string): string {\n return paramCase(input)\n}\n\n/**\n * Transform a string to snake_case.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function underscore(input: string): string {\n return snakeCase(input)\n}\n\n/**\n * Transform a string to CONSTANT_CASE.\n *\n * @param input - String to transform.\n * @returns The transformed string.\n */\nexport function constantize(input: string): string {\n return constantCase(input)\n}\n\n/**\n * Given a date, return a formatted string like \"2021-01-01 12:00:00\".\n *\n * @param date - Date to format.\n * @returns The transformed string.\n */\nexport function formatDate(date: Date): string {\n const components = date.toISOString().split('T')\n const dateString = components[0] ?? date.toDateString()\n const timeString = components[1]?.split('.')[0] ?? date.toTimeString()\n return `${dateString} ${timeString}`\n}\n\n/**\n * Given a date in UTC ISO String format, return a formatted string in local time like \"2021-01-01 12:00:00\".\n *\n * @param dateString - UTC ISO Date String.\n * @returns The transformed string in local system time.\n */\nexport function formatLocalDate(dateString: string): string {\n const dateObj = new Date(dateString)\n const localDate = new Date(\n Date.UTC(\n dateObj.getFullYear(),\n dateObj.getMonth(),\n dateObj.getDate(),\n dateObj.getHours(),\n dateObj.getMinutes(),\n dateObj.getSeconds(),\n ),\n )\n return formatDate(localDate)\n}\n\n/**\n * Given a list of items, it returns a string with the items joined by commas and the last item joined by \"and\".\n * All items are wrapped in double quotes.\n * For example: [\"a\", \"b\", \"c\"] returns \"a\", \"b\" and \"c\".\n *\n * @param items - List of items.\n * @returns The joined string.\n */\nexport function joinWithAnd(items: string[]): string {\n if (items.length === 0) return ''\n if (items.length === 1) return `\"${items[0]}\"`\n\n return `${items\n .slice(0, -1)\n .map((item) => `\"${item}\"`)\n .join(', ')} and \"${items[items.length - 1]}\"`\n}\n\n/**\n * Given a string, it returns the PascalCase form of it.\n * Eg: \"pascal_case\" returns \"PascalCase\".\n *\n * @param str - String to PascalCase.\n * @returns String with all the first letter capitalized with no spaces.\n */\nexport function pascalize(str: string): string {\n return pascalCase(str)\n}\n\n/**\n * Given a string that represents a list of delimited tokens, it returns the normalized string representing the same\n * list, without empty elements, sorted, and with no duplicates.\n *\n * @param delimitedString - String to normalize.\n * @param delimiter - Delimiter used to split the string into tokens.\n * @returns String with the normalized list of tokens.\n */\nexport function normalizeDelimitedString(delimitedString?: string, delimiter = ','): string | undefined {\n if (!delimitedString) return\n\n return uniq(\n delimitedString\n .split(delimiter)\n .map((item) => item.trim())\n .filter((item) => item !== ''),\n )\n .sort()\n .join(delimiter)\n}\n\n/**\n * Given two dates, it returns a human-readable string representing the time elapsed between them.\n *\n * @param from - Start date.\n * @param to - End date.\n * @returns A string like \"5 minutes ago\" or \"2 days ago\".\n */\nexport function timeAgo(from: Date, to: Date): string {\n const seconds = Math.floor((to.getTime() - from.getTime()) / 1000)\n if (seconds < 60) return `${formatTimeUnit(seconds, 'second')} ago`\n\n const minutes = Math.floor(seconds / 60)\n if (minutes < 60) return `${formatTimeUnit(minutes, 'minute')} ago`\n\n const hours = Math.floor(minutes / 60)\n if (hours < 24) return `${formatTimeUnit(hours, 'hour')} ago`\n\n const days = Math.floor(hours / 24)\n return `${formatTimeUnit(days, 'day')} ago`\n}\n\nfunction formatTimeUnit(count: number, unit: string): string {\n return `${count} ${unit}${count === 1 ? '' : 's'}`\n}\n"]}
|
|
@@ -13,3 +13,19 @@ export declare function isValidURL(url: string): boolean;
|
|
|
13
13
|
* @returns A URL object if the parsing is successful, undefined otherwise.
|
|
14
14
|
*/
|
|
15
15
|
export declare function safeParseURL(url: string): URL | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Extracts the lowercased hostname from a URL-shaped string. Tolerates
|
|
18
|
+
* bare hosts (without a scheme) and inputs that come back from APIs as
|
|
19
|
+
* either `https://shop.myshopify.com` or `shop.myshopify.com`.
|
|
20
|
+
*
|
|
21
|
+
* @param value - A URL or bare host string, possibly null/undefined.
|
|
22
|
+
* @returns The lowercased hostname, or undefined when the input is empty.
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractHost(value: string | null | undefined): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Extracts the subdomain handle from a `*.myshopify.com` URL or host.
|
|
27
|
+
*
|
|
28
|
+
* @param value - A URL or host string, possibly null/undefined.
|
|
29
|
+
* @returns The myshopify subdomain handle, or undefined when the input isn't a `*.myshopify.com` URL.
|
|
30
|
+
*/
|
|
31
|
+
export declare function extractMyshopifyHandle(value: string | null | undefined): string | undefined;
|
|
@@ -30,4 +30,34 @@ export function safeParseURL(url) {
|
|
|
30
30
|
return undefined;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Extracts the lowercased hostname from a URL-shaped string. Tolerates
|
|
35
|
+
* bare hosts (without a scheme) and inputs that come back from APIs as
|
|
36
|
+
* either `https://shop.myshopify.com` or `shop.myshopify.com`.
|
|
37
|
+
*
|
|
38
|
+
* @param value - A URL or bare host string, possibly null/undefined.
|
|
39
|
+
* @returns The lowercased hostname, or undefined when the input is empty.
|
|
40
|
+
*/
|
|
41
|
+
export function extractHost(value) {
|
|
42
|
+
if (!value)
|
|
43
|
+
return undefined;
|
|
44
|
+
const lowered = value.toLowerCase();
|
|
45
|
+
const parsed = safeParseURL(lowered);
|
|
46
|
+
if (parsed)
|
|
47
|
+
return parsed.hostname;
|
|
48
|
+
return lowered.replace(/^https?:\/\//, '').split('/')[0];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Extracts the subdomain handle from a `*.myshopify.com` URL or host.
|
|
52
|
+
*
|
|
53
|
+
* @param value - A URL or host string, possibly null/undefined.
|
|
54
|
+
* @returns The myshopify subdomain handle, or undefined when the input isn't a `*.myshopify.com` URL.
|
|
55
|
+
*/
|
|
56
|
+
export function extractMyshopifyHandle(value) {
|
|
57
|
+
const host = extractHost(value);
|
|
58
|
+
if (!host)
|
|
59
|
+
return undefined;
|
|
60
|
+
const match = host.match(/^([^.]+)\.myshopify\.com$/);
|
|
61
|
+
return match ? match[1] : undefined;
|
|
62
|
+
}
|
|
33
63
|
//# sourceMappingURL=url.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../../src/public/common/url.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAC9B,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,KAAK,YAAY,SAAS;YAAE,OAAO,KAAK,CAAA;QAC5C,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QACnB,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC","sourcesContent":["/**\n * Check if the format of a URL is valid or not.\n *\n * @param url - URL to be checked.\n * @returns True if the URL is valid, false otherwise.\n * @throws An error if URL's constructor throws an error other than `TypeError`.\n */\nexport function isValidURL(url: string): boolean {\n try {\n return Boolean(new URL(url))\n } catch (error: unknown) {\n if (error instanceof TypeError) return false\n throw error\n }\n}\n\n/**\n * Safely parse a string into a URL.\n *\n * @param url - The string to parse into a URL.\n * @returns A URL object if the parsing is successful, undefined otherwise.\n */\nexport function safeParseURL(url: string): URL | undefined {\n try {\n return new URL(url)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return undefined\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../../src/public/common/url.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAC9B,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,KAAK,YAAY,SAAS;YAAE,OAAO,KAAK,CAAA;QAC5C,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QACnB,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,KAAgC;IAC1D,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;IACnC,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;IACpC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAA;IAClC,OAAO,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AAC1D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAgC;IACrE,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAA;IAC/B,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAA;IACrD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AACrC,CAAC","sourcesContent":["/**\n * Check if the format of a URL is valid or not.\n *\n * @param url - URL to be checked.\n * @returns True if the URL is valid, false otherwise.\n * @throws An error if URL's constructor throws an error other than `TypeError`.\n */\nexport function isValidURL(url: string): boolean {\n try {\n return Boolean(new URL(url))\n } catch (error: unknown) {\n if (error instanceof TypeError) return false\n throw error\n }\n}\n\n/**\n * Safely parse a string into a URL.\n *\n * @param url - The string to parse into a URL.\n * @returns A URL object if the parsing is successful, undefined otherwise.\n */\nexport function safeParseURL(url: string): URL | undefined {\n try {\n return new URL(url)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return undefined\n }\n}\n\n/**\n * Extracts the lowercased hostname from a URL-shaped string. Tolerates\n * bare hosts (without a scheme) and inputs that come back from APIs as\n * either `https://shop.myshopify.com` or `shop.myshopify.com`.\n *\n * @param value - A URL or bare host string, possibly null/undefined.\n * @returns The lowercased hostname, or undefined when the input is empty.\n */\nexport function extractHost(value: string | null | undefined): string | undefined {\n if (!value) return undefined\n const lowered = value.toLowerCase()\n const parsed = safeParseURL(lowered)\n if (parsed) return parsed.hostname\n return lowered.replace(/^https?:\\/\\//, '').split('/')[0]\n}\n\n/**\n * Extracts the subdomain handle from a `*.myshopify.com` URL or host.\n *\n * @param value - A URL or host string, possibly null/undefined.\n * @returns The myshopify subdomain handle, or undefined when the input isn't a `*.myshopify.com` URL.\n */\nexport function extractMyshopifyHandle(value: string | null | undefined): string | undefined {\n const host = extractHost(value)\n if (!host) return undefined\n const match = host.match(/^([^.]+)\\.myshopify\\.com$/)\n return match ? match[1] : undefined\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CLI_KIT_VERSION = "4.
|
|
1
|
+
export declare const CLI_KIT_VERSION = "4.2.0";
|