@shopify/cli-kit 4.2.0 → 4.4.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/bulk-operations/generated/bulk-operation-cancel.d.ts +28 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.js +74 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.d.ts +28 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.js +92 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.d.ts +26 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.js +72 -0
- package/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.d.ts +19 -0
- package/dist/cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js +49 -0
- package/dist/cli/api/graphql/bulk-operations/generated/get-bulk-operation-by-id.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.d.ts +22 -0
- package/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.js +78 -0
- package/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.js.map +1 -0
- package/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.d.ts +22 -0
- package/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.js +82 -0
- package/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.js.map +1 -0
- package/dist/private/node/api/headers.js +1 -1
- package/dist/private/node/api/headers.js.map +1 -1
- package/dist/private/node/session/store.js +10 -1
- package/dist/private/node/session/store.js.map +1 -1
- package/dist/private/node/ui/components/Alert.test.js +5 -5
- package/dist/private/node/ui/components/Alert.test.js.map +1 -1
- package/dist/private/node/ui/components/Banner.js +9 -1
- package/dist/private/node/ui/components/Banner.js.map +1 -1
- package/dist/public/common/url.js +13 -4
- 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/api/admin.d.ts +2 -1
- package/dist/public/node/api/admin.js +4 -3
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/bulk-operations/cancel.d.ts +15 -0
- package/dist/public/node/api/bulk-operations/cancel.js +20 -0
- package/dist/public/node/api/bulk-operations/cancel.js.map +1 -0
- package/dist/public/node/api/bulk-operations/constants.d.ts +5 -0
- package/dist/public/node/api/bulk-operations/constants.js +6 -0
- package/dist/public/node/api/bulk-operations/constants.js.map +1 -0
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.d.ts +17 -0
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js +48 -0
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js.map +1 -0
- package/dist/public/node/api/bulk-operations/fetch.d.ts +31 -0
- package/dist/public/node/api/bulk-operations/fetch.js +42 -0
- package/dist/public/node/api/bulk-operations/fetch.js.map +1 -0
- package/dist/public/node/api/bulk-operations/format-bulk-operation-status.d.ts +45 -0
- package/dist/public/node/api/bulk-operations/format-bulk-operation-status.js +91 -0
- package/dist/public/node/api/bulk-operations/format-bulk-operation-status.js.map +1 -0
- package/dist/public/node/api/bulk-operations/helpers.d.ts +51 -0
- package/dist/public/node/api/bulk-operations/helpers.js +110 -0
- package/dist/public/node/api/bulk-operations/helpers.js.map +1 -0
- package/dist/public/node/api/bulk-operations/query.d.ts +22 -0
- package/dist/public/node/api/bulk-operations/query.js +40 -0
- package/dist/public/node/api/bulk-operations/query.js.map +1 -0
- package/dist/public/node/api/bulk-operations/run-mutation.d.ts +16 -0
- package/dist/public/node/api/bulk-operations/run-mutation.js +27 -0
- package/dist/public/node/api/bulk-operations/run-mutation.js.map +1 -0
- package/dist/public/node/api/bulk-operations/run-query.d.ts +15 -0
- package/dist/public/node/api/bulk-operations/run-query.js +19 -0
- package/dist/public/node/api/bulk-operations/run-query.js.map +1 -0
- package/dist/public/node/api/bulk-operations/stage-file.d.ts +13 -0
- package/dist/public/node/api/bulk-operations/stage-file.js +89 -0
- package/dist/public/node/api/bulk-operations/stage-file.js.map +1 -0
- package/dist/public/node/api/bulk-operations/watch-bulk-operation.d.ts +26 -0
- package/dist/public/node/api/bulk-operations/watch-bulk-operation.js +131 -0
- package/dist/public/node/api/bulk-operations/watch-bulk-operation.js.map +1 -0
- package/dist/public/node/api/bulk-operations.d.ts +18 -0
- package/dist/public/node/api/bulk-operations.js +19 -0
- package/dist/public/node/api/bulk-operations.js.map +1 -0
- package/dist/public/node/constants.d.ts +1 -0
- package/dist/public/node/constants.js +2 -0
- package/dist/public/node/constants.js.map +1 -0
- package/dist/public/node/context/fqdn.js +46 -5
- package/dist/public/node/context/fqdn.js.map +1 -1
- package/dist/public/node/graphiql/session.d.ts +50 -0
- package/dist/public/node/graphiql/session.js +92 -0
- package/dist/public/node/graphiql/session.js.map +1 -0
- package/dist/public/node/graphiql/templates/graphiql.js +1 -4
- package/dist/public/node/graphiql/templates/graphiql.js.map +1 -1
- package/dist/public/node/json-schema.js +22 -6
- package/dist/public/node/json-schema.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/session.d.ts +2 -1
- package/dist/public/node/session.js +3 -2
- package/dist/public/node/session.js.map +1 -1
- package/dist/public/node/store-auth-session.d.ts +113 -0
- package/dist/public/node/store-auth-session.js +257 -0
- package/dist/public/node/store-auth-session.js.map +1 -0
- package/dist/public/node/ui.d.ts +2 -6
- package/dist/public/node/ui.js +2 -6
- package/dist/public/node/ui.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export const StagedUploadsCreate = {
|
|
2
|
+
kind: 'Document',
|
|
3
|
+
definitions: [
|
|
4
|
+
{
|
|
5
|
+
kind: 'OperationDefinition',
|
|
6
|
+
operation: 'mutation',
|
|
7
|
+
name: { kind: 'Name', value: 'StagedUploadsCreate' },
|
|
8
|
+
variableDefinitions: [
|
|
9
|
+
{
|
|
10
|
+
kind: 'VariableDefinition',
|
|
11
|
+
variable: { kind: 'Variable', name: { kind: 'Name', value: 'input' } },
|
|
12
|
+
type: {
|
|
13
|
+
kind: 'NonNullType',
|
|
14
|
+
type: {
|
|
15
|
+
kind: 'ListType',
|
|
16
|
+
type: { kind: 'NonNullType', type: { kind: 'NamedType', name: { kind: 'Name', value: 'StagedUploadInput' } } },
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
selectionSet: {
|
|
22
|
+
kind: 'SelectionSet',
|
|
23
|
+
selections: [
|
|
24
|
+
{
|
|
25
|
+
kind: 'Field',
|
|
26
|
+
name: { kind: 'Name', value: 'stagedUploadsCreate' },
|
|
27
|
+
arguments: [
|
|
28
|
+
{
|
|
29
|
+
kind: 'Argument',
|
|
30
|
+
name: { kind: 'Name', value: 'input' },
|
|
31
|
+
value: { kind: 'Variable', name: { kind: 'Name', value: 'input' } },
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
selectionSet: {
|
|
35
|
+
kind: 'SelectionSet',
|
|
36
|
+
selections: [
|
|
37
|
+
{
|
|
38
|
+
kind: 'Field',
|
|
39
|
+
name: { kind: 'Name', value: 'stagedTargets' },
|
|
40
|
+
selectionSet: {
|
|
41
|
+
kind: 'SelectionSet',
|
|
42
|
+
selections: [
|
|
43
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'url' } },
|
|
44
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'resourceUrl' } },
|
|
45
|
+
{
|
|
46
|
+
kind: 'Field',
|
|
47
|
+
name: { kind: 'Name', value: 'parameters' },
|
|
48
|
+
selectionSet: {
|
|
49
|
+
kind: 'SelectionSet',
|
|
50
|
+
selections: [
|
|
51
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
|
|
52
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'value' } },
|
|
53
|
+
{ kind: 'Field', name: { kind: 'Name', value: '__typename' } },
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{ kind: 'Field', name: { kind: 'Name', value: '__typename' } },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
kind: 'Field',
|
|
63
|
+
name: { kind: 'Name', value: 'userErrors' },
|
|
64
|
+
selectionSet: {
|
|
65
|
+
kind: 'SelectionSet',
|
|
66
|
+
selections: [
|
|
67
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'field' } },
|
|
68
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'message' } },
|
|
69
|
+
{ kind: 'Field', name: { kind: 'Name', value: '__typename' } },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{ kind: 'Field', name: { kind: 'Name', value: '__typename' } },
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=staged-uploads-create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staged-uploads-create.js","sourceRoot":"","sources":["../../../../../../src/cli/api/graphql/bulk-operations/generated/staged-uploads-create.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/consistent-type-definitions */\nimport * as Types from './types.js'\n\nimport {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'\n\nexport type StagedUploadsCreateMutationVariables = Types.Exact<{\n input: Types.StagedUploadInput[] | Types.StagedUploadInput\n}>\n\nexport type StagedUploadsCreateMutation = {\n stagedUploadsCreate?: {\n stagedTargets?:\n | {\n url?: string | null\n resourceUrl?: string | null\n parameters: {name: string; value: string}[]\n }[]\n | null\n userErrors: {field?: string[] | null; message: string}[]\n } | null\n}\n\nexport const StagedUploadsCreate = {\n kind: 'Document',\n definitions: [\n {\n kind: 'OperationDefinition',\n operation: 'mutation',\n name: {kind: 'Name', value: 'StagedUploadsCreate'},\n variableDefinitions: [\n {\n kind: 'VariableDefinition',\n variable: {kind: 'Variable', name: {kind: 'Name', value: 'input'}},\n type: {\n kind: 'NonNullType',\n type: {\n kind: 'ListType',\n type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'StagedUploadInput'}}},\n },\n },\n },\n ],\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {\n kind: 'Field',\n name: {kind: 'Name', value: 'stagedUploadsCreate'},\n arguments: [\n {\n kind: 'Argument',\n name: {kind: 'Name', value: 'input'},\n value: {kind: 'Variable', name: {kind: 'Name', value: 'input'}},\n },\n ],\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {\n kind: 'Field',\n name: {kind: 'Name', value: 'stagedTargets'},\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {kind: 'Field', name: {kind: 'Name', value: 'url'}},\n {kind: 'Field', name: {kind: 'Name', value: 'resourceUrl'}},\n {\n kind: 'Field',\n name: {kind: 'Name', value: 'parameters'},\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {kind: 'Field', name: {kind: 'Name', value: 'name'}},\n {kind: 'Field', name: {kind: 'Name', value: 'value'}},\n {kind: 'Field', name: {kind: 'Name', value: '__typename'}},\n ],\n },\n },\n {kind: 'Field', name: {kind: 'Name', value: '__typename'}},\n ],\n },\n },\n {\n kind: 'Field',\n name: {kind: 'Name', value: 'userErrors'},\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {kind: 'Field', name: {kind: 'Name', value: 'field'}},\n {kind: 'Field', name: {kind: 'Name', value: 'message'}},\n {kind: 'Field', name: {kind: 'Name', value: '__typename'}},\n ],\n },\n },\n {kind: 'Field', name: {kind: 'Name', value: '__typename'}},\n ],\n },\n },\n ],\n },\n },\n ],\n} as unknown as DocumentNode<StagedUploadsCreateMutation, StagedUploadsCreateMutationVariables>\n"]}
|
|
@@ -19,7 +19,7 @@ export class GraphQLClientError extends RequestClientError {
|
|
|
19
19
|
this.stack = undefined;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
const SENSITIVE_HEADERS = ['token', 'authorization', 'subject_token', 'cookie'];
|
|
22
|
+
const SENSITIVE_HEADERS = ['token', 'authorization', 'subject_token', 'cookie', 'signature'];
|
|
23
23
|
/**
|
|
24
24
|
* Removes the sensitive data from the headers and outputs them as a string.
|
|
25
25
|
* @param headers - HTTP headers.
|
|
@@ -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,EAAE,UAAU,EAAE,SAAS,EAAC,MAAM,uCAAuC,CAAA;AAC1F,OAAO,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAA;AACxD,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,kBAAmB,SAAQ,UAAU;IAEzC,YAAmB,OAAe,EAAE,UAAkB;QACpD,MAAM,UAAU,GACd,UAAU,KAAK,GAAG;YAChB,CAAC,CAAC,oFAAoF;YACtF,CAAC,CAAC,SAAS,CAAA;QACf,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC1B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;CACF;AACD,MAAM,OAAO,kBAAmB,SAAQ,kBAAkB;IAIxD,8DAA8D;IAC9D,YAAmB,OAAe,EAAE,UAAkB,EAAE,MAAc;QACpE,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;IACxB,CAAC;CACF;AAED,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,CAAC,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', 'signature']\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"]}
|
|
@@ -19,7 +19,16 @@ export async function fetch() {
|
|
|
19
19
|
if (!content) {
|
|
20
20
|
return undefined;
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
let contentJson;
|
|
23
|
+
try {
|
|
24
|
+
contentJson = JSON.parse(content);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (!(error instanceof SyntaxError))
|
|
28
|
+
throw error;
|
|
29
|
+
await remove();
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
23
32
|
const parsedSessions = await SessionsSchema.safeParseAsync(contentJson);
|
|
24
33
|
if (parsedSessions.success) {
|
|
25
34
|
return parsedSessions.data;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/private/node/session/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAC,WAAW,EAAE,sBAAsB,EAAE,cAAc,EAAE,WAAW,EAAC,MAAM,kBAAkB,CAAA;AACjG,OAAO,EAAC,YAAY,EAAC,MAAM,sCAAsC,CAAA;AAGjE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,QAAkB;IAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IAC7C,WAAW,CAAC,YAAY,CAAC,CAAA;AAC3B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,OAAO,GAAG,WAAW,EAAE,CAAA;IAE7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAA;IAClB,CAAC;
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/private/node/session/store.ts"],"names":[],"mappings":"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","sourcesContent":["import {SessionsSchema} from './schema.js'\nimport {getSessions, removeCurrentSessionId, removeSessions, setSessions} from '../conf-store.js'\nimport {identityFqdn} from '../../../public/node/context/fqdn.js'\nimport type {Session, Sessions} from './schema.js'\n\n/**\n * Serializes the session as a JSON and stores it in the system.\n * @param session - the session to store.\n */\nexport async function store(sessions: Sessions) {\n const jsonSessions = JSON.stringify(sessions)\n setSessions(jsonSessions)\n}\n\n/**\n * Fetches the sessions from the local storage and returns it.\n * If the format of the object is invalid, the method will discard it.\n * @returns Returns a promise that resolves with the sessions object if it exists and is valid.\n */\nexport async function fetch(): Promise<Sessions | undefined> {\n const content = getSessions()\n\n if (!content) {\n return undefined\n }\n\n let contentJson: unknown\n try {\n contentJson = JSON.parse(content)\n } catch (error) {\n if (!(error instanceof SyntaxError)) throw error\n await remove()\n return undefined\n }\n\n const parsedSessions = await SessionsSchema.safeParseAsync(contentJson)\n if (parsedSessions.success) {\n return parsedSessions.data\n } else {\n await remove()\n return undefined\n }\n}\n\n/**\n * Removes a session from the system.\n */\nexport async function remove() {\n removeSessions()\n removeCurrentSessionId()\n}\n\n/**\n * Gets the session alias for a given user ID.\n *\n * @param userId - The user ID of the session to get the alias for.\n * @returns The alias for the session if it exists, otherwise undefined.\n */\nexport async function getSessionAlias(userId: string): Promise<string | undefined> {\n const sessions = await fetch()\n if (!sessions) return undefined\n\n const fqdn = await identityFqdn()\n if (!sessions[fqdn] || !sessions[fqdn][userId]) return undefined\n return sessions[fqdn][userId].identity.alias\n}\n\n/**\n * Sets the alias for a given user's session and persists it.\n *\n * @param userId - The user ID of the session to update.\n * @param alias - The new alias to set.\n */\nexport async function setSessionAlias(userId: string, alias: string): Promise<void> {\n const sessions = await fetch()\n if (!sessions) return\n\n const fqdn = await identityFqdn()\n const session: Session | undefined = sessions[fqdn]?.[userId]\n if (!session) return\n\n session.identity.alias = alias\n await store(sessions)\n}\n\n/**\n * Finds a session by its alias.\n *\n * @param alias - The alias to search for\n * @returns The user ID if found, otherwise undefined\n */\nexport async function findSessionByAlias(alias: string): Promise<string | undefined> {\n const sessions = await fetch()\n if (!sessions) return undefined\n\n const fqdn = await identityFqdn()\n const fqdnSessions = sessions[fqdn]\n if (!fqdnSessions) return undefined\n\n for (const [userId, session] of Object.entries(fqdnSessions)) {\n if (session.identity.alias === alias || userId === alias) {\n return userId\n }\n }\n\n return undefined\n}\n"]}
|
|
@@ -150,14 +150,14 @@ describe('Alert', async () => {
|
|
|
150
150
|
expect(line).not.toContain(longUrl);
|
|
151
151
|
});
|
|
152
152
|
// The footnote block (rendered after the closing `╰`) must list the
|
|
153
|
-
// URL
|
|
154
|
-
//
|
|
155
|
-
//
|
|
153
|
+
// URL as a single contiguous `[1] URL` line. The footnote Box is sized to
|
|
154
|
+
// the line length so Ink never hard-wraps the URL (which would insert
|
|
155
|
+
// newline characters and break copy-paste/clickability); the terminal
|
|
156
|
+
// soft-wraps the overflow at display time instead.
|
|
156
157
|
const closingBorderIndex = frame.indexOf('╰');
|
|
157
158
|
expect(closingBorderIndex).toBeGreaterThanOrEqual(0);
|
|
158
159
|
const afterBox = frame.slice(closingBorderIndex);
|
|
159
|
-
expect(afterBox).toContain(
|
|
160
|
-
expect(afterBox).toContain(longUrl);
|
|
160
|
+
expect(afterBox).toContain(`[1] ${longUrl}`);
|
|
161
161
|
// And the body must reference the footnote.
|
|
162
162
|
expect(frame).toContain('docs [1]');
|
|
163
163
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Alert.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Alert.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Alert} from './Alert.js'\nimport {unstyled} from '../../../../public/node/output.js'\nimport {render} from '../../testing/ui.js'\nimport {describe, expect, test} from 'vitest'\n\nimport React from 'react'\n\ndescribe('Alert', async () => {\n test('renders correctly with all the options', async () => {\n const options = {\n headline: [{userInput: 'my-app'}, 'initialized and ready to build.'],\n body: ['You can find the build files in the', {filePath: 'dist'}, 'folder.'],\n nextSteps: [\n [\n 'Run',\n {\n command: 'cd santorini-goods',\n },\n ],\n [\n 'To preview your project, run',\n {\n command: 'npm app dev',\n },\n ],\n [\n 'To add extensions, run',\n {\n command: 'npm generate extension',\n },\n ],\n ],\n reference: [\n [\n 'Run',\n {\n command: 'npm shopify help',\n },\n ],\n [\n // testing link wrapping behavior\n \"Press 'return' to open the really amazing and clean\",\n {\n link: {\n label: 'dev docs',\n url: 'https://shopify.dev',\n },\n },\n ],\n ],\n link: {\n label: 'Link',\n url: 'https://www.google.com',\n },\n customSections: [\n {\n title: 'Custom section',\n body: {\n list: {\n items: ['Item 1', 'Item 2', 'Item 3'],\n },\n },\n },\n {\n title: 'Custom section 2',\n body: {\n list: {\n items: ['Item 1', 'Item 2', 'Item 3'],\n },\n },\n },\n ],\n }\n\n const {lastFrame} = render(<Alert type=\"info\" {...options} />)\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"╭─ info ───────────────────────────────────────────────────────────────────────╮\n │ │\n │ my-app initialized and ready to build. │\n │ │\n │ You can find the build files in the dist folder. │\n │ │\n │ Next steps │\n │ • Run \\`cd santorini-goods\\` │\n │ • To preview your project, run \\`npm app dev\\` │\n │ • To add extensions, run \\`npm generate extension\\` │\n │ │\n │ Reference │\n │ • Run \\`npm shopify help\\` │\n │ • Press 'return' to open the really amazing and clean dev docs [1] │\n │ │\n │ Link [2] │\n │ │\n │ Custom section │\n │ • Item 1 │\n │ • Item 2 │\n │ • Item 3 │\n │ │\n │ Custom section 2 │\n │ • Item 1 │\n │ • Item 2 │\n │ • Item 3 │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n [1] https://shopify.dev\n [2] https://www.google.com\n \"\n `)\n })\n\n test('allows passing just a body', async () => {\n const options = {\n body: 'Title',\n }\n\n const {lastFrame} = render(<Alert type=\"info\" {...options} />)\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"╭─ info ───────────────────────────────────────────────────────────────────────╮\n │ │\n │ Title │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('has the headline in bold', async () => {\n const options = {\n headline: 'Title.',\n }\n\n const {lastFrame} = render(<Alert type=\"info\" {...options} />)\n\n expect(lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[2m╭─\u001b[22m info \u001b[2m───────────────────────────────────────────────────────────────────────╮\u001b[22m\n \u001b[2m│\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m│\u001b[22m \u001b[1mTitle.\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m│\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[22m\n \"\n `)\n })\n\n test(\"footnotes a long URL written as `[label](url)` in the body so it doesn't wrap inside the banner border\", async () => {\n // Regression: a 100-char URL embedded as plain text wraps across the\n // banner border at ~78 cols, splitting the URL with │ characters and\n // making it neither clickable nor copy-pasteable. Marking the URL up\n // with `[label](url)` should place the label inline (with a `[N]`\n // anchor) and emit the URL in the post-banner footnote block.\n const longUrl =\n 'https://shopify.dev/docs/apps/build/sales-channels/channel-config-extension#specification-properties'\n const options = {\n body: `See specification requirements: [docs](${longUrl})`,\n }\n\n const {lastFrame} = render(<Alert type=\"error\" {...options} />)\n const frame = unstyled(lastFrame()!)\n\n // The URL must not appear inside the bordered box.\n const bodyLines = frame.split('\\n').filter((line) => line.startsWith('│'))\n bodyLines.forEach((line) => {\n expect(line).not.toContain(longUrl)\n })\n\n // The footnote block (rendered after the closing `╰`) must list the\n // URL. Ink wraps the long URL onto its own line when it exceeds terminal\n // width, so we assert the `[1]` anchor and the URL show up *outside* the\n // bordered box rather than as a single contiguous `[1] URL` substring.\n const closingBorderIndex = frame.indexOf('╰')\n expect(closingBorderIndex).toBeGreaterThanOrEqual(0)\n const afterBox = frame.slice(closingBorderIndex)\n expect(afterBox).toContain('[1]')\n expect(afterBox).toContain(longUrl)\n // And the body must reference the footnote.\n expect(frame).toContain('docs [1]')\n })\n})\n"]}
|
|
1
|
+
{"version":3,"file":"Alert.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Alert.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Alert} from './Alert.js'\nimport {unstyled} from '../../../../public/node/output.js'\nimport {render} from '../../testing/ui.js'\nimport {describe, expect, test} from 'vitest'\n\nimport React from 'react'\n\ndescribe('Alert', async () => {\n test('renders correctly with all the options', async () => {\n const options = {\n headline: [{userInput: 'my-app'}, 'initialized and ready to build.'],\n body: ['You can find the build files in the', {filePath: 'dist'}, 'folder.'],\n nextSteps: [\n [\n 'Run',\n {\n command: 'cd santorini-goods',\n },\n ],\n [\n 'To preview your project, run',\n {\n command: 'npm app dev',\n },\n ],\n [\n 'To add extensions, run',\n {\n command: 'npm generate extension',\n },\n ],\n ],\n reference: [\n [\n 'Run',\n {\n command: 'npm shopify help',\n },\n ],\n [\n // testing link wrapping behavior\n \"Press 'return' to open the really amazing and clean\",\n {\n link: {\n label: 'dev docs',\n url: 'https://shopify.dev',\n },\n },\n ],\n ],\n link: {\n label: 'Link',\n url: 'https://www.google.com',\n },\n customSections: [\n {\n title: 'Custom section',\n body: {\n list: {\n items: ['Item 1', 'Item 2', 'Item 3'],\n },\n },\n },\n {\n title: 'Custom section 2',\n body: {\n list: {\n items: ['Item 1', 'Item 2', 'Item 3'],\n },\n },\n },\n ],\n }\n\n const {lastFrame} = render(<Alert type=\"info\" {...options} />)\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"╭─ info ───────────────────────────────────────────────────────────────────────╮\n │ │\n │ my-app initialized and ready to build. │\n │ │\n │ You can find the build files in the dist folder. │\n │ │\n │ Next steps │\n │ • Run \\`cd santorini-goods\\` │\n │ • To preview your project, run \\`npm app dev\\` │\n │ • To add extensions, run \\`npm generate extension\\` │\n │ │\n │ Reference │\n │ • Run \\`npm shopify help\\` │\n │ • Press 'return' to open the really amazing and clean dev docs [1] │\n │ │\n │ Link [2] │\n │ │\n │ Custom section │\n │ • Item 1 │\n │ • Item 2 │\n │ • Item 3 │\n │ │\n │ Custom section 2 │\n │ • Item 1 │\n │ • Item 2 │\n │ • Item 3 │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n [1] https://shopify.dev\n [2] https://www.google.com\n \"\n `)\n })\n\n test('allows passing just a body', async () => {\n const options = {\n body: 'Title',\n }\n\n const {lastFrame} = render(<Alert type=\"info\" {...options} />)\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"╭─ info ───────────────────────────────────────────────────────────────────────╮\n │ │\n │ Title │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('has the headline in bold', async () => {\n const options = {\n headline: 'Title.',\n }\n\n const {lastFrame} = render(<Alert type=\"info\" {...options} />)\n\n expect(lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[2m╭─\u001b[22m info \u001b[2m───────────────────────────────────────────────────────────────────────╮\u001b[22m\n \u001b[2m│\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m│\u001b[22m \u001b[1mTitle.\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m│\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[22m\n \"\n `)\n })\n\n test(\"footnotes a long URL written as `[label](url)` in the body so it doesn't wrap inside the banner border\", async () => {\n // Regression: a 100-char URL embedded as plain text wraps across the\n // banner border at ~78 cols, splitting the URL with │ characters and\n // making it neither clickable nor copy-pasteable. Marking the URL up\n // with `[label](url)` should place the label inline (with a `[N]`\n // anchor) and emit the URL in the post-banner footnote block.\n const longUrl =\n 'https://shopify.dev/docs/apps/build/sales-channels/channel-config-extension#specification-properties'\n const options = {\n body: `See specification requirements: [docs](${longUrl})`,\n }\n\n const {lastFrame} = render(<Alert type=\"error\" {...options} />)\n const frame = unstyled(lastFrame()!)\n\n // The URL must not appear inside the bordered box.\n const bodyLines = frame.split('\\n').filter((line) => line.startsWith('│'))\n bodyLines.forEach((line) => {\n expect(line).not.toContain(longUrl)\n })\n\n // The footnote block (rendered after the closing `╰`) must list the\n // URL as a single contiguous `[1] URL` line. The footnote Box is sized to\n // the line length so Ink never hard-wraps the URL (which would insert\n // newline characters and break copy-paste/clickability); the terminal\n // soft-wraps the overflow at display time instead.\n const closingBorderIndex = frame.indexOf('╰')\n expect(closingBorderIndex).toBeGreaterThanOrEqual(0)\n const afterBox = frame.slice(closingBorderIndex)\n expect(afterBox).toContain(`[1] ${longUrl}`)\n // And the body must reference the footnote.\n expect(frame).toContain('docs [1]')\n })\n})\n"]}
|
|
@@ -18,7 +18,15 @@ const Footnotes = () => {
|
|
|
18
18
|
}
|
|
19
19
|
const links = linksContext.links.current;
|
|
20
20
|
const linkIds = Object.keys(links);
|
|
21
|
-
return linkIds.length > 0 ? (React.createElement(Box, { marginBottom: 1, marginTop: -1, flexDirection: "column" }, linkIds.map((id) =>
|
|
21
|
+
return linkIds.length > 0 ? (React.createElement(Box, { marginBottom: 1, marginTop: -1, flexDirection: "column" }, linkIds.map((id) => {
|
|
22
|
+
const line = `[${id}] ${links[id]?.url}`;
|
|
23
|
+
// Render each footnote on a Box wide enough to fit the whole line so
|
|
24
|
+
// Ink doesn't hard-wrap long URLs (which inserts newline characters and
|
|
25
|
+
// breaks copy-paste/clickability). The terminal soft-wraps the overflow
|
|
26
|
+
// at display time without mutating the underlying text.
|
|
27
|
+
return (React.createElement(Box, { key: id, width: line.length },
|
|
28
|
+
React.createElement(Text, null, line)));
|
|
29
|
+
}))) : null;
|
|
22
30
|
};
|
|
23
31
|
const BoxWithBorder = ({ type, children }) => {
|
|
24
32
|
const { twoThirds } = useLayout();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Banner.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Banner.tsx"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,wBAAwB,CAAA;AAC9C,OAAO,EAAO,YAAY,EAAC,MAAM,6BAA6B,CAAA;AAC9D,OAAO,EAAC,GAAG,EAAE,IAAI,EAAC,MAAM,KAAK,CAAA;AAC7B,OAAO,KAAK,EAAE,EAAoB,UAAU,EAAE,MAAM,EAAC,MAAM,OAAO,CAAA;AASlE,SAAS,WAAW,CAAC,IAAyB;IAC5C,OAAO;QACL,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,QAAQ;QACjB,IAAI,EAAE,KAAK;QACX,cAAc,EAAE,KAAK;KACtB,CAAC,IAAI,CAAC,CAAA;AACT,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,YAAY,GAAG,UAAU,CAAC,YAAY,CAAC,CAAA;IAE7C,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,CAAC,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QACjE,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAA;IACxC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAElC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAC1B,oBAAC,GAAG,IAAC,YAAY,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,aAAa,EAAC,QAAQ,IACxD,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"Banner.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Banner.tsx"],"names":[],"mappings":"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","sourcesContent":["import useLayout from '../hooks/use-layout.js'\nimport {Link, LinksContext} from '../contexts/LinksContext.js'\nimport {Box, Text} from 'ink'\nimport React, {FunctionComponent, useContext, useRef} from 'react'\n\nexport type BannerType = 'success' | 'error' | 'warning' | 'info' | 'external_error'\n\ninterface BannerProps {\n type: BannerType\n children?: React.ReactNode\n}\n\nfunction typeToColor(type: BannerProps['type']) {\n return {\n success: 'green',\n error: 'red',\n warning: 'yellow',\n info: 'dim',\n external_error: 'red',\n }[type]\n}\n\nconst Footnotes = () => {\n const linksContext = useContext(LinksContext)\n\n if (linksContext === null || linksContext.links.current === null) {\n return null\n }\n\n const links = linksContext.links.current\n const linkIds = Object.keys(links)\n\n return linkIds.length > 0 ? (\n <Box marginBottom={1} marginTop={-1} flexDirection=\"column\">\n {linkIds.map((id) => {\n const line = `[${id}] ${links[id]?.url}`\n // Render each footnote on a Box wide enough to fit the whole line so\n // Ink doesn't hard-wrap long URLs (which inserts newline characters and\n // breaks copy-paste/clickability). The terminal soft-wraps the overflow\n // at display time without mutating the underlying text.\n return (\n <Box key={id} width={line.length}>\n <Text>{line}</Text>\n </Box>\n )\n })}\n </Box>\n ) : null\n}\n\nconst BoxWithBorder: FunctionComponent<BannerProps> = ({type, children}) => {\n const {twoThirds} = useLayout()\n const links = useRef<Record<string, Link>>({})\n\n return (\n <LinksContext.Provider\n value={{\n links,\n addLink: (label, url) => {\n const id: string | undefined = Object.keys(links.current).find((id) => links.current[id]!.url === url)\n if (id) {\n return id\n }\n const newId = (Object.keys(links.current).length + 1).toString()\n links.current = {\n ...links.current,\n [newId]: {label, url},\n }\n return newId\n },\n }}\n >\n <Box\n width={twoThirds}\n marginBottom={1}\n borderStyle=\"round\"\n flexDirection=\"column\"\n borderColor={typeToColor(type)}\n >\n <Box marginTop={-1} marginLeft={1}>\n <Text>{` ${type.replace(/_/g, ' ')} `}</Text>\n </Box>\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n {children}\n </Box>\n </Box>\n <Footnotes />\n </LinksContext.Provider>\n )\n}\n\nconst BoxWithTopBottomLines: FunctionComponent<BannerProps> = ({type, children}) => {\n const {twoThirds} = useLayout()\n // 2 initial dashes + 2 spaces surrounding the type\n let topLineAfterTypeLength = twoThirds - 2 - type.length - 2\n if (topLineAfterTypeLength < 0) topLineAfterTypeLength = 0\n\n return (\n <Box flexDirection=\"column\" marginBottom={1} gap={1}>\n <Text>\n <Text color={typeToColor(type)}>{'─'.repeat(2)}</Text>\n <Text>{` ${type.replace(/_/g, ' ')} `}</Text>\n <Text color={typeToColor(type)}>{'─'.repeat(topLineAfterTypeLength)}</Text>\n </Text>\n\n {children}\n\n <Text color={typeToColor(type)}>{'─'.repeat(twoThirds)}</Text>\n </Box>\n )\n}\n\nconst Banner: FunctionComponent<BannerProps> = ({children, ...props}) => {\n if (props.type === 'external_error') {\n return React.createElement(BoxWithTopBottomLines, props, children)\n } else {\n return React.createElement(BoxWithBorder, props, children)\n }\n}\n\nexport {Banner}\n"]}
|
|
@@ -42,10 +42,19 @@ export function extractHost(value) {
|
|
|
42
42
|
if (!value)
|
|
43
43
|
return undefined;
|
|
44
44
|
const lowered = value.toLowerCase();
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
// A bare `host:port` (e.g. `my-shop.shop.dev:9292`) parses as an opaque URL whose hostname is
|
|
46
|
+
// empty (the host is read as the scheme), so try parsing with an explicit scheme as well and only
|
|
47
|
+
// accept a non-empty hostname.
|
|
48
|
+
for (const candidate of [lowered, `https://${lowered}`]) {
|
|
49
|
+
const hostname = safeParseURL(candidate)?.hostname;
|
|
50
|
+
if (hostname)
|
|
51
|
+
return hostname;
|
|
52
|
+
}
|
|
53
|
+
// Never return an empty string: callers using `extractHost(value) ?? value` must keep the input.
|
|
54
|
+
const fallback = lowered.replace(/^https?:\/\//, '').split('/')[0];
|
|
55
|
+
if (fallback)
|
|
56
|
+
return fallback;
|
|
57
|
+
return undefined;
|
|
49
58
|
}
|
|
50
59
|
/**
|
|
51
60
|
* Extracts the subdomain handle from a `*.myshopify.com` URL or host.
|
|
@@ -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;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,
|
|
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,8FAA8F;IAC9F,kGAAkG;IAClG,+BAA+B;IAC/B,KAAK,MAAM,SAAS,IAAI,CAAC,OAAO,EAAE,WAAW,OAAO,EAAE,CAAC,EAAE,CAAC;QACxD,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAA;QAClD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAA;IAC/B,CAAC;IACD,iGAAiG;IACjG,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IAClE,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC7B,OAAO,SAAS,CAAA;AAClB,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 // A bare `host:port` (e.g. `my-shop.shop.dev:9292`) parses as an opaque URL whose hostname is\n // empty (the host is read as the scheme), so try parsing with an explicit scheme as well and only\n // accept a non-empty hostname.\n for (const candidate of [lowered, `https://${lowered}`]) {\n const hostname = safeParseURL(candidate)?.hostname\n if (hostname) return hostname\n }\n // Never return an empty string: callers using `extractHost(value) ?? value` must keep the input.\n const fallback = lowered.replace(/^https?:\\/\\//, '').split('/')[0]\n if (fallback) return fallback\n return undefined\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.4.0";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const CLI_KIT_VERSION = '4.
|
|
1
|
+
export const CLI_KIT_VERSION = '4.4.0';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '4.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '4.4.0'\n"]}
|
|
@@ -9,9 +9,10 @@ import { TypedDocumentNode } from '@graphql-typed-document-node/core';
|
|
|
9
9
|
* @param query - GraphQL query to execute.
|
|
10
10
|
* @param session - Shopify admin session including token and Store FQDN.
|
|
11
11
|
* @param variables - GraphQL variables to pass to the query.
|
|
12
|
+
* @param version - API version.
|
|
12
13
|
* @returns The response of the query of generic type <T>.
|
|
13
14
|
*/
|
|
14
|
-
export declare function adminRequest<T>(query: string, session: AdminSession, variables?: GraphQLVariables): Promise<T>;
|
|
15
|
+
export declare function adminRequest<T>(query: string, session: AdminSession, variables?: GraphQLVariables, version?: string): Promise<T>;
|
|
15
16
|
export interface AdminRequestOptions<TResult, TVariables extends Variables> {
|
|
16
17
|
/** GraphQL query to execute. */
|
|
17
18
|
query: TypedDocumentNode<TResult, TVariables>;
|
|
@@ -16,18 +16,19 @@ const LatestApiVersionByFQDN = new Map();
|
|
|
16
16
|
* @param query - GraphQL query to execute.
|
|
17
17
|
* @param session - Shopify admin session including token and Store FQDN.
|
|
18
18
|
* @param variables - GraphQL variables to pass to the query.
|
|
19
|
+
* @param version - API version.
|
|
19
20
|
* @returns The response of the query of generic type <T>.
|
|
20
21
|
*/
|
|
21
|
-
export async function adminRequest(query, session, variables) {
|
|
22
|
+
export async function adminRequest(query, session, variables, version) {
|
|
22
23
|
const api = 'Admin';
|
|
23
|
-
const
|
|
24
|
+
const apiVersion = version ?? (await fetchLatestSupportedApiVersion(session));
|
|
24
25
|
let storeDomain = session.storeFqdn;
|
|
25
26
|
const addedHeaders = themeAccessHeaders(session);
|
|
26
27
|
if (serviceEnvironment() === 'local') {
|
|
27
28
|
addedHeaders['x-forwarded-host'] = storeDomain;
|
|
28
29
|
storeDomain = new DevServerCore().host('app');
|
|
29
30
|
}
|
|
30
|
-
const url = adminUrl(storeDomain,
|
|
31
|
+
const url = adminUrl(storeDomain, apiVersion, session);
|
|
31
32
|
return graphqlRequest({ query, api, addedHeaders, url, token: session.token, variables });
|
|
32
33
|
}
|
|
33
34
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../../src/public/node/api/admin.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n graphqlRequest,\n graphqlRequestDoc,\n GraphQLResponseOptions,\n GraphQLVariables,\n UnauthorizedHandler,\n} from './graphql.js'\nimport {AdminSession} from '../session.js'\nimport {outputContent, outputToken} from '../output.js'\nimport {AbortError, BugError} from '../error.js'\nimport {\n restRequestBody,\n restRequestHeaders,\n restRequestUrl,\n isThemeAccessSession,\n} from '../../../private/node/api/rest.js'\nimport {isNetworkError} from '../../../private/node/api.js'\nimport {RequestModeInput, shopifyFetch} from '../http.js'\nimport {PublicApiVersions} from '../../../cli/api/graphql/admin/generated/public_api_versions.js'\nimport {themeKitAccessDomain} from '../../../private/node/constants.js'\nimport {serviceEnvironment} from '../../../private/node/context/service.js'\nimport {DevServerCore} from '../vendor/dev_server/index.js'\nimport {ClientError, Variables} from 'graphql-request'\n\nimport {TypedDocumentNode} from '@graphql-typed-document-node/core'\n\nconst LatestApiVersionByFQDN = new Map<string, string>()\n\n/**\n * Executes a GraphQL query against the Admin API.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @returns The response of the query of generic type <T>.\n */\nexport async function adminRequest<T>(query: string, session: AdminSession, variables?: GraphQLVariables): Promise<T> {\n const api = 'Admin'\n const version = await fetchLatestSupportedApiVersion(session)\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const url = adminUrl(storeDomain, version, session)\n return graphqlRequest({query, api, addedHeaders, url, token: session.token, variables})\n}\n\nexport interface AdminRequestOptions<TResult, TVariables extends Variables> {\n /** GraphQL query to execute. */\n query: TypedDocumentNode<TResult, TVariables>\n /** Shopify admin session including token and Store FQDN. */\n session: AdminSession\n /** GraphQL variables to pass to the query. */\n variables?: TVariables\n /** API version. */\n version?: string\n /** Control how API responses will be handled. */\n responseOptions?: GraphQLResponseOptions<TResult>\n /** Custom request behaviour for retries and timeouts. */\n preferredBehaviour?: RequestModeInput\n}\n\n/**\n * Executes a GraphQL query against the Admin API. Uses typed documents.\n *\n * @param options - Admin request options.\n * @returns The response of the query of generic type <TResult>.\n */\nexport async function adminRequestDoc<TResult, TVariables extends Variables>(\n options: AdminRequestOptions<TResult, TVariables>,\n): Promise<TResult> {\n const {query, session, variables, version, responseOptions, preferredBehaviour} = options\n\n let apiVersion = version ?? LatestApiVersionByFQDN.get(session.storeFqdn)\n apiVersion ??= await fetchLatestSupportedApiVersion(session, preferredBehaviour)\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const opts = {\n url: adminUrl(storeDomain, apiVersion, session),\n api: 'Admin',\n token: session.token,\n addedHeaders,\n }\n let unauthorizedHandler: UnauthorizedHandler | undefined\n if ('refresh' in session) {\n unauthorizedHandler = {type: 'token_refresh', handler: session.refresh as () => Promise<{token: string}>}\n }\n const result = graphqlRequestDoc<TResult, TVariables>({\n ...opts,\n query,\n variables,\n responseOptions,\n unauthorizedHandler,\n preferredBehaviour,\n })\n return result\n}\n\nfunction themeAccessHeaders(session: AdminSession): Record<string, string> {\n return isThemeAccessSession(session)\n ? {'X-Shopify-Shop': session.storeFqdn, 'X-Shopify-Access-Token': session.token}\n : {}\n}\n\n/**\n * GraphQL query to retrieve the latest supported API version.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - The latest supported API version.\n */\nasync function fetchLatestSupportedApiVersion(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string> {\n const apiVersions = await supportedApiVersions(session, preferredBehaviour)\n\n const latest = apiVersions.reverse()[0]!\n LatestApiVersionByFQDN.set(session.storeFqdn, latest)\n return latest\n}\n\n/**\n * GraphQL query to retrieve all supported API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported API versions.\n */\nexport async function supportedApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string[]> {\n const apiVersions = await fetchApiVersions(session, preferredBehaviour)\n return apiVersions\n .filter((item) => item.supported)\n .map((item) => item.handle)\n .sort()\n}\n\n/**\n * GraphQL query to retrieve all API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported and unsupported API versions.\n */\nexport async function fetchApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<ApiVersion[]> {\n try {\n const response = await adminRequestDoc({\n query: PublicApiVersions,\n session,\n variables: {},\n version: 'unstable',\n responseOptions: {handleErrors: false},\n preferredBehaviour,\n })\n return response.publicApiVersions\n } catch (error) {\n if (error instanceof ClientError && error.response.status === 403) {\n const storeName = session.storeFqdn.replace('.myshopify.com', '')\n throw new AbortError(\n outputContent`Looks like you don't have access to this dev store: (${outputToken.link(\n storeName,\n `https://${session.storeFqdn}`,\n )})`,\n outputContent`If you're not the owner, create a dev store staff account for yourself`,\n )\n }\n if (error instanceof ClientError && (error.response.status === 401 || error.response.status === 404)) {\n throw new AbortError(\n `Error connecting to your store ${session.storeFqdn}: ${error.message} ${error.response.status} ${error.response.data}`,\n )\n }\n\n // Check for network-level errors (connection issues, timeouts, DNS failures, TLS/certificate errors, etc.)\n // All network errors should be treated as user-facing errors, not CLI bugs\n // Note: Some of these may have been retried already by lower-level retry logic\n if (isNetworkError(error)) {\n throw new AbortError(\n `Network error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'Check your internet connection and try again.',\n )\n }\n\n // Unknown errors are likely bugs in the CLI\n throw new BugError(\n `Unknown error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n}\n\n/**\n * Returns the Admin API URL for the given store and version.\n *\n * @param store - Store FQDN.\n * @param version - API version.\n * @param session - User session.\n * @returns - Admin API URL.\n */\nexport function adminUrl(store: string, version: string | undefined, session?: AdminSession): string {\n const realVersion = version ?? 'unstable'\n\n const url =\n session && isThemeAccessSession(session)\n ? `https://${themeKitAccessDomain}/cli/admin/api/${realVersion}/graphql.json`\n : `https://${store}/admin/api/${realVersion}/graphql.json`\n return url\n}\n\ninterface ApiVersion {\n handle: string\n supported: boolean\n}\n\n/**\n * Executes a REST request against the Admin API.\n *\n * @param method - Request's HTTP method.\n * @param path - Path of the REST resource.\n * @param session - Shopify Admin session including token and Store FQDN.\n * @param requestBody - Request body of including REST resource specific parameters.\n * @param searchParams - Search params, appended to the URL.\n * @param apiVersion - Admin API version.\n * @returns - The {@link RestResponse}.\n */\nexport async function restRequest<T>(\n method: string,\n path: string,\n session: AdminSession,\n requestBody?: T,\n searchParams: Record<string, string> = {},\n apiVersion = 'unstable',\n): Promise<RestResponse> {\n const url = restRequestUrl(session, apiVersion, path, searchParams)\n const body = restRequestBody<T>(requestBody)\n\n const headers = restRequestHeaders(session)\n const response = await shopifyFetch(url, {\n headers,\n method,\n body,\n })\n\n const json = await response.json().catch(() => ({}))\n\n return {\n json,\n status: response.status,\n headers: response.headers.raw(),\n }\n}\n\n/**\n * Respose of a REST request.\n */\nexport interface RestResponse {\n /**\n * REST JSON respose.\n */\n // Using `any` to avoid introducing extra DTO layers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: any\n\n /**\n * HTTP response status.\n */\n status: number\n\n /**\n * HTTP response headers.\n */\n headers: Record<string, string[]>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../../src/public/node/api/admin.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n graphqlRequest,\n graphqlRequestDoc,\n GraphQLResponseOptions,\n GraphQLVariables,\n UnauthorizedHandler,\n} from './graphql.js'\nimport {AdminSession} from '../session.js'\nimport {outputContent, outputToken} from '../output.js'\nimport {AbortError, BugError} from '../error.js'\nimport {\n restRequestBody,\n restRequestHeaders,\n restRequestUrl,\n isThemeAccessSession,\n} from '../../../private/node/api/rest.js'\nimport {isNetworkError} from '../../../private/node/api.js'\nimport {RequestModeInput, shopifyFetch} from '../http.js'\nimport {PublicApiVersions} from '../../../cli/api/graphql/admin/generated/public_api_versions.js'\nimport {themeKitAccessDomain} from '../../../private/node/constants.js'\nimport {serviceEnvironment} from '../../../private/node/context/service.js'\nimport {DevServerCore} from '../vendor/dev_server/index.js'\nimport {ClientError, Variables} from 'graphql-request'\n\nimport {TypedDocumentNode} from '@graphql-typed-document-node/core'\n\nconst LatestApiVersionByFQDN = new Map<string, string>()\n\n/**\n * Executes a GraphQL query against the Admin API.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @param version - API version.\n * @returns The response of the query of generic type <T>.\n */\nexport async function adminRequest<T>(\n query: string,\n session: AdminSession,\n variables?: GraphQLVariables,\n version?: string,\n): Promise<T> {\n const api = 'Admin'\n const apiVersion = version ?? (await fetchLatestSupportedApiVersion(session))\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const url = adminUrl(storeDomain, apiVersion, session)\n return graphqlRequest({query, api, addedHeaders, url, token: session.token, variables})\n}\n\nexport interface AdminRequestOptions<TResult, TVariables extends Variables> {\n /** GraphQL query to execute. */\n query: TypedDocumentNode<TResult, TVariables>\n /** Shopify admin session including token and Store FQDN. */\n session: AdminSession\n /** GraphQL variables to pass to the query. */\n variables?: TVariables\n /** API version. */\n version?: string\n /** Control how API responses will be handled. */\n responseOptions?: GraphQLResponseOptions<TResult>\n /** Custom request behaviour for retries and timeouts. */\n preferredBehaviour?: RequestModeInput\n}\n\n/**\n * Executes a GraphQL query against the Admin API. Uses typed documents.\n *\n * @param options - Admin request options.\n * @returns The response of the query of generic type <TResult>.\n */\nexport async function adminRequestDoc<TResult, TVariables extends Variables>(\n options: AdminRequestOptions<TResult, TVariables>,\n): Promise<TResult> {\n const {query, session, variables, version, responseOptions, preferredBehaviour} = options\n\n let apiVersion = version ?? LatestApiVersionByFQDN.get(session.storeFqdn)\n apiVersion ??= await fetchLatestSupportedApiVersion(session, preferredBehaviour)\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const opts = {\n url: adminUrl(storeDomain, apiVersion, session),\n api: 'Admin',\n token: session.token,\n addedHeaders,\n }\n let unauthorizedHandler: UnauthorizedHandler | undefined\n if ('refresh' in session) {\n unauthorizedHandler = {type: 'token_refresh', handler: session.refresh as () => Promise<{token: string}>}\n }\n const result = graphqlRequestDoc<TResult, TVariables>({\n ...opts,\n query,\n variables,\n responseOptions,\n unauthorizedHandler,\n preferredBehaviour,\n })\n return result\n}\n\nfunction themeAccessHeaders(session: AdminSession): Record<string, string> {\n return isThemeAccessSession(session)\n ? {'X-Shopify-Shop': session.storeFqdn, 'X-Shopify-Access-Token': session.token}\n : {}\n}\n\n/**\n * GraphQL query to retrieve the latest supported API version.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - The latest supported API version.\n */\nasync function fetchLatestSupportedApiVersion(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string> {\n const apiVersions = await supportedApiVersions(session, preferredBehaviour)\n\n const latest = apiVersions.reverse()[0]!\n LatestApiVersionByFQDN.set(session.storeFqdn, latest)\n return latest\n}\n\n/**\n * GraphQL query to retrieve all supported API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported API versions.\n */\nexport async function supportedApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string[]> {\n const apiVersions = await fetchApiVersions(session, preferredBehaviour)\n return apiVersions\n .filter((item) => item.supported)\n .map((item) => item.handle)\n .sort()\n}\n\n/**\n * GraphQL query to retrieve all API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported and unsupported API versions.\n */\nexport async function fetchApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<ApiVersion[]> {\n try {\n const response = await adminRequestDoc({\n query: PublicApiVersions,\n session,\n variables: {},\n version: 'unstable',\n responseOptions: {handleErrors: false},\n preferredBehaviour,\n })\n return response.publicApiVersions\n } catch (error) {\n if (error instanceof ClientError && error.response.status === 403) {\n const storeName = session.storeFqdn.replace('.myshopify.com', '')\n throw new AbortError(\n outputContent`Looks like you don't have access to this dev store: (${outputToken.link(\n storeName,\n `https://${session.storeFqdn}`,\n )})`,\n outputContent`If you're not the owner, create a dev store staff account for yourself`,\n )\n }\n if (error instanceof ClientError && (error.response.status === 401 || error.response.status === 404)) {\n throw new AbortError(\n `Error connecting to your store ${session.storeFqdn}: ${error.message} ${error.response.status} ${error.response.data}`,\n )\n }\n\n // Check for network-level errors (connection issues, timeouts, DNS failures, TLS/certificate errors, etc.)\n // All network errors should be treated as user-facing errors, not CLI bugs\n // Note: Some of these may have been retried already by lower-level retry logic\n if (isNetworkError(error)) {\n throw new AbortError(\n `Network error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'Check your internet connection and try again.',\n )\n }\n\n // Unknown errors are likely bugs in the CLI\n throw new BugError(\n `Unknown error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n}\n\n/**\n * Returns the Admin API URL for the given store and version.\n *\n * @param store - Store FQDN.\n * @param version - API version.\n * @param session - User session.\n * @returns - Admin API URL.\n */\nexport function adminUrl(store: string, version: string | undefined, session?: AdminSession): string {\n const realVersion = version ?? 'unstable'\n\n const url =\n session && isThemeAccessSession(session)\n ? `https://${themeKitAccessDomain}/cli/admin/api/${realVersion}/graphql.json`\n : `https://${store}/admin/api/${realVersion}/graphql.json`\n return url\n}\n\ninterface ApiVersion {\n handle: string\n supported: boolean\n}\n\n/**\n * Executes a REST request against the Admin API.\n *\n * @param method - Request's HTTP method.\n * @param path - Path of the REST resource.\n * @param session - Shopify Admin session including token and Store FQDN.\n * @param requestBody - Request body of including REST resource specific parameters.\n * @param searchParams - Search params, appended to the URL.\n * @param apiVersion - Admin API version.\n * @returns - The {@link RestResponse}.\n */\nexport async function restRequest<T>(\n method: string,\n path: string,\n session: AdminSession,\n requestBody?: T,\n searchParams: Record<string, string> = {},\n apiVersion = 'unstable',\n): Promise<RestResponse> {\n const url = restRequestUrl(session, apiVersion, path, searchParams)\n const body = restRequestBody<T>(requestBody)\n\n const headers = restRequestHeaders(session)\n const response = await shopifyFetch(url, {\n headers,\n method,\n body,\n })\n\n const json = await response.json().catch(() => ({}))\n\n return {\n json,\n status: response.status,\n headers: response.headers.raw(),\n }\n}\n\n/**\n * Respose of a REST request.\n */\nexport interface RestResponse {\n /**\n * REST JSON respose.\n */\n // Using `any` to avoid introducing extra DTO layers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: any\n\n /**\n * HTTP response status.\n */\n status: number\n\n /**\n * HTTP response headers.\n */\n headers: Record<string, string[]>\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AdminSession } from '../../session.js';
|
|
2
|
+
import { BulkOperationCancelMutation } from '../../../../cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.js';
|
|
3
|
+
interface CancelBulkOperationOptions {
|
|
4
|
+
adminSession: AdminSession;
|
|
5
|
+
operationId: string;
|
|
6
|
+
version?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Requests cancellation of a bulk operation.
|
|
10
|
+
*
|
|
11
|
+
* @param options - The admin session, operation ID, and optional API version.
|
|
12
|
+
* @returns The bulkOperationCancel result, including any user errors.
|
|
13
|
+
*/
|
|
14
|
+
export declare function cancelBulkOperationRequest(options: CancelBulkOperationOptions): Promise<BulkOperationCancelMutation['bulkOperationCancel']>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BULK_OPERATIONS_MIN_API_VERSION } from './constants.js';
|
|
2
|
+
import { adminRequestDoc } from '../admin.js';
|
|
3
|
+
import { BulkOperationCancel, } from '../../../../cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.js';
|
|
4
|
+
/**
|
|
5
|
+
* Requests cancellation of a bulk operation.
|
|
6
|
+
*
|
|
7
|
+
* @param options - The admin session, operation ID, and optional API version.
|
|
8
|
+
* @returns The bulkOperationCancel result, including any user errors.
|
|
9
|
+
*/
|
|
10
|
+
export async function cancelBulkOperationRequest(options) {
|
|
11
|
+
const { adminSession, operationId, version } = options;
|
|
12
|
+
const response = await adminRequestDoc({
|
|
13
|
+
query: BulkOperationCancel,
|
|
14
|
+
session: adminSession,
|
|
15
|
+
variables: { id: operationId },
|
|
16
|
+
version: version ?? BULK_OPERATIONS_MIN_API_VERSION,
|
|
17
|
+
});
|
|
18
|
+
return response.bulkOperationCancel;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=cancel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancel.js","sourceRoot":"","sources":["../../../../../src/public/node/api/bulk-operations/cancel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,+BAA+B,EAAC,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAE3C,OAAO,EACL,mBAAmB,GAGpB,MAAM,gFAAgF,CAAA;AAQvF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,OAAmC;IAEnC,MAAM,EAAC,YAAY,EAAE,WAAW,EAAE,OAAO,EAAC,GAAG,OAAO,CAAA;IAEpD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAoE;QACxG,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,YAAY;QACrB,SAAS,EAAE,EAAC,EAAE,EAAE,WAAW,EAAC;QAC5B,OAAO,EAAE,OAAO,IAAI,+BAA+B;KACpD,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,mBAAmB,CAAA;AACrC,CAAC","sourcesContent":["import {BULK_OPERATIONS_MIN_API_VERSION} from './constants.js'\nimport {adminRequestDoc} from '../admin.js'\nimport {AdminSession} from '../../session.js'\nimport {\n BulkOperationCancel,\n BulkOperationCancelMutation,\n BulkOperationCancelMutationVariables,\n} from '../../../../cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.js'\n\ninterface CancelBulkOperationOptions {\n adminSession: AdminSession\n operationId: string\n version?: string\n}\n\n/**\n * Requests cancellation of a bulk operation.\n *\n * @param options - The admin session, operation ID, and optional API version.\n * @returns The bulkOperationCancel result, including any user errors.\n */\nexport async function cancelBulkOperationRequest(\n options: CancelBulkOperationOptions,\n): Promise<BulkOperationCancelMutation['bulkOperationCancel']> {\n const {adminSession, operationId, version} = options\n\n const response = await adminRequestDoc<BulkOperationCancelMutation, BulkOperationCancelMutationVariables>({\n query: BulkOperationCancel,\n session: adminSession,\n variables: {id: operationId},\n version: version ?? BULK_OPERATIONS_MIN_API_VERSION,\n })\n\n return response.bulkOperationCancel\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../src/public/node/api/bulk-operations/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,SAAS,CAAA","sourcesContent":["/**\n * Minimum API version for bulk operations.\n * This ensures bulk operation features work correctly across all operations.\n */\nexport const BULK_OPERATIONS_MIN_API_VERSION = '2026-01'\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Downloads the results of a completed bulk operation.
|
|
3
|
+
*
|
|
4
|
+
* @param url - The results URL returned by the Admin API.
|
|
5
|
+
* @returns The raw JSONL results as a string.
|
|
6
|
+
*/
|
|
7
|
+
export declare function downloadBulkOperationResults(url: string): Promise<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Checks whether any line of a JSONL bulk operation result reports GraphQL user errors.
|
|
10
|
+
*
|
|
11
|
+
* Blank result files, such as a completed operation that matched nothing, are treated as having
|
|
12
|
+
* no user errors instead of crashing the JSON parser.
|
|
13
|
+
*
|
|
14
|
+
* @param results - The raw JSONL results string.
|
|
15
|
+
* @returns True if any result line reports user errors.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resultsContainUserErrors(results: string): boolean;
|