@shopify/cli-kit 3.68.1 → 3.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/api/graphql/admin/generated/public_api_versions.d.ts +14 -0
- package/dist/cli/api/graphql/admin/generated/public_api_versions.js +28 -0
- package/dist/cli/api/graphql/admin/generated/public_api_versions.js.map +1 -0
- package/dist/private/node/api/graphql.d.ts +1 -1
- package/dist/private/node/api/graphql.js +1 -0
- package/dist/private/node/api/graphql.js.map +1 -1
- package/dist/private/node/api/headers.js +2 -2
- package/dist/private/node/api/headers.js.map +1 -1
- package/dist/private/node/api/rest.js +3 -1
- package/dist/private/node/api/rest.js.map +1 -1
- package/dist/private/node/api.d.ts +2 -2
- package/dist/private/node/api.js +8 -6
- package/dist/private/node/api.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/demo-recorder.js +1 -0
- package/dist/private/node/demo-recorder.js.map +1 -1
- package/dist/private/node/session/device-authorization.js +15 -7
- package/dist/private/node/session/device-authorization.js.map +1 -1
- package/dist/private/node/session/exchange.d.ts +0 -8
- package/dist/private/node/session/exchange.js +2 -19
- package/dist/private/node/session/exchange.js.map +1 -1
- package/dist/private/node/session/validate.js +1 -0
- package/dist/private/node/session/validate.js.map +1 -1
- package/dist/private/node/session.d.ts +5 -5
- package/dist/private/node/session.js +4 -12
- package/dist/private/node/session.js.map +1 -1
- package/dist/private/node/testing/ui.js +0 -3
- package/dist/private/node/testing/ui.js.map +1 -1
- package/dist/private/node/themes/generate-theme-name.js +1 -0
- package/dist/private/node/themes/generate-theme-name.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.test.js +0 -3
- package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Banner.js +1 -0
- package/dist/private/node/ui/components/Banner.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.test.js +7 -7
- package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
- package/dist/private/node/ui/components/FatalError.js +1 -0
- package/dist/private/node/ui/components/FatalError.js.map +1 -1
- package/dist/private/node/ui/components/List.js +1 -1
- package/dist/private/node/ui/components/List.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/InfoTable.js +1 -0
- package/dist/private/node/ui/components/Prompts/InfoTable.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.js +1 -1
- package/dist/private/node/ui/components/SelectInput.js.map +1 -1
- package/dist/private/node/ui/components/SelectPrompt.test.js +0 -4
- package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Table/Row.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.js +2 -1
- package/dist/private/node/ui/components/Tasks.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.d.ts +1 -1
- package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
- package/dist/private/node/ui/components/TokenizedText.js +1 -0
- package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
- package/dist/private/node/ui/hooks/use-abort-signal.js +1 -1
- package/dist/private/node/ui/hooks/use-abort-signal.js.map +1 -1
- package/dist/private/node/ui.js +3 -1
- package/dist/private/node/ui.js.map +1 -1
- package/dist/public/common/array.js +1 -0
- package/dist/public/common/array.js.map +1 -1
- package/dist/public/common/string.js +3 -0
- package/dist/public/common/string.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/api/admin.d.ts +14 -1
- package/dist/public/node/api/admin.js +29 -28
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/app-management.d.ts +5 -3
- package/dist/public/node/api/app-management.js +16 -11
- package/dist/public/node/api/app-management.js.map +1 -1
- package/dist/public/node/api/graphql.js +13 -1
- package/dist/public/node/api/graphql.js.map +1 -1
- package/dist/public/node/api/rest-api-throttler.js +10 -3
- package/dist/public/node/api/rest-api-throttler.js.map +1 -1
- package/dist/public/node/archiver.js +6 -2
- package/dist/public/node/archiver.js.map +1 -1
- package/dist/public/node/base-command.js +1 -1
- package/dist/public/node/base-command.js.map +1 -1
- package/dist/public/node/context/local.d.ts +0 -9
- package/dist/public/node/context/local.js +0 -13
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/context/spin.js +1 -1
- package/dist/public/node/context/spin.js.map +1 -1
- package/dist/public/node/custom-oclif-loader.js +5 -4
- package/dist/public/node/custom-oclif-loader.js.map +1 -1
- package/dist/public/node/dot-env.js +2 -1
- package/dist/public/node/dot-env.js.map +1 -1
- package/dist/public/node/environments.js +1 -1
- package/dist/public/node/environments.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/framework.js +5 -4
- package/dist/public/node/framework.js.map +1 -1
- package/dist/public/node/fs.d.ts +1 -1
- package/dist/public/node/fs.js +1 -1
- package/dist/public/node/fs.js.map +1 -1
- package/dist/public/node/git.js +2 -0
- package/dist/public/node/git.js.map +1 -1
- package/dist/public/node/github.js +2 -0
- package/dist/public/node/github.js.map +1 -1
- package/dist/public/node/hooks/deprecations.js +1 -1
- package/dist/public/node/hooks/deprecations.js.map +1 -1
- package/dist/public/node/hooks/postrun.js +2 -1
- package/dist/public/node/hooks/postrun.js.map +1 -1
- package/dist/public/node/hooks/prerun.js +1 -1
- package/dist/public/node/hooks/prerun.js.map +1 -1
- package/dist/public/node/http.js +2 -1
- package/dist/public/node/http.js.map +1 -1
- package/dist/public/node/json-schema.d.ts +1 -1
- package/dist/public/node/json-schema.js.map +1 -1
- package/dist/public/node/liquid.js +12 -2
- package/dist/public/node/liquid.js.map +1 -1
- package/dist/public/node/metadata.js +1 -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 +2 -1
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/ruby.js +1 -0
- package/dist/public/node/ruby.js.map +1 -1
- package/dist/public/node/session.d.ts +7 -6
- package/dist/public/node/session.js +2 -1
- package/dist/public/node/session.js.map +1 -1
- package/dist/public/node/system.js +1 -1
- package/dist/public/node/system.js.map +1 -1
- package/dist/public/node/themes/api.js +34 -4
- package/dist/public/node/themes/api.js.map +1 -1
- package/dist/public/node/themes/factories.js +1 -0
- package/dist/public/node/themes/factories.js.map +1 -1
- package/dist/public/node/themes/types.d.ts +2 -3
- package/dist/public/node/themes/types.js.map +1 -1
- package/dist/public/node/themes/urls.d.ts +1 -0
- package/dist/public/node/themes/urls.js +3 -0
- package/dist/public/node/themes/urls.js.map +1 -1
- package/dist/public/node/tree-kill.js +8 -4
- package/dist/public/node/tree-kill.js.map +1 -1
- package/dist/public/node/ui.js +5 -2
- package/dist/public/node/ui.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -5
- package/assets/auth-error.html +0 -23
- package/assets/empty-url.html +0 -23
- package/assets/favicon.svg +0 -26
- package/assets/missing-code.html +0 -23
- package/assets/missing-state.html +0 -23
- package/assets/style.css +0 -58
- package/assets/success.html +0 -20
- package/dist/private/node/session/authorize.d.ts +0 -5
- package/dist/private/node/session/authorize.js +0 -69
- package/dist/private/node/session/authorize.js.map +0 -1
- package/dist/private/node/session/post-auth.d.ts +0 -10
- package/dist/private/node/session/post-auth.js +0 -61
- package/dist/private/node/session/post-auth.js.map +0 -1
- package/dist/private/node/session/redirect-listener.d.ts +0 -34
- package/dist/private/node/session/redirect-listener.js +0 -105
- package/dist/private/node/session/redirect-listener.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../../src/private/node/session/validate.ts"],"names":[],"mappings":"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","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../../src/private/node/session/validate.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport {applicationId} from './identity.js'\nimport {ApplicationToken, IdentityToken, validateCachedIdentityTokenStructure} from './schema.js'\nimport {validateIdentityToken} from './identity-token-validation.js'\nimport {sessionConstants} from '../constants.js'\nimport {outputDebug} from '../../../public/node/output.js'\nimport {firstPartyDev} from '../../../public/node/context/local.js'\nimport {OAuthApplications} from '../session.js'\n\ntype ValidationResult = 'needs_refresh' | 'needs_full_auth' | 'ok'\n\n/**\n * Validate if an identity token is valid for the requested scopes\n */\nfunction validateScopes(requestedScopes: string[], identity: IdentityToken) {\n const currentScopes = identity.scopes\n if (firstPartyDev() !== currentScopes.includes('employee')) return false\n return requestedScopes.every((scope) => currentScopes.includes(scope))\n}\n\n/**\n * Validate if the current session is valid or we need to refresh/re-authenticate\n * @param scopes - requested scopes to validate\n * @param applications - requested applications\n * @param session - current session with identity and application tokens\n * @returns 'ok' if the session is valid, 'needs_full_auth' if we need to re-authenticate, 'needs_refresh' if we need to refresh the session\n */\nexport async function validateSession(\n scopes: string[],\n applications: OAuthApplications,\n session: {\n identity: IdentityToken\n applications: {[x: string]: ApplicationToken}\n },\n): Promise<ValidationResult> {\n if (!session) return 'needs_full_auth'\n const scopesAreValid = validateScopes(scopes, session.identity)\n const identityIsValid = await validateIdentityToken(session.identity.accessToken)\n if (!scopesAreValid) return 'needs_full_auth'\n let tokensAreExpired = isTokenExpired(session.identity)\n\n if (applications.partnersApi) {\n const appId = applicationId('partners')\n const token = session.applications[appId]!\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n if (applications.appManagementApi) {\n const appId = applicationId('app-management')\n const token = session.applications[appId]!\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n if (applications.storefrontRendererApi) {\n const appId = applicationId('storefront-renderer')\n const token = session.applications[appId]!\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n if (applications.adminApi) {\n const appId = applicationId('admin')\n const realAppId = `${applications.adminApi.storeFqdn}-${appId}`\n const token = session.applications[realAppId]!\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n outputDebug(`\nThe validation of the token for application/identity completed with the following results:\n- It's expired: ${tokensAreExpired}\n- It's invalid in identity: ${!identityIsValid}\n `)\n\n if (!validateCachedIdentityTokenStructure(session.identity)) {\n return 'needs_full_auth'\n }\n\n if (tokensAreExpired) return 'needs_refresh'\n if (!identityIsValid) return 'needs_full_auth'\n return 'ok'\n}\n\nfunction isTokenExpired(token: ApplicationToken): boolean {\n if (!token) return true\n return token.expiresAt < expireThreshold()\n}\n\nfunction expireThreshold(): Date {\n return new Date(Date.now() + sessionConstants.expirationTimeMarginInMinutes * 60 * 1000)\n}\n"]}
|
|
@@ -3,7 +3,7 @@ import { AdminSession } from '@shopify/cli-kit/node/session';
|
|
|
3
3
|
/**
|
|
4
4
|
* A scope supported by the Shopify Admin API.
|
|
5
5
|
*/
|
|
6
|
-
type AdminAPIScope = 'graphql' | 'themes' | 'collaborator'
|
|
6
|
+
export type AdminAPIScope = 'graphql' | 'themes' | 'collaborator';
|
|
7
7
|
/**
|
|
8
8
|
* It represents the options to authenticate against the Shopify Admin API.
|
|
9
9
|
*/
|
|
@@ -16,7 +16,7 @@ interface AdminAPIOAuthOptions {
|
|
|
16
16
|
/**
|
|
17
17
|
* A scope supported by the Partners API.
|
|
18
18
|
*/
|
|
19
|
-
type PartnersAPIScope = 'cli'
|
|
19
|
+
export type PartnersAPIScope = 'cli';
|
|
20
20
|
interface PartnersAPIOAuthOptions {
|
|
21
21
|
/** List of scopes to request permissions for. */
|
|
22
22
|
scopes: PartnersAPIScope[];
|
|
@@ -24,7 +24,7 @@ interface PartnersAPIOAuthOptions {
|
|
|
24
24
|
/**
|
|
25
25
|
* A scope supported by the Developer Platform API.
|
|
26
26
|
*/
|
|
27
|
-
type AppManagementAPIScope = 'https://api.shopify.com/auth/organization.apps.manage'
|
|
27
|
+
export type AppManagementAPIScope = 'https://api.shopify.com/auth/organization.apps.manage';
|
|
28
28
|
interface AppManagementAPIOauthOptions {
|
|
29
29
|
/** List of scopes to request permissions for. */
|
|
30
30
|
scopes: AppManagementAPIScope[];
|
|
@@ -32,12 +32,12 @@ interface AppManagementAPIOauthOptions {
|
|
|
32
32
|
/**
|
|
33
33
|
* A scope supported by the Storefront Renderer API.
|
|
34
34
|
*/
|
|
35
|
-
type StorefrontRendererScope = 'devtools'
|
|
35
|
+
export type StorefrontRendererScope = 'devtools';
|
|
36
36
|
interface StorefrontRendererAPIOAuthOptions {
|
|
37
37
|
/** List of scopes to request permissions for. */
|
|
38
38
|
scopes: StorefrontRendererScope[];
|
|
39
39
|
}
|
|
40
|
-
type BusinessPlatformScope = 'destinations'
|
|
40
|
+
export type BusinessPlatformScope = 'destinations';
|
|
41
41
|
interface BusinessPlatformAPIOAuthOptions {
|
|
42
42
|
/** List of scopes to request permissions for. */
|
|
43
43
|
scopes: BusinessPlatformScope[];
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { applicationId } from './session/identity.js';
|
|
2
2
|
import { validateSession } from './session/validate.js';
|
|
3
3
|
import { allDefaultScopes, apiScopes } from './session/scopes.js';
|
|
4
|
-
import { exchangeAccessForApplicationTokens,
|
|
5
|
-
import { authorize } from './session/authorize.js';
|
|
4
|
+
import { exchangeAccessForApplicationTokens, exchangeCustomPartnerToken, refreshAccessToken, InvalidGrantError, InvalidRequestError, } from './session/exchange.js';
|
|
6
5
|
import * as secureStore from './session/store.js';
|
|
7
6
|
import { pollForDeviceAuthorization, requestDeviceAuthorization } from './session/device-authorization.js';
|
|
8
7
|
import { RequestClientError } from './api/headers.js';
|
|
9
8
|
import { getCachedPartnerAccountStatus, setCachedPartnerAccountStatus } from './conf-store.js';
|
|
10
9
|
import { isThemeAccessSession } from './api/rest.js';
|
|
11
10
|
import { outputContent, outputToken, outputDebug } from '../../public/node/output.js';
|
|
12
|
-
import { firstPartyDev, themeToken
|
|
11
|
+
import { firstPartyDev, themeToken } from '../../public/node/context/local.js';
|
|
13
12
|
import { AbortError, BugError } from '../../public/node/error.js';
|
|
14
13
|
import { partnersRequest } from '../../public/node/api/partners.js';
|
|
15
14
|
import { normalizeStoreFqdn, partnersFqdn, identityFqdn } from '../../public/node/context/fqdn.js';
|
|
@@ -99,6 +98,7 @@ export async function ensureAuthenticated(applications, _env, { forceRefresh = f
|
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
100
|
const currentSession = (await secureStore.fetch()) || {};
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
102
102
|
const fqdnSession = currentSession[fqdn];
|
|
103
103
|
const scopes = getFlattenScopes(applications);
|
|
104
104
|
outputDebug(outputContent `Validating existing session against the scopes:
|
|
@@ -175,7 +175,7 @@ async function executeCompleteFlow(applications, identityFqdn) {
|
|
|
175
175
|
if (identityTokenInformation) {
|
|
176
176
|
identityToken = buildIdentityTokenFromEnv(scopes, identityTokenInformation);
|
|
177
177
|
}
|
|
178
|
-
else
|
|
178
|
+
else {
|
|
179
179
|
// Request a device code to authorize without a browser redirect.
|
|
180
180
|
outputDebug(outputContent `Requesting device authorization code...`);
|
|
181
181
|
const deviceAuth = await requestDeviceAuthorization(scopes);
|
|
@@ -183,14 +183,6 @@ async function executeCompleteFlow(applications, identityFqdn) {
|
|
|
183
183
|
outputDebug(outputContent `Starting polling for the identity token...`);
|
|
184
184
|
identityToken = await pollForDeviceAuthorization(deviceAuth.deviceCode, deviceAuth.interval);
|
|
185
185
|
}
|
|
186
|
-
else {
|
|
187
|
-
// Authorize user via browser
|
|
188
|
-
outputDebug(outputContent `Authorizing through Identity's website...`);
|
|
189
|
-
const code = await authorize(scopes);
|
|
190
|
-
// Exchange code for identity token
|
|
191
|
-
outputDebug(outputContent `Authorization code received. Exchanging it for a CLI token...`);
|
|
192
|
-
identityToken = await exchangeCodeForAccessToken(code);
|
|
193
|
-
}
|
|
194
186
|
// Exchange identity token for application tokens
|
|
195
187
|
outputDebug(outputContent `CLI token received. Exchanging it for application tokens...`);
|
|
196
188
|
const result = await exchangeAccessForApplicationTokens(identityToken, exchangeScopes, store);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/private/node/session.ts"],"names":[],"mappings":"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","sourcesContent":["import {applicationId} from './session/identity.js'\nimport {validateSession} from './session/validate.js'\nimport {allDefaultScopes, apiScopes} from './session/scopes.js'\nimport {\n exchangeAccessForApplicationTokens,\n exchangeCodeForAccessToken,\n exchangeCustomPartnerToken,\n ExchangeScopes,\n refreshAccessToken,\n InvalidGrantError,\n InvalidRequestError,\n} from './session/exchange.js'\nimport {authorize} from './session/authorize.js'\nimport {IdentityToken, Session} from './session/schema.js'\nimport * as secureStore from './session/store.js'\nimport {pollForDeviceAuthorization, requestDeviceAuthorization} from './session/device-authorization.js'\nimport {RequestClientError} from './api/headers.js'\nimport {getCachedPartnerAccountStatus, setCachedPartnerAccountStatus} from './conf-store.js'\nimport {isThemeAccessSession} from './api/rest.js'\nimport {outputContent, outputToken, outputDebug} from '../../public/node/output.js'\nimport {firstPartyDev, themeToken, useDeviceAuth} from '../../public/node/context/local.js'\nimport {AbortError, BugError} from '../../public/node/error.js'\nimport {partnersRequest} from '../../public/node/api/partners.js'\nimport {normalizeStoreFqdn, partnersFqdn, identityFqdn} from '../../public/node/context/fqdn.js'\nimport {openURL} from '../../public/node/system.js'\nimport {keypress} from '../../public/node/ui.js'\nimport {getIdentityTokenInformation, getPartnersToken} from '../../public/node/environment.js'\nimport {gql} from 'graphql-request'\nimport {AdminSession} from '@shopify/cli-kit/node/session'\nimport {outputCompleted, outputInfo, outputWarn} from '@shopify/cli-kit/node/output'\nimport {isTruthy} from '@shopify/cli-kit/node/context/utilities'\nimport {isSpin} from '@shopify/cli-kit/node/context/spin'\nimport {nonRandomUUID} from '@shopify/cli-kit/node/crypto'\n\n/**\n * A scope supported by the Shopify Admin API.\n */\ntype AdminAPIScope = 'graphql' | 'themes' | 'collaborator' | string\n\n/**\n * It represents the options to authenticate against the Shopify Admin API.\n */\n\ninterface AdminAPIOAuthOptions {\n /** Store to request permissions for. */\n storeFqdn: string\n /** List of scopes to request permissions for. */\n scopes: AdminAPIScope[]\n}\n\n/**\n * A scope supported by the Partners API.\n */\ntype PartnersAPIScope = 'cli' | string\ninterface PartnersAPIOAuthOptions {\n /** List of scopes to request permissions for. */\n scopes: PartnersAPIScope[]\n}\n\n/**\n * A scope supported by the Developer Platform API.\n */\ntype AppManagementAPIScope = 'https://api.shopify.com/auth/organization.apps.manage' | string\ninterface AppManagementAPIOauthOptions {\n /** List of scopes to request permissions for. */\n scopes: AppManagementAPIScope[]\n}\n\n/**\n * A scope supported by the Storefront Renderer API.\n */\ntype StorefrontRendererScope = 'devtools' | string\ninterface StorefrontRendererAPIOAuthOptions {\n /** List of scopes to request permissions for. */\n scopes: StorefrontRendererScope[]\n}\n\ntype BusinessPlatformScope = 'destinations' | string\ninterface BusinessPlatformAPIOAuthOptions {\n /** List of scopes to request permissions for. */\n scopes: BusinessPlatformScope[]\n}\n\n/**\n * It represents the authentication requirements and\n * is the input necessary to trigger the authentication\n * flow.\n */\nexport interface OAuthApplications {\n adminApi?: AdminAPIOAuthOptions\n storefrontRendererApi?: StorefrontRendererAPIOAuthOptions\n partnersApi?: PartnersAPIOAuthOptions\n businessPlatformApi?: BusinessPlatformAPIOAuthOptions\n appManagementApi?: AppManagementAPIOauthOptions\n}\n\nexport interface OAuthSession {\n admin?: AdminSession\n partners?: string\n storefront?: string\n businessPlatform?: string\n appManagement?: string\n userId: string\n}\n\ntype AuthMethod = 'partners_token' | 'device_auth' | 'theme_access_token' | 'custom_app_token' | 'none'\n\nlet userId: undefined | string\nlet authMethod: AuthMethod = 'none'\n\n/**\n * Retrieves the user ID from the current session or returns 'unknown' if not found.\n *\n * This function performs the following steps:\n * 1. Checks for a cached user ID in memory (obtained in the current run).\n * 2. Attempts to fetch it from the secure store (from a previous auth session).\n * 3. Checks if a custom token was used (either as a theme password or partners token).\n * 4. If a custom token is present in the environment, generates a UUID and uses it as userId.\n * 5. If after all this we don't have a userId, then reports as 'unknown'.\n *\n * @returns A Promise that resolves to the user ID as a string.\n */\nexport async function getLastSeenUserIdAfterAuth(): Promise<string> {\n if (userId) return userId\n\n const currentSession = (await secureStore.fetch()) || {}\n const fqdn = await identityFqdn()\n const cachedUserId = currentSession[fqdn]?.identity.userId\n if (cachedUserId) return cachedUserId\n\n const customToken = getPartnersToken() ?? themeToken()\n return customToken ? nonRandomUUID(customToken) : 'unknown'\n}\n\nexport function setLastSeenUserIdAfterAuth(id: string) {\n userId = id\n}\n\n/**\n * Retrieves the last seen authentication method used in the current session.\n *\n * This function checks for the authentication method in the following order:\n * 1. Returns the cached auth method if it's not 'none'.\n * 2. Checks for a cached session, which implies 'device_auth' was used.\n * 3. Checks for a partners token in the environment.\n * 4. Checks for a theme password in the environment.\n * 5. If none of the above are true, returns 'none'.\n *\n * @returns A Promise that resolves to the last seen authentication method as an AuthMethod type.\n */\nexport async function getLastSeenAuthMethod(): Promise<AuthMethod> {\n if (authMethod !== 'none') return authMethod\n\n const currentSession = (await secureStore.fetch()) || {}\n const fqdn = await identityFqdn()\n const cachedUserId = currentSession[fqdn]?.identity.userId\n if (cachedUserId) return 'device_auth'\n\n const partnersToken = getPartnersToken()\n if (partnersToken) return 'partners_token'\n\n const themePassword = themeToken()\n if (themePassword) {\n return isThemeAccessSession({token: themePassword, storeFqdn: ''}) ? 'theme_access_token' : 'custom_app_token'\n }\n\n return 'none'\n}\n\nexport function setLastSeenAuthMethod(method: AuthMethod) {\n authMethod = method\n}\n\n/**\n * This method ensures that we have a valid session to authenticate against the given applications using the provided scopes.\n *\n * @param applications - An object containing the applications we need to be authenticated with.\n * @param _env - Optional environment variables to use.\n * @param forceRefresh - Optional flag to force a refresh of the token.\n * @returns An instance with the access tokens organized by application.\n */\nexport async function ensureAuthenticated(\n applications: OAuthApplications,\n _env?: NodeJS.ProcessEnv,\n {forceRefresh = false, noPrompt = false}: {forceRefresh?: boolean; noPrompt?: boolean} = {},\n): Promise<OAuthSession> {\n const fqdn = await identityFqdn()\n\n const previousStoreFqdn = applications.adminApi?.storeFqdn\n if (previousStoreFqdn) {\n const normalizedStoreName = await normalizeStoreFqdn(previousStoreFqdn)\n if (previousStoreFqdn === applications.adminApi?.storeFqdn) {\n applications.adminApi.storeFqdn = normalizedStoreName\n }\n }\n\n const currentSession = (await secureStore.fetch()) || {}\n const fqdnSession = currentSession[fqdn]!\n const scopes = getFlattenScopes(applications)\n\n outputDebug(outputContent`Validating existing session against the scopes:\n${outputToken.json(scopes)}\nFor applications:\n${outputToken.json(applications)}\n`)\n const validationResult = await validateSession(scopes, applications, fqdnSession)\n\n let newSession = {}\n\n function throwOnNoPrompt() {\n if (!noPrompt || (isSpin() && firstPartyDev())) return\n throw new AbortError(\n `The currently available CLI credentials are invalid.\n\nThe CLI is currently unable to prompt for reauthentication.`,\n 'Restart the CLI process you were running. If in an interactive terminal, you will be prompted to reauthenticate. If in a non-interactive terminal, ensure the correct credentials are available in the program environment.',\n )\n }\n\n if (validationResult === 'needs_full_auth') {\n throwOnNoPrompt()\n outputDebug(outputContent`Initiating the full authentication flow...`)\n newSession = await executeCompleteFlow(applications, fqdn)\n } else if (validationResult === 'needs_refresh' || forceRefresh) {\n outputDebug(outputContent`The current session is valid but needs refresh. Refreshing...`)\n try {\n newSession = await refreshTokens(fqdnSession.identity, applications, fqdn)\n } catch (error) {\n if (error instanceof InvalidGrantError) {\n throwOnNoPrompt()\n newSession = await executeCompleteFlow(applications, fqdn)\n } else if (error instanceof InvalidRequestError) {\n await secureStore.remove()\n throw new AbortError('\\nError validating auth session', \"We've cleared the current session, please try again\")\n } else {\n throw error\n }\n }\n }\n\n const completeSession: Session = {...currentSession, ...newSession}\n\n // Save the new session info if it has changed\n if (Object.keys(newSession).length > 0) await secureStore.store(completeSession)\n const tokens = await tokensFor(applications, completeSession, fqdn)\n\n // Overwrite partners token if using a custom CLI Token\n const envToken = getPartnersToken()\n if (envToken && applications.partnersApi) {\n tokens.partners = (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n if (!envToken && tokens.partners) {\n await ensureUserHasPartnerAccount(tokens.partners, tokens.userId)\n }\n\n setLastSeenAuthMethod(envToken ? 'partners_token' : 'device_auth')\n setLastSeenUserIdAfterAuth(tokens.userId)\n return tokens\n}\n\n/**\n * Execute the full authentication flow.\n *\n * @param applications - An object containing the applications we need to be authenticated with.\n * @param identityFqdn - The identity FQDN.\n */\nasync function executeCompleteFlow(applications: OAuthApplications, identityFqdn: string): Promise<Session> {\n const scopes = getFlattenScopes(applications)\n const exchangeScopes = getExchangeScopes(applications)\n const store = applications.adminApi?.storeFqdn\n if (firstPartyDev()) {\n outputDebug(outputContent`Authenticating as Shopify Employee...`)\n scopes.push('employee')\n }\n\n let identityToken: IdentityToken\n const identityTokenInformation = getIdentityTokenInformation()\n if (identityTokenInformation) {\n identityToken = buildIdentityTokenFromEnv(scopes, identityTokenInformation)\n } else if (useDeviceAuth()) {\n // Request a device code to authorize without a browser redirect.\n outputDebug(outputContent`Requesting device authorization code...`)\n const deviceAuth = await requestDeviceAuthorization(scopes)\n\n // Poll for the identity token\n outputDebug(outputContent`Starting polling for the identity token...`)\n identityToken = await pollForDeviceAuthorization(deviceAuth.deviceCode, deviceAuth.interval)\n } else {\n // Authorize user via browser\n outputDebug(outputContent`Authorizing through Identity's website...`)\n const code = await authorize(scopes)\n\n // Exchange code for identity token\n outputDebug(outputContent`Authorization code received. Exchanging it for a CLI token...`)\n identityToken = await exchangeCodeForAccessToken(code)\n }\n\n // Exchange identity token for application tokens\n outputDebug(outputContent`CLI token received. Exchanging it for application tokens...`)\n const result = await exchangeAccessForApplicationTokens(identityToken, exchangeScopes, store)\n\n const session: Session = {\n [identityFqdn]: {\n identity: identityToken,\n applications: result,\n },\n }\n\n outputCompleted('Logged in.')\n\n return session\n}\n\n/**\n * If the user creates an account from the Identity website, the created\n * account won't get a Partner organization created. We need to detect that\n * and take the user to create a partner organization.\n *\n * @param partnersToken - Partners token.\n */\nasync function ensureUserHasPartnerAccount(partnersToken: string, userId: string | undefined) {\n if (isTruthy(process.env.USE_APP_MANAGEMENT_API)) return\n\n outputDebug(outputContent`Verifying that the user has a Partner organization`)\n if (!(await hasPartnerAccount(partnersToken, userId))) {\n outputInfo(`\\nA Shopify Partners organization is needed to proceed.`)\n outputInfo(`👉 Press any key to create one`)\n await keypress()\n await openURL(`https://${await partnersFqdn()}/signup`)\n outputInfo(outputContent`👉 Press any key when you have ${outputToken.cyan('created the organization')}`)\n outputWarn(outputContent`Make sure you've confirmed your Shopify and the Partner organization from the email`)\n await keypress()\n if (!(await hasPartnerAccount(partnersToken, userId))) {\n throw new AbortError(\n `Couldn't find your Shopify Partners organization`,\n `Have you confirmed your accounts from the emails you received?`,\n )\n }\n }\n}\n\n// eslint-disable-next-line @shopify/cli/no-inline-graphql\nconst getFirstOrganization = gql`\n {\n organizations(first: 1) {\n nodes {\n id\n }\n }\n }\n`\n\n/**\n * Validate if the current token is valid for partners API.\n *\n * @param partnersToken - Partners token.\n * @returns A promise that resolves to true if the token is valid for partners API.\n */\nasync function hasPartnerAccount(partnersToken: string, userId?: string): Promise<boolean> {\n const cacheKey = userId ?? partnersToken\n const cachedStatus = getCachedPartnerAccountStatus(cacheKey)\n\n if (cachedStatus) {\n outputDebug(`Confirmed partner account exists from cache`)\n return true\n }\n\n try {\n await partnersRequest(getFirstOrganization, partnersToken)\n setCachedPartnerAccountStatus(cacheKey)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n if (error instanceof RequestClientError && error.statusCode === 404) {\n return false\n } else {\n return true\n }\n }\n}\n\n/**\n * Refresh the tokens for a given session.\n *\n * @param token - Identity token.\n * @param applications - An object containing the applications we need to be authenticated with.\n * @param fqdn - The identity FQDN.\n */\nasync function refreshTokens(token: IdentityToken, applications: OAuthApplications, fqdn: string): Promise<Session> {\n // Refresh Identity Token\n const identityToken = await refreshAccessToken(token)\n // Exchange new identity token for application tokens\n const exchangeScopes = getExchangeScopes(applications)\n const applicationTokens = await exchangeAccessForApplicationTokens(\n identityToken,\n exchangeScopes,\n applications.adminApi?.storeFqdn,\n )\n\n return {\n [fqdn]: {\n identity: identityToken,\n applications: applicationTokens,\n },\n }\n}\n\n/**\n * Get the application tokens for a given session.\n *\n * @param applications - An object containing the applications we need the tokens for.\n * @param session - The current session.\n * @param fqdn - The identity FQDN.\n */\nasync function tokensFor(applications: OAuthApplications, session: Session, fqdn: string): Promise<OAuthSession> {\n const fqdnSession = session[fqdn]\n if (!fqdnSession) {\n throw new BugError('No session found after ensuring authenticated')\n }\n const tokens: OAuthSession = {\n userId: fqdnSession.identity.userId,\n }\n if (applications.adminApi) {\n const appId = applicationId('admin')\n const realAppId = `${applications.adminApi.storeFqdn}-${appId}`\n const token = fqdnSession.applications[realAppId]?.accessToken\n if (token) {\n tokens.admin = {token, storeFqdn: applications.adminApi.storeFqdn}\n }\n }\n\n if (applications.partnersApi) {\n const appId = applicationId('partners')\n tokens.partners = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.storefrontRendererApi) {\n const appId = applicationId('storefront-renderer')\n tokens.storefront = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.businessPlatformApi) {\n const appId = applicationId('business-platform')\n tokens.businessPlatform = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.appManagementApi) {\n const appId = applicationId('app-management')\n tokens.appManagement = fqdnSession.applications[appId]?.accessToken\n }\n\n return tokens\n}\n\n// Scope Helpers\n/**\n * Get a flattened array of scopes for the given applications.\n *\n * @param apps - An object containing the applications we need the scopes for.\n * @returns A flattened array of scopes.\n */\nfunction getFlattenScopes(apps: OAuthApplications): string[] {\n const admin = apps.adminApi?.scopes || []\n const partner = apps.partnersApi?.scopes || []\n const storefront = apps.storefrontRendererApi?.scopes || []\n const businessPlatform = apps.businessPlatformApi?.scopes || []\n const appManagement = apps.appManagementApi?.scopes || []\n const requestedScopes = [...admin, ...partner, ...storefront, ...businessPlatform, ...appManagement]\n return allDefaultScopes(requestedScopes)\n}\n\n/**\n * Get the scopes for the given applications.\n *\n * @param apps - An object containing the applications we need the scopes for.\n * @returns An object containing the scopes for each application.\n */\nfunction getExchangeScopes(apps: OAuthApplications): ExchangeScopes {\n const adminScope = apps.adminApi?.scopes || []\n const partnerScope = apps.partnersApi?.scopes || []\n const storefrontScopes = apps.storefrontRendererApi?.scopes || []\n const businessPlatformScopes = apps.businessPlatformApi?.scopes || []\n const appManagementScopes = apps.appManagementApi?.scopes || []\n return {\n admin: apiScopes('admin', adminScope),\n partners: apiScopes('partners', partnerScope),\n storefront: apiScopes('storefront-renderer', storefrontScopes),\n businessPlatform: apiScopes('business-platform', businessPlatformScopes),\n appManagement: apiScopes('app-management', appManagementScopes),\n }\n}\n\nfunction buildIdentityTokenFromEnv(\n scopes: string[],\n identityTokenInformation: {accessToken: string; refreshToken: string; userId: string},\n) {\n return {\n ...identityTokenInformation,\n expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),\n scopes,\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/private/node/session.ts"],"names":[],"mappings":"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","sourcesContent":["import {applicationId} from './session/identity.js'\nimport {validateSession} from './session/validate.js'\nimport {allDefaultScopes, apiScopes} from './session/scopes.js'\nimport {\n exchangeAccessForApplicationTokens,\n exchangeCustomPartnerToken,\n ExchangeScopes,\n refreshAccessToken,\n InvalidGrantError,\n InvalidRequestError,\n} from './session/exchange.js'\nimport {IdentityToken, Session} from './session/schema.js'\nimport * as secureStore from './session/store.js'\nimport {pollForDeviceAuthorization, requestDeviceAuthorization} from './session/device-authorization.js'\nimport {RequestClientError} from './api/headers.js'\nimport {getCachedPartnerAccountStatus, setCachedPartnerAccountStatus} from './conf-store.js'\nimport {isThemeAccessSession} from './api/rest.js'\nimport {outputContent, outputToken, outputDebug} from '../../public/node/output.js'\nimport {firstPartyDev, themeToken} from '../../public/node/context/local.js'\nimport {AbortError, BugError} from '../../public/node/error.js'\nimport {partnersRequest} from '../../public/node/api/partners.js'\nimport {normalizeStoreFqdn, partnersFqdn, identityFqdn} from '../../public/node/context/fqdn.js'\nimport {openURL} from '../../public/node/system.js'\nimport {keypress} from '../../public/node/ui.js'\nimport {getIdentityTokenInformation, getPartnersToken} from '../../public/node/environment.js'\nimport {gql} from 'graphql-request'\nimport {AdminSession} from '@shopify/cli-kit/node/session'\nimport {outputCompleted, outputInfo, outputWarn} from '@shopify/cli-kit/node/output'\nimport {isTruthy} from '@shopify/cli-kit/node/context/utilities'\nimport {isSpin} from '@shopify/cli-kit/node/context/spin'\nimport {nonRandomUUID} from '@shopify/cli-kit/node/crypto'\n\n/**\n * A scope supported by the Shopify Admin API.\n */\nexport type AdminAPIScope = 'graphql' | 'themes' | 'collaborator'\n\n/**\n * It represents the options to authenticate against the Shopify Admin API.\n */\n\ninterface AdminAPIOAuthOptions {\n /** Store to request permissions for. */\n storeFqdn: string\n /** List of scopes to request permissions for. */\n scopes: AdminAPIScope[]\n}\n\n/**\n * A scope supported by the Partners API.\n */\nexport type PartnersAPIScope = 'cli'\ninterface PartnersAPIOAuthOptions {\n /** List of scopes to request permissions for. */\n scopes: PartnersAPIScope[]\n}\n\n/**\n * A scope supported by the Developer Platform API.\n */\nexport type AppManagementAPIScope = 'https://api.shopify.com/auth/organization.apps.manage'\ninterface AppManagementAPIOauthOptions {\n /** List of scopes to request permissions for. */\n scopes: AppManagementAPIScope[]\n}\n\n/**\n * A scope supported by the Storefront Renderer API.\n */\nexport type StorefrontRendererScope = 'devtools'\ninterface StorefrontRendererAPIOAuthOptions {\n /** List of scopes to request permissions for. */\n scopes: StorefrontRendererScope[]\n}\n\nexport type BusinessPlatformScope = 'destinations'\ninterface BusinessPlatformAPIOAuthOptions {\n /** List of scopes to request permissions for. */\n scopes: BusinessPlatformScope[]\n}\n\n/**\n * It represents the authentication requirements and\n * is the input necessary to trigger the authentication\n * flow.\n */\nexport interface OAuthApplications {\n adminApi?: AdminAPIOAuthOptions\n storefrontRendererApi?: StorefrontRendererAPIOAuthOptions\n partnersApi?: PartnersAPIOAuthOptions\n businessPlatformApi?: BusinessPlatformAPIOAuthOptions\n appManagementApi?: AppManagementAPIOauthOptions\n}\n\nexport interface OAuthSession {\n admin?: AdminSession\n partners?: string\n storefront?: string\n businessPlatform?: string\n appManagement?: string\n userId: string\n}\n\ntype AuthMethod = 'partners_token' | 'device_auth' | 'theme_access_token' | 'custom_app_token' | 'none'\n\nlet userId: undefined | string\nlet authMethod: AuthMethod = 'none'\n\n/**\n * Retrieves the user ID from the current session or returns 'unknown' if not found.\n *\n * This function performs the following steps:\n * 1. Checks for a cached user ID in memory (obtained in the current run).\n * 2. Attempts to fetch it from the secure store (from a previous auth session).\n * 3. Checks if a custom token was used (either as a theme password or partners token).\n * 4. If a custom token is present in the environment, generates a UUID and uses it as userId.\n * 5. If after all this we don't have a userId, then reports as 'unknown'.\n *\n * @returns A Promise that resolves to the user ID as a string.\n */\nexport async function getLastSeenUserIdAfterAuth(): Promise<string> {\n if (userId) return userId\n\n const currentSession = (await secureStore.fetch()) || {}\n const fqdn = await identityFqdn()\n const cachedUserId = currentSession[fqdn]?.identity.userId\n if (cachedUserId) return cachedUserId\n\n const customToken = getPartnersToken() ?? themeToken()\n return customToken ? nonRandomUUID(customToken) : 'unknown'\n}\n\nexport function setLastSeenUserIdAfterAuth(id: string) {\n userId = id\n}\n\n/**\n * Retrieves the last seen authentication method used in the current session.\n *\n * This function checks for the authentication method in the following order:\n * 1. Returns the cached auth method if it's not 'none'.\n * 2. Checks for a cached session, which implies 'device_auth' was used.\n * 3. Checks for a partners token in the environment.\n * 4. Checks for a theme password in the environment.\n * 5. If none of the above are true, returns 'none'.\n *\n * @returns A Promise that resolves to the last seen authentication method as an AuthMethod type.\n */\nexport async function getLastSeenAuthMethod(): Promise<AuthMethod> {\n if (authMethod !== 'none') return authMethod\n\n const currentSession = (await secureStore.fetch()) || {}\n const fqdn = await identityFqdn()\n const cachedUserId = currentSession[fqdn]?.identity.userId\n if (cachedUserId) return 'device_auth'\n\n const partnersToken = getPartnersToken()\n if (partnersToken) return 'partners_token'\n\n const themePassword = themeToken()\n if (themePassword) {\n return isThemeAccessSession({token: themePassword, storeFqdn: ''}) ? 'theme_access_token' : 'custom_app_token'\n }\n\n return 'none'\n}\n\nexport function setLastSeenAuthMethod(method: AuthMethod) {\n authMethod = method\n}\n\n/**\n * This method ensures that we have a valid session to authenticate against the given applications using the provided scopes.\n *\n * @param applications - An object containing the applications we need to be authenticated with.\n * @param _env - Optional environment variables to use.\n * @param forceRefresh - Optional flag to force a refresh of the token.\n * @returns An instance with the access tokens organized by application.\n */\nexport async function ensureAuthenticated(\n applications: OAuthApplications,\n _env?: NodeJS.ProcessEnv,\n {forceRefresh = false, noPrompt = false}: {forceRefresh?: boolean; noPrompt?: boolean} = {},\n): Promise<OAuthSession> {\n const fqdn = await identityFqdn()\n\n const previousStoreFqdn = applications.adminApi?.storeFqdn\n if (previousStoreFqdn) {\n const normalizedStoreName = await normalizeStoreFqdn(previousStoreFqdn)\n if (previousStoreFqdn === applications.adminApi?.storeFqdn) {\n applications.adminApi.storeFqdn = normalizedStoreName\n }\n }\n\n const currentSession = (await secureStore.fetch()) || {}\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const fqdnSession = currentSession[fqdn]!\n const scopes = getFlattenScopes(applications)\n\n outputDebug(outputContent`Validating existing session against the scopes:\n${outputToken.json(scopes)}\nFor applications:\n${outputToken.json(applications)}\n`)\n const validationResult = await validateSession(scopes, applications, fqdnSession)\n\n let newSession = {}\n\n function throwOnNoPrompt() {\n if (!noPrompt || (isSpin() && firstPartyDev())) return\n throw new AbortError(\n `The currently available CLI credentials are invalid.\n\nThe CLI is currently unable to prompt for reauthentication.`,\n 'Restart the CLI process you were running. If in an interactive terminal, you will be prompted to reauthenticate. If in a non-interactive terminal, ensure the correct credentials are available in the program environment.',\n )\n }\n\n if (validationResult === 'needs_full_auth') {\n throwOnNoPrompt()\n outputDebug(outputContent`Initiating the full authentication flow...`)\n newSession = await executeCompleteFlow(applications, fqdn)\n } else if (validationResult === 'needs_refresh' || forceRefresh) {\n outputDebug(outputContent`The current session is valid but needs refresh. Refreshing...`)\n try {\n newSession = await refreshTokens(fqdnSession.identity, applications, fqdn)\n } catch (error) {\n if (error instanceof InvalidGrantError) {\n throwOnNoPrompt()\n newSession = await executeCompleteFlow(applications, fqdn)\n } else if (error instanceof InvalidRequestError) {\n await secureStore.remove()\n throw new AbortError('\\nError validating auth session', \"We've cleared the current session, please try again\")\n } else {\n throw error\n }\n }\n }\n\n const completeSession: Session = {...currentSession, ...newSession}\n\n // Save the new session info if it has changed\n if (Object.keys(newSession).length > 0) await secureStore.store(completeSession)\n const tokens = await tokensFor(applications, completeSession, fqdn)\n\n // Overwrite partners token if using a custom CLI Token\n const envToken = getPartnersToken()\n if (envToken && applications.partnersApi) {\n tokens.partners = (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n if (!envToken && tokens.partners) {\n await ensureUserHasPartnerAccount(tokens.partners, tokens.userId)\n }\n\n setLastSeenAuthMethod(envToken ? 'partners_token' : 'device_auth')\n setLastSeenUserIdAfterAuth(tokens.userId)\n return tokens\n}\n\n/**\n * Execute the full authentication flow.\n *\n * @param applications - An object containing the applications we need to be authenticated with.\n * @param identityFqdn - The identity FQDN.\n */\nasync function executeCompleteFlow(applications: OAuthApplications, identityFqdn: string): Promise<Session> {\n const scopes = getFlattenScopes(applications)\n const exchangeScopes = getExchangeScopes(applications)\n const store = applications.adminApi?.storeFqdn\n if (firstPartyDev()) {\n outputDebug(outputContent`Authenticating as Shopify Employee...`)\n scopes.push('employee')\n }\n\n let identityToken: IdentityToken\n const identityTokenInformation = getIdentityTokenInformation()\n if (identityTokenInformation) {\n identityToken = buildIdentityTokenFromEnv(scopes, identityTokenInformation)\n } else {\n // Request a device code to authorize without a browser redirect.\n outputDebug(outputContent`Requesting device authorization code...`)\n const deviceAuth = await requestDeviceAuthorization(scopes)\n\n // Poll for the identity token\n outputDebug(outputContent`Starting polling for the identity token...`)\n identityToken = await pollForDeviceAuthorization(deviceAuth.deviceCode, deviceAuth.interval)\n }\n\n // Exchange identity token for application tokens\n outputDebug(outputContent`CLI token received. Exchanging it for application tokens...`)\n const result = await exchangeAccessForApplicationTokens(identityToken, exchangeScopes, store)\n\n const session: Session = {\n [identityFqdn]: {\n identity: identityToken,\n applications: result,\n },\n }\n\n outputCompleted('Logged in.')\n\n return session\n}\n\n/**\n * If the user creates an account from the Identity website, the created\n * account won't get a Partner organization created. We need to detect that\n * and take the user to create a partner organization.\n *\n * @param partnersToken - Partners token.\n */\nasync function ensureUserHasPartnerAccount(partnersToken: string, userId: string | undefined) {\n if (isTruthy(process.env.USE_APP_MANAGEMENT_API)) return\n\n outputDebug(outputContent`Verifying that the user has a Partner organization`)\n if (!(await hasPartnerAccount(partnersToken, userId))) {\n outputInfo(`\\nA Shopify Partners organization is needed to proceed.`)\n outputInfo(`👉 Press any key to create one`)\n await keypress()\n await openURL(`https://${await partnersFqdn()}/signup`)\n outputInfo(outputContent`👉 Press any key when you have ${outputToken.cyan('created the organization')}`)\n outputWarn(outputContent`Make sure you've confirmed your Shopify and the Partner organization from the email`)\n await keypress()\n if (!(await hasPartnerAccount(partnersToken, userId))) {\n throw new AbortError(\n `Couldn't find your Shopify Partners organization`,\n `Have you confirmed your accounts from the emails you received?`,\n )\n }\n }\n}\n\n// eslint-disable-next-line @shopify/cli/no-inline-graphql\nconst getFirstOrganization = gql`\n {\n organizations(first: 1) {\n nodes {\n id\n }\n }\n }\n`\n\n/**\n * Validate if the current token is valid for partners API.\n *\n * @param partnersToken - Partners token.\n * @returns A promise that resolves to true if the token is valid for partners API.\n */\nasync function hasPartnerAccount(partnersToken: string, userId?: string): Promise<boolean> {\n const cacheKey = userId ?? partnersToken\n const cachedStatus = getCachedPartnerAccountStatus(cacheKey)\n\n if (cachedStatus) {\n outputDebug(`Confirmed partner account exists from cache`)\n return true\n }\n\n try {\n await partnersRequest(getFirstOrganization, partnersToken)\n setCachedPartnerAccountStatus(cacheKey)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n if (error instanceof RequestClientError && error.statusCode === 404) {\n return false\n } else {\n return true\n }\n }\n}\n\n/**\n * Refresh the tokens for a given session.\n *\n * @param token - Identity token.\n * @param applications - An object containing the applications we need to be authenticated with.\n * @param fqdn - The identity FQDN.\n */\nasync function refreshTokens(token: IdentityToken, applications: OAuthApplications, fqdn: string): Promise<Session> {\n // Refresh Identity Token\n const identityToken = await refreshAccessToken(token)\n // Exchange new identity token for application tokens\n const exchangeScopes = getExchangeScopes(applications)\n const applicationTokens = await exchangeAccessForApplicationTokens(\n identityToken,\n exchangeScopes,\n applications.adminApi?.storeFqdn,\n )\n\n return {\n [fqdn]: {\n identity: identityToken,\n applications: applicationTokens,\n },\n }\n}\n\n/**\n * Get the application tokens for a given session.\n *\n * @param applications - An object containing the applications we need the tokens for.\n * @param session - The current session.\n * @param fqdn - The identity FQDN.\n */\nasync function tokensFor(applications: OAuthApplications, session: Session, fqdn: string): Promise<OAuthSession> {\n const fqdnSession = session[fqdn]\n if (!fqdnSession) {\n throw new BugError('No session found after ensuring authenticated')\n }\n const tokens: OAuthSession = {\n userId: fqdnSession.identity.userId,\n }\n if (applications.adminApi) {\n const appId = applicationId('admin')\n const realAppId = `${applications.adminApi.storeFqdn}-${appId}`\n const token = fqdnSession.applications[realAppId]?.accessToken\n if (token) {\n tokens.admin = {token, storeFqdn: applications.adminApi.storeFqdn}\n }\n }\n\n if (applications.partnersApi) {\n const appId = applicationId('partners')\n tokens.partners = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.storefrontRendererApi) {\n const appId = applicationId('storefront-renderer')\n tokens.storefront = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.businessPlatformApi) {\n const appId = applicationId('business-platform')\n tokens.businessPlatform = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.appManagementApi) {\n const appId = applicationId('app-management')\n tokens.appManagement = fqdnSession.applications[appId]?.accessToken\n }\n\n return tokens\n}\n\n// Scope Helpers\n/**\n * Get a flattened array of scopes for the given applications.\n *\n * @param apps - An object containing the applications we need the scopes for.\n * @returns A flattened array of scopes.\n */\nfunction getFlattenScopes(apps: OAuthApplications): string[] {\n const admin = apps.adminApi?.scopes || []\n const partner = apps.partnersApi?.scopes || []\n const storefront = apps.storefrontRendererApi?.scopes || []\n const businessPlatform = apps.businessPlatformApi?.scopes || []\n const appManagement = apps.appManagementApi?.scopes || []\n const requestedScopes = [...admin, ...partner, ...storefront, ...businessPlatform, ...appManagement]\n return allDefaultScopes(requestedScopes)\n}\n\n/**\n * Get the scopes for the given applications.\n *\n * @param apps - An object containing the applications we need the scopes for.\n * @returns An object containing the scopes for each application.\n */\nfunction getExchangeScopes(apps: OAuthApplications): ExchangeScopes {\n const adminScope = apps.adminApi?.scopes || []\n const partnerScope = apps.partnersApi?.scopes || []\n const storefrontScopes = apps.storefrontRendererApi?.scopes || []\n const businessPlatformScopes = apps.businessPlatformApi?.scopes || []\n const appManagementScopes = apps.appManagementApi?.scopes || []\n return {\n admin: apiScopes('admin', adminScope),\n partners: apiScopes('partners', partnerScope),\n storefront: apiScopes('storefront-renderer', storefrontScopes),\n businessPlatform: apiScopes('business-platform', businessPlatformScopes),\n appManagement: apiScopes('app-management', appManagementScopes),\n }\n}\n\nfunction buildIdentityTokenFromEnv(\n scopes: string[],\n identityTokenInformation: {accessToken: string; refreshToken: string; userId: string},\n) {\n return {\n ...identityTokenInformation,\n expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),\n scopes,\n }\n}\n"]}
|
|
@@ -38,11 +38,8 @@ export const render = (tree, options = {}) => {
|
|
|
38
38
|
const stderr = new Stderr();
|
|
39
39
|
const stdin = new Stdin();
|
|
40
40
|
const instance = inkRender(tree, {
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
41
|
stdout: options.stdout ?? stdout,
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
42
|
stderr: options.stderr ?? stderr,
|
|
45
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
43
|
stdin: options.stdin ?? stdin,
|
|
47
44
|
debug: true,
|
|
48
45
|
exitOnCtrlC: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../../src/private/node/testing/ui.ts"],"names":[],"mappings":"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","sourcesContent":["import {isTruthy} from '../../../public/node/context/utilities.js'\nimport {Stdout} from '../ui.js'\nimport {ReactElement} from 'react'\nimport {render as inkRender} from 'ink'\nimport {EventEmitter} from 'events'\n\nclass Stderr extends EventEmitter {\n readonly frames: string[] = []\n private _lastFrame?: string\n\n write = (frame: string) => {\n this.frames.push(frame)\n this._lastFrame = frame\n }\n\n lastFrame = () => this._lastFrame\n}\n\nexport class Stdin extends EventEmitter {\n isTTY: boolean\n data: string | null = null\n\n constructor(options: {isTTY?: boolean} = {}) {\n super()\n this.isTTY = options.isTTY ?? true\n }\n\n write = (data: string) => {\n this.data = data\n this.emit('readable')\n }\n\n setEncoding() {}\n setRawMode() {}\n ref() {}\n unref() {}\n read: () => string | null = () => {\n const data = this.data\n\n this.data = null\n\n return data\n }\n}\n\ninterface Instance {\n rerender: (tree: ReactElement) => void\n unmount: () => void\n cleanup: () => void\n stdout: Stdout\n stderr: Stderr\n stdin: Stdin\n frames: string[]\n lastFrame: () => string | undefined\n waitUntilExit: () => TrackedPromise<void>\n}\n\ninterface RenderOptions {\n stdout?: EventEmitter\n stderr?: EventEmitter\n stdin?: EventEmitter\n}\n\nexport const render = (tree: ReactElement, options: RenderOptions = {}): Instance => {\n const stdout = new Stdout({columns: 100})\n const stderr = new Stderr()\n const stdin = new Stdin()\n\n const instance = inkRender(tree, {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stdout: options.stdout ?? (stdout as any),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stderr: options.stderr ?? (stderr as any),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stdin: options.stdin ?? (stdin as any),\n debug: true,\n exitOnCtrlC: false,\n patchConsole: false,\n })\n\n return {\n rerender: instance.rerender,\n unmount: instance.unmount,\n cleanup: instance.cleanup,\n waitUntilExit: () => trackPromise(instance.waitUntilExit()),\n stdout,\n stderr,\n stdin,\n frames: stdout.frames,\n lastFrame: stdout.lastFrame,\n }\n}\n\n/**\n * Wait for the component to be ready to accept input.\n */\nexport function waitForInputsToBeReady() {\n return new Promise((resolve) => setTimeout(resolve, 100))\n}\n\n/**\n * Wait for the last frame to change to anything.\n */\nexport function waitForChange(func: () => void, getChangingValue: () => string | number | undefined) {\n return new Promise<void>((resolve) => {\n const initialValue = getChangingValue()\n\n func()\n\n const interval = setInterval(() => {\n if (getChangingValue() !== initialValue) {\n clearInterval(interval)\n resolve()\n }\n }, 10)\n })\n}\n\nexport function waitFor(func: () => void, condition: () => boolean) {\n return new Promise<void>((resolve) => {\n func()\n\n const interval = setInterval(() => {\n if (condition()) {\n clearInterval(interval)\n resolve()\n }\n }, 10)\n })\n}\n\n/**\n * Wait for the last frame to contain specific text.\n */\nexport function waitForContent(\n renderInstance: ReturnType<typeof render>,\n content: string,\n func: () => void = () => {},\n) {\n return waitFor(\n () => func(),\n () => renderInstance.lastFrame()!.includes(content),\n )\n}\n\n/**\n * Send input and wait for the last frame to change.\n *\n * Useful when you want to send some input and wait for anything to change in the interface.\n * If you need to wait for a specific change instead, you can use sendInputAndWaitForContent.\n */\nexport async function sendInputAndWaitForChange(renderInstance: ReturnType<typeof render>, ...inputs: string[]) {\n await waitForChange(() => inputs.forEach((input) => renderInstance.stdin.write(input)), renderInstance.lastFrame)\n // wait for another tick so we give time to react to update caches\n await new Promise((resolve) => setTimeout(resolve, 0))\n}\n\n/** Send input and wait a number of milliseconds.\n *\n * Useful if you know some what will happen after input will take a certain amount of time\n * and it will not cause any visible change so you can't use sendInputAndWaitForChange.\n * This function can also be used if you want to test that nothing changes after some input has been sent.\n */\nexport async function sendInputAndWait(\n renderInstance: ReturnType<typeof render>,\n waitTime: number,\n ...inputs: string[]\n) {\n inputs.forEach((input) => renderInstance.stdin.write(input))\n await new Promise((resolve) => setTimeout(resolve, waitTime))\n}\n\n/**\n * Send input and wait for the last frame to contain specific text.\n *\n * Useful when you want to send some input and wait for a specific change to happen.\n * If you need to wait for any change instead, you can use sendInputAndWaitForChange.\n */\nexport async function sendInputAndWaitForContent(\n renderInstance: ReturnType<typeof render>,\n content: string,\n ...inputs: string[]\n) {\n await waitForContent(renderInstance, content, () => inputs.forEach((input) => renderInstance.stdin.write(input)))\n}\n\n/** Function that is useful when you want to check the last frame of a component that unmounted.\n *\n * The reason this function exists is that in CI Ink will clear the last frame on unmount.\n */\nexport function getLastFrameAfterUnmount(renderInstance: ReturnType<typeof render>) {\n return isTruthy(process.env.CI) ? renderInstance.frames[renderInstance.frames.length - 2] : renderInstance.lastFrame()\n}\n\ntype TrackedPromise<T> = Promise<T> & {\n isFulfilled: () => boolean\n isPending: () => boolean\n isRejected: () => boolean\n}\n\nfunction trackPromise<T>(promise: Promise<T>): TrackedPromise<T> {\n let isPending = true\n let isRejected = false\n let isFulfilled = false\n\n const trackedPromise = promise.then(\n function (result) {\n isFulfilled = true\n isPending = false\n return result\n },\n function (error) {\n isRejected = true\n isPending = false\n throw error\n },\n ) as TrackedPromise<T>\n\n trackedPromise.isFulfilled = function () {\n return isFulfilled\n }\n trackedPromise.isPending = function () {\n return isPending\n }\n trackedPromise.isRejected = function () {\n return isRejected\n }\n\n return trackedPromise\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../../src/private/node/testing/ui.ts"],"names":[],"mappings":"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","sourcesContent":["import {isTruthy} from '../../../public/node/context/utilities.js'\nimport {Stdout} from '../ui.js'\nimport {ReactElement} from 'react'\nimport {render as inkRender} from 'ink'\nimport {EventEmitter} from 'events'\n\nclass Stderr extends EventEmitter {\n readonly frames: string[] = []\n private _lastFrame?: string\n\n write = (frame: string) => {\n this.frames.push(frame)\n this._lastFrame = frame\n }\n\n lastFrame = () => this._lastFrame\n}\n\nexport class Stdin extends EventEmitter {\n isTTY: boolean\n data: string | null = null\n\n constructor(options: {isTTY?: boolean} = {}) {\n super()\n this.isTTY = options.isTTY ?? true\n }\n\n write = (data: string) => {\n this.data = data\n this.emit('readable')\n }\n\n setEncoding() {}\n setRawMode() {}\n ref() {}\n unref() {}\n read: () => string | null = () => {\n const data = this.data\n\n this.data = null\n\n return data\n }\n}\n\ninterface Instance {\n rerender: (tree: ReactElement) => void\n unmount: () => void\n cleanup: () => void\n stdout: Stdout\n stderr: Stderr\n stdin: Stdin\n frames: string[]\n lastFrame: () => string | undefined\n waitUntilExit: () => TrackedPromise<void>\n}\n\ninterface RenderOptions {\n stdout?: EventEmitter\n stderr?: EventEmitter\n stdin?: EventEmitter\n}\n\nexport const render = (tree: ReactElement, options: RenderOptions = {}): Instance => {\n const stdout = new Stdout({columns: 100})\n const stderr = new Stderr()\n const stdin = new Stdin()\n\n const instance = inkRender(tree, {\n stdout: options.stdout ?? (stdout as any),\n\n stderr: options.stderr ?? (stderr as any),\n\n stdin: options.stdin ?? (stdin as any),\n debug: true,\n exitOnCtrlC: false,\n patchConsole: false,\n })\n\n return {\n rerender: instance.rerender,\n unmount: instance.unmount,\n cleanup: instance.cleanup,\n waitUntilExit: () => trackPromise(instance.waitUntilExit()),\n stdout,\n stderr,\n stdin,\n frames: stdout.frames,\n lastFrame: stdout.lastFrame,\n }\n}\n\n/**\n * Wait for the component to be ready to accept input.\n */\nexport function waitForInputsToBeReady() {\n return new Promise((resolve) => setTimeout(resolve, 100))\n}\n\n/**\n * Wait for the last frame to change to anything.\n */\nexport function waitForChange(func: () => void, getChangingValue: () => string | number | undefined) {\n return new Promise<void>((resolve) => {\n const initialValue = getChangingValue()\n\n func()\n\n const interval = setInterval(() => {\n if (getChangingValue() !== initialValue) {\n clearInterval(interval)\n resolve()\n }\n }, 10)\n })\n}\n\nexport function waitFor(func: () => void, condition: () => boolean) {\n return new Promise<void>((resolve) => {\n func()\n\n const interval = setInterval(() => {\n if (condition()) {\n clearInterval(interval)\n resolve()\n }\n }, 10)\n })\n}\n\n/**\n * Wait for the last frame to contain specific text.\n */\nexport function waitForContent(\n renderInstance: ReturnType<typeof render>,\n content: string,\n func: () => void = () => {},\n) {\n return waitFor(\n () => func(),\n\n () => renderInstance.lastFrame()!.includes(content),\n )\n}\n\n/**\n * Send input and wait for the last frame to change.\n *\n * Useful when you want to send some input and wait for anything to change in the interface.\n * If you need to wait for a specific change instead, you can use sendInputAndWaitForContent.\n */\nexport async function sendInputAndWaitForChange(renderInstance: ReturnType<typeof render>, ...inputs: string[]) {\n await waitForChange(() => inputs.forEach((input) => renderInstance.stdin.write(input)), renderInstance.lastFrame)\n // wait for another tick so we give time to react to update caches\n await new Promise((resolve) => setTimeout(resolve, 0))\n}\n\n/** Send input and wait a number of milliseconds.\n *\n * Useful if you know some what will happen after input will take a certain amount of time\n * and it will not cause any visible change so you can't use sendInputAndWaitForChange.\n * This function can also be used if you want to test that nothing changes after some input has been sent.\n */\nexport async function sendInputAndWait(\n renderInstance: ReturnType<typeof render>,\n waitTime: number,\n ...inputs: string[]\n) {\n inputs.forEach((input) => renderInstance.stdin.write(input))\n await new Promise((resolve) => setTimeout(resolve, waitTime))\n}\n\n/**\n * Send input and wait for the last frame to contain specific text.\n *\n * Useful when you want to send some input and wait for a specific change to happen.\n * If you need to wait for any change instead, you can use sendInputAndWaitForChange.\n */\nexport async function sendInputAndWaitForContent(\n renderInstance: ReturnType<typeof render>,\n content: string,\n ...inputs: string[]\n) {\n await waitForContent(renderInstance, content, () => inputs.forEach((input) => renderInstance.stdin.write(input)))\n}\n\n/** Function that is useful when you want to check the last frame of a component that unmounted.\n *\n * The reason this function exists is that in CI Ink will clear the last frame on unmount.\n */\nexport function getLastFrameAfterUnmount(renderInstance: ReturnType<typeof render>) {\n return isTruthy(process.env.CI) ? renderInstance.frames[renderInstance.frames.length - 2] : renderInstance.lastFrame()\n}\n\ntype TrackedPromise<T> = Promise<T> & {\n isFulfilled: () => boolean\n isPending: () => boolean\n isRejected: () => boolean\n}\n\nfunction trackPromise<T>(promise: Promise<T>): TrackedPromise<T> {\n let isPending = true\n let isRejected = false\n let isFulfilled = false\n\n const trackedPromise = promise.then(\n function (result) {\n isFulfilled = true\n isPending = false\n return result\n },\n function (error) {\n isRejected = true\n isPending = false\n throw error\n },\n ) as TrackedPromise<T>\n\n trackedPromise.isFulfilled = function () {\n return isFulfilled\n }\n trackedPromise.isPending = function () {\n return isPending\n }\n trackedPromise.isRejected = function () {\n return isRejected\n }\n\n return trackedPromise\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import { randomBytes } from 'crypto';
|
|
|
3
3
|
import { hostname } from 'os';
|
|
4
4
|
export const API_NAME_LIMIT = 50;
|
|
5
5
|
export function generateThemeName(context) {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
6
7
|
const hostNameWithoutDomain = hostname().split('.')[0];
|
|
7
8
|
const hash = randomBytes(3).toString('hex');
|
|
8
9
|
const name = `${context} ()`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-theme-name.js","sourceRoot":"","sources":["../../../../src/private/node/themes/generate-theme-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,wBAAwB,EAAC,MAAM,iCAAiC,CAAA;AACxE,OAAO,EAAC,WAAW,EAAC,MAAM,QAAQ,CAAA;AAClC,OAAO,EAAC,QAAQ,EAAC,MAAM,IAAI,CAAA;AAE3B,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAA;AAEhC,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,qBAAqB,GAAG,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAA;IACvD,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE3C,MAAM,IAAI,GAAG,GAAG,OAAO,KAAK,CAAA;IAC5B,MAAM,sBAAsB,GAAG,cAAc,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7E,MAAM,UAAU,GAAG,wBAAwB,CAAC,GAAG,IAAI,IAAI,qBAAqB,CAAC,SAAS,CAAC,CAAC,EAAE,sBAAsB,CAAC,EAAE,CAAC,CAAA;IACpH,OAAO,GAAG,OAAO,KAAK,UAAU,GAAG,CAAA;AACrC,CAAC","sourcesContent":["import {replaceInvalidCharacters} from './replace-invalid-characters.js'\nimport {randomBytes} from 'crypto'\nimport {hostname} from 'os'\n\nexport const API_NAME_LIMIT = 50\n\nexport function generateThemeName(context: string): string {\n const hostNameWithoutDomain = hostname().split('.')[0]!\n const hash = randomBytes(3).toString('hex')\n\n const name = `${context} ()`\n const hostNameCharacterLimit = API_NAME_LIMIT - name.length - hash.length - 1\n const identifier = replaceInvalidCharacters(`${hash}-${hostNameWithoutDomain.substring(0, hostNameCharacterLimit)}`)\n return `${context} (${identifier})`\n}\n"]}
|
|
1
|
+
{"version":3,"file":"generate-theme-name.js","sourceRoot":"","sources":["../../../../src/private/node/themes/generate-theme-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,wBAAwB,EAAC,MAAM,iCAAiC,CAAA;AACxE,OAAO,EAAC,WAAW,EAAC,MAAM,QAAQ,CAAA;AAClC,OAAO,EAAC,QAAQ,EAAC,MAAM,IAAI,CAAA;AAE3B,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAA;AAEhC,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,oEAAoE;IACpE,MAAM,qBAAqB,GAAG,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAA;IACvD,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE3C,MAAM,IAAI,GAAG,GAAG,OAAO,KAAK,CAAA;IAC5B,MAAM,sBAAsB,GAAG,cAAc,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7E,MAAM,UAAU,GAAG,wBAAwB,CAAC,GAAG,IAAI,IAAI,qBAAqB,CAAC,SAAS,CAAC,CAAC,EAAE,sBAAsB,CAAC,EAAE,CAAC,CAAA;IACpH,OAAO,GAAG,OAAO,KAAK,UAAU,GAAG,CAAA;AACrC,CAAC","sourcesContent":["import {replaceInvalidCharacters} from './replace-invalid-characters.js'\nimport {randomBytes} from 'crypto'\nimport {hostname} from 'os'\n\nexport const API_NAME_LIMIT = 50\n\nexport function generateThemeName(context: string): string {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const hostNameWithoutDomain = hostname().split('.')[0]!\n const hash = randomBytes(3).toString('hex')\n\n const name = `${context} ()`\n const hostNameCharacterLimit = API_NAME_LIMIT - name.length - hash.length - 1\n const identifier = replaceInvalidCharacters(`${hash}-${hostNameWithoutDomain.substring(0, hostNameCharacterLimit)}`)\n return `${context} (${identifier})`\n}\n"]}
|
|
@@ -6,7 +6,6 @@ import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import { useStdout } from 'ink';
|
|
8
8
|
vi.mock('ink', async () => {
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
9
|
const original = await vi.importActual('ink');
|
|
11
10
|
return {
|
|
12
11
|
...original,
|
|
@@ -73,7 +72,6 @@ beforeEach(() => {
|
|
|
73
72
|
stdout: new Stdout({
|
|
74
73
|
columns: 80,
|
|
75
74
|
rows: 80,
|
|
76
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
75
|
}),
|
|
78
76
|
write: () => { },
|
|
79
77
|
});
|
|
@@ -554,7 +552,6 @@ describe('AutocompletePrompt', async () => {
|
|
|
554
552
|
});
|
|
555
553
|
test('adapts to the height of the container', async () => {
|
|
556
554
|
vi.mocked(useStdout).mockReturnValue({
|
|
557
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
558
555
|
stdout: new Stdout({ rows: 10 }),
|
|
559
556
|
write: () => { },
|
|
560
557
|
});
|