@shopify/cli 3.63.2 → 3.64.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/assets/cli-ruby/lib/shopify_cli/reporting_configuration_controller.rb +2 -37
  2. package/dist/assets/cli-ruby/lib/shopify_cli/theme/file.rb +5 -1
  3. package/dist/assets/dev-console/extensions/dev-console/assets/index-Cgb-oKsM.css +1 -0
  4. package/dist/assets/dev-console/extensions/dev-console/assets/{index-Dui3DO9f.js → index-D7F9wNys.js} +12 -12
  5. package/dist/assets/dev-console/index.html +2 -2
  6. package/dist/assets/hydrogen/starter/.graphqlrc.ts +27 -0
  7. package/dist/assets/hydrogen/starter/CHANGELOG.md +108 -6
  8. package/dist/assets/hydrogen/starter/app/components/AddToCartButton.tsx +37 -0
  9. package/dist/assets/hydrogen/starter/app/components/CartLineItem.tsx +150 -0
  10. package/dist/assets/hydrogen/starter/app/components/CartMain.tsx +68 -0
  11. package/dist/assets/hydrogen/starter/app/components/CartSummary.tsx +101 -0
  12. package/dist/assets/hydrogen/starter/app/components/Header.tsx +3 -3
  13. package/dist/assets/hydrogen/starter/app/components/PageLayout.tsx +2 -2
  14. package/dist/assets/hydrogen/starter/app/components/ProductForm.tsx +80 -0
  15. package/dist/assets/hydrogen/starter/app/components/ProductImage.tsx +23 -0
  16. package/dist/assets/hydrogen/starter/app/components/ProductPrice.tsx +27 -0
  17. package/dist/assets/hydrogen/starter/app/root.tsx +11 -17
  18. package/dist/assets/hydrogen/starter/app/routes/cart.tsx +1 -1
  19. package/dist/assets/hydrogen/starter/app/routes/products.$handle.tsx +51 -232
  20. package/dist/assets/hydrogen/starter/package.json +11 -11
  21. package/dist/assets/hydrogen/tailwind/package.json +1 -6
  22. package/dist/assets/hydrogen/tailwind/tailwind.css +6 -3
  23. package/dist/assets/hydrogen/vanilla-extract/package.json +2 -3
  24. package/dist/assets/hydrogen/virtual-routes/components/{Layout.jsx → PageLayout.jsx} +2 -2
  25. package/dist/assets/hydrogen/virtual-routes/virtual-root.jsx +8 -30
  26. package/dist/{chunk-YAYFJITA.js → chunk-2DXCIFDK.js} +3 -3
  27. package/dist/{chunk-EQR6CWKL.js → chunk-63D4EGTO.js} +3 -3
  28. package/dist/{chunk-EZYMDZPN.js → chunk-6PJAGL2L.js} +5 -5
  29. package/dist/{chunk-S4VBXFXP.js → chunk-7PVTYKQI.js} +220 -16
  30. package/dist/{chunk-IRWSC76I.js → chunk-7TIDA343.js} +3 -3
  31. package/dist/{chunk-NPLAQVTF.js → chunk-7W6SRTYP.js} +3 -3
  32. package/dist/{chunk-UJYIV6JP.js → chunk-ARCFCLME.js} +5 -5
  33. package/dist/{chunk-DIZHFZTJ.js → chunk-ATGUMSCJ.js} +4 -4
  34. package/dist/chunk-B3D5VLUA.js +12 -0
  35. package/dist/{chunk-UNPXLODI.js → chunk-B7RN7IRD.js} +3 -4
  36. package/dist/{chunk-5BLMIE7F.js → chunk-DX43V2L4.js} +4 -4
  37. package/dist/{chunk-6UDFXWNE.js → chunk-EJITPGUJ.js} +21 -4
  38. package/dist/chunk-FDLU3RD4.js +29 -0
  39. package/dist/{chunk-7OCUVNSF.js → chunk-H6AQTECB.js} +1485 -2977
  40. package/dist/{chunk-T54B5GJP.js → chunk-JNUJZFQL.js} +2 -2
  41. package/dist/{chunk-XER2L725.js → chunk-KUVX423E.js} +2 -2
  42. package/dist/{chunk-R5KML52V.js → chunk-KZTALMEV.js} +4 -4
  43. package/dist/{chunk-CM4H6QMH.js → chunk-M6KGRVDD.js} +3 -3
  44. package/dist/{chunk-3MDI6LZT.js → chunk-NLE3ZLU6.js} +905 -896
  45. package/dist/{chunk-WADS2TV5.js → chunk-NO7MYZEO.js} +5 -4
  46. package/dist/{chunk-LH533WG4.js → chunk-NPH2SXRO.js} +2 -2
  47. package/dist/{chunk-VZUWS5IH.js → chunk-OVWFZSJT.js} +3 -3
  48. package/dist/{chunk-UQUO22Q5.js → chunk-OXMHVKM3.js} +5 -5
  49. package/dist/{chunk-PNFEODLY.js → chunk-QNI6VLVR.js} +3 -3
  50. package/dist/{chunk-MCT2524Y.js → chunk-QYT42J3T.js} +4 -4
  51. package/dist/{chunk-VQTHQBEC.js → chunk-S3HWVIGJ.js} +9 -14
  52. package/dist/{chunk-23OKKZ5V.js → chunk-S7A7BHNA.js} +4 -4
  53. package/dist/{chunk-3TGMDPDI.js → chunk-SSAUIEBT.js} +2 -2
  54. package/dist/{chunk-YMPGWFWU.js → chunk-UQQI7TQG.js} +3 -3
  55. package/dist/{chunk-UZUD5DRI.js → chunk-UXA5YROL.js} +2 -2
  56. package/dist/{chunk-K3CVGV3F.js → chunk-V7NH4SZB.js} +3 -3
  57. package/dist/{chunk-7AVKIH7O.js → chunk-WVY52EEZ.js} +5 -5
  58. package/dist/{chunk-QEOBHRRQ.js → chunk-X3OUSYUQ.js} +17912 -17444
  59. package/dist/{chunk-EARPFFS7.js → chunk-XNCQBHNR.js} +241 -4
  60. package/dist/{chunk-EQPYUHNM.js → chunk-ZIGJPI5N.js} +1497 -112
  61. package/dist/{chunk-A2UVOX6O.js → chunk-ZKWHKX2C.js} +7066 -6051
  62. package/dist/{chunk-GPMHDCWK.js → chunk-ZRGD2HUL.js} +3 -3
  63. package/dist/{chunk-PQKGBYDC.js → chunk-ZVT2WZZF.js} +3 -3
  64. package/dist/cli/commands/auth/logout.js +14 -19
  65. package/dist/cli/commands/auth/logout.test.js +17 -21
  66. package/dist/cli/commands/debug/command-flags.js +11 -15
  67. package/dist/cli/commands/demo/catalog.js +13 -18
  68. package/dist/cli/commands/demo/generate-file.js +13 -18
  69. package/dist/cli/commands/demo/index.js +13 -18
  70. package/dist/cli/commands/demo/print-ai-prompt.js +13 -18
  71. package/dist/cli/commands/docs/generate.js +11 -15
  72. package/dist/cli/commands/docs/generate.test.js +11 -15
  73. package/dist/cli/commands/help.js +11 -15
  74. package/dist/cli/commands/kitchen-sink/async.js +12 -16
  75. package/dist/cli/commands/kitchen-sink/async.test.js +12 -16
  76. package/dist/cli/commands/kitchen-sink/index.js +14 -18
  77. package/dist/cli/commands/kitchen-sink/index.test.js +14 -18
  78. package/dist/cli/commands/kitchen-sink/prompts.js +12 -16
  79. package/dist/cli/commands/kitchen-sink/prompts.test.js +12 -16
  80. package/dist/cli/commands/kitchen-sink/static.js +12 -16
  81. package/dist/cli/commands/kitchen-sink/static.test.js +12 -16
  82. package/dist/cli/commands/search.js +12 -16
  83. package/dist/cli/commands/upgrade.js +11 -15
  84. package/dist/cli/commands/version.js +12 -16
  85. package/dist/cli/commands/version.test.js +12 -16
  86. package/dist/cli/services/commands/search.js +4 -4
  87. package/dist/cli/services/commands/search.test.js +4 -4
  88. package/dist/cli/services/commands/version.js +6 -7
  89. package/dist/cli/services/commands/version.test.js +7 -8
  90. package/dist/cli/services/demo.js +5 -6
  91. package/dist/cli/services/demo.test.js +5 -6
  92. package/dist/cli/services/kitchen-sink/async.js +4 -4
  93. package/dist/cli/services/kitchen-sink/prompts.js +4 -4
  94. package/dist/cli/services/kitchen-sink/static.js +4 -4
  95. package/dist/cli/services/upgrade.js +5 -6
  96. package/dist/cli/services/upgrade.test.js +7 -8
  97. package/dist/{constants-3CLHB4LQ.js → constants-EVER32LA.js} +3 -3
  98. package/dist/{custom-oclif-loader-D4H5EJW6.js → custom-oclif-loader-BQAFOUNG.js} +13 -6
  99. package/dist/{error-handler-HUI4HW3X.js → error-handler-S56KHSGD.js} +10 -8
  100. package/dist/hooks/postrun.js +12 -14
  101. package/dist/hooks/prerun.js +8 -11
  102. package/dist/index.js +7811 -7490
  103. package/dist/{local-7IRDZWLW.js → local-UQAQKOVL.js} +4 -4
  104. package/dist/{morph-6NYGHGNT.js → morph-DN4AZJZW.js} +9 -9
  105. package/dist/{node-UIH7JP3D.js → node-GZYZUMBW.js} +21 -19
  106. package/dist/{node-package-manager-2LWT2MNN.js → node-package-manager-AOVZD6TP.js} +5 -6
  107. package/dist/{path-JVVXOELJ.js → path-KUSF6CYC.js} +2 -2
  108. package/dist/{system-4HHX42JS.js → system-G7DVECOP.js} +4 -4
  109. package/dist/templates/ui-extensions/projects/web_pixel_extension/package.json.liquid +1 -1
  110. package/dist/tsconfig.tsbuildinfo +1 -1
  111. package/dist/{ui-NFBKMC4P.js → ui-2AOZFYFM.js} +4 -4
  112. package/dist/{workerd-4HFD3PS4.js → workerd-2MO23YDQ.js} +22 -19
  113. package/oclif.manifest.json +265 -4
  114. package/package.json +7 -10
  115. package/dist/assets/dev-console/extensions/dev-console/assets/index-Bi7y6lI5.css +0 -1
  116. package/dist/assets/hydrogen/css-modules/package.json +0 -6
  117. package/dist/assets/hydrogen/postcss/package.json +0 -10
  118. package/dist/assets/hydrogen/postcss/postcss.config.js +0 -8
  119. package/dist/assets/hydrogen/starter/.graphqlrc.yml +0 -12
  120. package/dist/assets/hydrogen/starter/app/components/Cart.tsx +0 -364
  121. package/dist/assets/hydrogen/tailwind/postcss.config.js +0 -10
  122. package/dist/assets/hydrogen/tailwind/tailwind.config.js +0 -8
  123. package/dist/chunk-4WBV3WP3.js +0 -221
  124. package/dist/chunk-OWICSMFV.js +0 -12
  125. package/dist/chunk-QCDYZY46.js +0 -1070
  126. package/dist/chunk-QEKTVN5A.js +0 -4385
  127. package/dist/chunk-QOUOFEGO.js +0 -35
  128. package/dist/chunk-WP234IUO.js +0 -265
  129. package/dist/chunk-XLPMGRR3.js +0 -496
  130. package/dist/chunk-XSKJYEAZ.js +0 -1453
  131. package/dist/error-handler-QDDLQDOJ.js +0 -43
@@ -1,1453 +0,0 @@
1
- import {
2
- checkPort,
3
- require_find_process,
4
- require_lib
5
- } from "./chunk-EQPYUHNM.js";
6
- import {
7
- setNextDeprecationDate
8
- } from "./chunk-LH533WG4.js";
9
- import {
10
- z
11
- } from "./chunk-6UDFXWNE.js";
12
- import {
13
- base_command_default
14
- } from "./chunk-WP234IUO.js";
15
- import {
16
- GraphQLClientError,
17
- RequestClientError,
18
- allAPIs,
19
- buildHeaders,
20
- debugLogResponseInfo,
21
- getIdentityTokenInformation,
22
- getPartnersToken,
23
- httpsAgent,
24
- sanitizedHeadersOutput,
25
- shopifyFetch
26
- } from "./chunk-QCDYZY46.js";
27
- import {
28
- ClientError,
29
- GraphQLClient,
30
- gql,
31
- resolveRequestDocument
32
- } from "./chunk-A2UVOX6O.js";
33
- import {
34
- base64URLEncode,
35
- randomBytes,
36
- randomHex,
37
- sha256
38
- } from "./chunk-VQTHQBEC.js";
39
- import {
40
- cacheRetrieveOrRepopulate,
41
- getSession,
42
- removeSession,
43
- setSession
44
- } from "./chunk-XLPMGRR3.js";
45
- import {
46
- AbortError,
47
- BugError,
48
- CancelExecution,
49
- FatalError,
50
- findPathUp,
51
- firstPartyDev,
52
- import_ts_error,
53
- isSpin,
54
- isSpinEnvironment,
55
- isTruthy,
56
- keypress,
57
- openURL,
58
- outputCompleted,
59
- outputContent,
60
- outputDebug,
61
- outputInfo,
62
- outputSuccess,
63
- outputToken,
64
- outputWarn,
65
- readFile,
66
- renderConfirmationPrompt,
67
- runWithTimer,
68
- serviceEnvironment,
69
- spinFqdn,
70
- stringifyMessage,
71
- useDeviceAuth
72
- } from "./chunk-3MDI6LZT.js";
73
- import {
74
- sessionConstants
75
- } from "./chunk-WADS2TV5.js";
76
- import {
77
- moduleDirectory
78
- } from "./chunk-UNPXLODI.js";
79
- import {
80
- __toESM,
81
- init_cjs_shims
82
- } from "./chunk-ZPL24Y2D.js";
83
-
84
- // src/cli/commands/auth/logout.ts
85
- init_cjs_shims();
86
-
87
- // ../cli-kit/src/public/node/session.ts
88
- init_cjs_shims();
89
-
90
- // ../cli-kit/src/public/node/context/fqdn.ts
91
- init_cjs_shims();
92
- var CouldntObtainPartnersSpinFQDNError = new AbortError(
93
- "Couldn't obtain the Spin FQDN for Partners when the CLI is not running from a Spin environment."
94
- );
95
- var CouldntObtainIdentitySpinFQDNError = new AbortError(
96
- "Couldn't obtain the Spin FQDN for Identity when the CLI is not running from a Spin environment."
97
- );
98
- var CouldntObtainShopifySpinFQDNError = new AbortError(
99
- "Couldn't obtain the Spin FQDN for Shopify when the CLI is not running from a Spin environment."
100
- );
101
- var NotProvidedStoreFQDNError = new AbortError(
102
- "Couldn't obtain the Shopify FQDN because the store FQDN was not provided."
103
- );
104
- async function partnersFqdn() {
105
- const environment = serviceEnvironment();
106
- const productionFqdn = "partners.shopify.com";
107
- switch (environment) {
108
- case "local":
109
- return "partners.myshopify.io";
110
- case "spin":
111
- return `partners.${await spinFqdn()}`;
112
- default:
113
- return productionFqdn;
114
- }
115
- }
116
- async function appManagementFqdn() {
117
- const environment = serviceEnvironment();
118
- const productionFqdn = "shopify.com";
119
- switch (environment) {
120
- case "local":
121
- return "app.shopify.myshopify.io";
122
- case "spin":
123
- return `app.shopify.${await spinFqdn()}`;
124
- default:
125
- return productionFqdn;
126
- }
127
- }
128
- async function businessPlatformFqdn() {
129
- const environment = serviceEnvironment();
130
- const productionFqdn = "destinations.shopifysvc.com";
131
- switch (environment) {
132
- case "local":
133
- return "business-platform.myshopify.io";
134
- case "spin":
135
- return `business-platform.${await spinFqdn()}`;
136
- default:
137
- return productionFqdn;
138
- }
139
- }
140
- async function identityFqdn() {
141
- const environment = serviceEnvironment();
142
- const productionFqdn = "accounts.shopify.com";
143
- switch (environment) {
144
- case "local":
145
- return "identity.myshopify.io";
146
- case "spin":
147
- return `identity.${await spinFqdn()}`;
148
- default:
149
- return productionFqdn;
150
- }
151
- }
152
- async function normalizeStoreFqdn(store2) {
153
- const storeFqdn = store2.replace(/^https?:\/\//, "").replace(/\/$/, "");
154
- const addDomain = async (storeFqdn2) => isSpinEnvironment() ? `${storeFqdn2}.shopify.${await spinFqdn()}` : `${storeFqdn2}.myshopify.com`;
155
- const containDomain = (storeFqdn2) => storeFqdn2.includes(".myshopify.com") || storeFqdn2.includes("spin.dev");
156
- return containDomain(storeFqdn) ? storeFqdn : addDomain(storeFqdn);
157
- }
158
-
159
- // ../cli-kit/src/private/node/session/store.ts
160
- init_cjs_shims();
161
-
162
- // ../cli-kit/src/private/node/session/schema.ts
163
- init_cjs_shims();
164
- var DateSchema = z.preprocess((arg) => {
165
- if (typeof arg === "string" || arg instanceof Date)
166
- return new Date(arg);
167
- return null;
168
- }, z.date());
169
- var IdentityTokenSchema = z.object({
170
- accessToken: z.string(),
171
- refreshToken: z.string(),
172
- expiresAt: DateSchema,
173
- scopes: z.array(z.string())
174
- });
175
- var ApplicationTokenSchema = z.object({
176
- accessToken: z.string(),
177
- expiresAt: DateSchema,
178
- scopes: z.array(z.string())
179
- });
180
- var SessionSchema = z.object({}).catchall(
181
- z.object({
182
- /**
183
- * It contains the identity token. Before usint it, we exchange it
184
- * to get a token that we can use with different applications. The exchanged
185
- * tokens for the applications are stored under applications.
186
- */
187
- identity: IdentityTokenSchema,
188
- /**
189
- * It contains exchanged tokens for the applications the CLI
190
- * authenticates with. Tokens are scoped under the fqdn of the applications.
191
- */
192
- applications: z.object({}).catchall(ApplicationTokenSchema)
193
- })
194
- );
195
-
196
- // ../cli-kit/src/private/node/session/store.ts
197
- async function store(session) {
198
- const jsonSession = JSON.stringify(session);
199
- setSession(jsonSession);
200
- }
201
- async function fetch() {
202
- const content = getSession();
203
- if (!content) {
204
- return void 0;
205
- }
206
- const contentJson = JSON.parse(content);
207
- const parsedSession = await SessionSchema.safeParseAsync(contentJson);
208
- if (parsedSession.success) {
209
- return parsedSession.data;
210
- } else {
211
- await remove();
212
- return void 0;
213
- }
214
- }
215
- async function remove() {
216
- removeSession();
217
- }
218
-
219
- // ../cli-kit/src/private/node/session/exchange.ts
220
- init_cjs_shims();
221
-
222
- // ../cli-kit/src/private/node/session/identity.ts
223
- init_cjs_shims();
224
- function clientId() {
225
- const environment = serviceEnvironment();
226
- if (environment === "local" /* Local */) {
227
- return "e5380e02-312a-7408-5718-e07017e9cf52";
228
- } else if (environment === "production" /* Production */) {
229
- return "fbdb2649-e327-4907-8f67-908d24cfd7e3";
230
- } else {
231
- return "e5380e02-312a-7408-5718-e07017e9cf52";
232
- }
233
- }
234
- function applicationId(api) {
235
- switch (api) {
236
- case "admin": {
237
- const environment = serviceEnvironment();
238
- if (environment === "local" /* Local */) {
239
- return "e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52";
240
- } else if (environment === "production" /* Production */) {
241
- return "7ee65a63608843c577db8b23c4d7316ea0a01bd2f7594f8a9c06ea668c1b775c";
242
- } else {
243
- return "e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52";
244
- }
245
- }
246
- case "partners": {
247
- const environment = serviceEnvironment();
248
- if (environment === "local" /* Local */) {
249
- return "df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978";
250
- } else if (environment === "production" /* Production */) {
251
- return "271e16d403dfa18082ffb3d197bd2b5f4479c3fc32736d69296829cbb28d41a6";
252
- } else {
253
- return "df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978";
254
- }
255
- }
256
- case "storefront-renderer": {
257
- const environment = serviceEnvironment();
258
- if (environment === "local" /* Local */) {
259
- return "46f603de-894f-488d-9471-5b721280ff49";
260
- } else if (environment === "production" /* Production */) {
261
- return "ee139b3d-5861-4d45-b387-1bc3ada7811c";
262
- } else {
263
- return "46f603de-894f-488d-9471-5b721280ff49";
264
- }
265
- }
266
- case "business-platform": {
267
- const environment = serviceEnvironment();
268
- if (environment === "local" /* Local */) {
269
- return "ace6dc89-b526-456d-a942-4b8ef6acda4b";
270
- } else if (environment === "production" /* Production */) {
271
- return "32ff8ee5-82b8-4d93-9f8a-c6997cefb7dc";
272
- } else {
273
- return "ace6dc89-b526-456d-a942-4b8ef6acda4b";
274
- }
275
- }
276
- case "app-management": {
277
- const environment = serviceEnvironment();
278
- if (environment === "production" /* Production */) {
279
- return "7ee65a63608843c577db8b23c4d7316ea0a01bd2f7594f8a9c06ea668c1b775c";
280
- } else {
281
- return "e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52";
282
- }
283
- }
284
- default:
285
- throw new BugError(`Application id for API of type: ${api}`);
286
- }
287
- }
288
-
289
- // ../cli-kit/src/public/node/result.ts
290
- init_cjs_shims();
291
- var ok = (value) => new Ok(value);
292
- var err = (err2) => new Err(err2);
293
- var Ok = class {
294
- constructor(value) {
295
- this.value = value;
296
- }
297
- /**
298
- * Check if a `Result` is an `Err` inferring its type. `!isErr()` should be used before accessing the `value`
299
- *
300
- * @returns `false` as the `Resul` is `OK`
301
- */
302
- isErr() {
303
- return false;
304
- }
305
- /**
306
- * Runs the `handler` method an return the same an unaltered copy of the `Result`. It could be used to log an
307
- * output when the result is `Ok` without breaking the flow
308
- *
309
- * @param handler - method to be run when the result is `Ok`
310
- * @returns a copy of the same `Result`
311
- */
312
- doOnOk(handler) {
313
- handler(this.value);
314
- return ok(this.value);
315
- }
316
- /**
317
- * A safe mode to throw the `error` of the `Result`
318
- */
319
- valueOrBug() {
320
- return this.value;
321
- }
322
- /**
323
- * Throws an abort error if the result doesn't represent a value.
324
- */
325
- valueOrAbort() {
326
- return this.value;
327
- }
328
- /**
329
- * Maps the value to another one with a different type. It leaves the `Error` type unaltered
330
- *
331
- * @param mapper - The mapper method to apply an `OK` value
332
- * @returns a new result with the new mapped value
333
- */
334
- map(mapper) {
335
- return ok(mapper(this.value));
336
- }
337
- /**
338
- * Maps the error type to another one. It leaves the `Ok` type and value unaltered
339
- *
340
- * @param _mapper - This mapper method is not used for an `Ok` value
341
- * @returns a new result with the new mapped error type and an value
342
- */
343
- mapError(_mapper) {
344
- return ok(this.value);
345
- }
346
- };
347
- var Err = class {
348
- // eslint-disable-next-line node/handle-callback-err
349
- constructor(error) {
350
- this.error = error;
351
- }
352
- /**
353
- * Check if a `Result` is an `Err` inferring its type. `!isErr()` should be used before accessing the `value`
354
- *
355
- * @returns `false` as the `Resul` is `OK`
356
- */
357
- isErr() {
358
- return true;
359
- }
360
- /**
361
- * Return an unaltered copy of the `Error` without doing anything.
362
- *
363
- * @param _handler - This handler method is not used for an `Error`
364
- * @returns a copy of the same `Error`
365
- */
366
- doOnOk(_handler) {
367
- return err(this.error);
368
- }
369
- /**
370
- * A safe mode to throw the `error` of the `Result`
371
- */
372
- valueOrBug() {
373
- throw this.error;
374
- }
375
- /**
376
- * Throws an abort error if the result doesn't represent a value.
377
- */
378
- valueOrAbort() {
379
- if (this.error instanceof FatalError) {
380
- throw this.error;
381
- } else if (this.error instanceof import_ts_error.ExtendableError || this.error instanceof Error) {
382
- const error = new AbortError(this.error.message);
383
- error.stack = this.error.stack;
384
- throw error;
385
- } else {
386
- throw new AbortError(`${this.error}`);
387
- }
388
- }
389
- /**
390
- * Maps the value type to another one. It leaves the `Error` unaltered
391
- *
392
- * @param _mapper - This mapper method is not used for an `Error` value
393
- * @returns a new result with the new value type and an unaltered error
394
- */
395
- map(_mapper) {
396
- return err(this.error);
397
- }
398
- /**
399
- * Maps the error to another one with a different type. It leaves the value type unaltered
400
- *
401
- * @param mapper - The mapper method to apply an `Error` value
402
- * @returns a new result with the new mapped error
403
- */
404
- mapError(mapper) {
405
- return err(mapper(this.error));
406
- }
407
- };
408
-
409
- // ../cli-kit/src/private/node/session/exchange.ts
410
- var InvalidGrantError = class extends import_ts_error.ExtendableError {
411
- };
412
- var InvalidRequestError = class extends import_ts_error.ExtendableError {
413
- };
414
- async function exchangeCodeForAccessToken(codeData) {
415
- const clientId2 = await clientId();
416
- const params = {
417
- grant_type: "authorization_code",
418
- code: codeData.code,
419
- redirect_uri: "http://127.0.0.1:3456",
420
- client_id: clientId2,
421
- code_verifier: codeData.codeVerifier
422
- };
423
- const tokenResult = await tokenRequest(params);
424
- const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug();
425
- return buildIdentityToken(value);
426
- }
427
- async function exchangeAccessForApplicationTokens(identityToken, scopes, store2) {
428
- const token = identityToken.accessToken;
429
- const appManagementEnabled = isTruthy(process.env.USE_APP_MANAGEMENT_API);
430
- const [partners, storefront, businessPlatform, admin, appManagement] = await Promise.all([
431
- requestAppToken("partners", token, scopes.partners),
432
- requestAppToken("storefront-renderer", token, scopes.storefront),
433
- requestAppToken("business-platform", token, scopes.businessPlatform),
434
- store2 ? requestAppToken("admin", token, scopes.admin, store2) : {},
435
- appManagementEnabled ? requestAppToken("app-management", token, scopes.appManagement) : {}
436
- ]);
437
- return {
438
- ...partners,
439
- ...storefront,
440
- ...businessPlatform,
441
- ...admin,
442
- ...appManagement
443
- };
444
- }
445
- async function refreshAccessToken(currentToken) {
446
- const clientId2 = clientId();
447
- const params = {
448
- grant_type: "refresh_token",
449
- access_token: currentToken.accessToken,
450
- refresh_token: currentToken.refreshToken,
451
- client_id: clientId2
452
- };
453
- const tokenResult = await tokenRequest(params);
454
- const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug();
455
- return buildIdentityToken(value);
456
- }
457
- async function exchangeCustomPartnerToken(token) {
458
- const appId = applicationId("partners");
459
- try {
460
- const newToken = await requestAppToken("partners", token, ["https://api.shopify.com/auth/partners.app.cli.access"]);
461
- return newToken[appId];
462
- } catch (error) {
463
- throw new AbortError("The custom token provided is invalid.", "Ensure the token is correct and not expired.");
464
- }
465
- }
466
- async function exchangeDeviceCodeForAccessToken(deviceCode) {
467
- const clientId2 = await clientId();
468
- const params = {
469
- grant_type: "urn:ietf:params:oauth:grant-type:device_code",
470
- device_code: deviceCode,
471
- client_id: clientId2
472
- };
473
- const tokenResult = await tokenRequest(params);
474
- if (tokenResult.isErr()) {
475
- return err(tokenResult.error);
476
- }
477
- const identityToken = buildIdentityToken(tokenResult.value);
478
- return ok(identityToken);
479
- }
480
- async function requestAppToken(api, token, scopes = [], store2) {
481
- const appId = applicationId(api);
482
- const clientId2 = await clientId();
483
- const params = {
484
- grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
485
- requested_token_type: "urn:ietf:params:oauth:token-type:access_token",
486
- subject_token_type: "urn:ietf:params:oauth:token-type:access_token",
487
- client_id: clientId2,
488
- audience: appId,
489
- scope: scopes.join(" "),
490
- subject_token: token,
491
- ...api === "admin" && { destination: `https://${store2}/admin` }
492
- };
493
- let identifier = appId;
494
- if (api === "admin" && store2) {
495
- identifier = `${store2}-${appId}`;
496
- }
497
- const tokenResult = await tokenRequest(params);
498
- const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug();
499
- const appToken = buildApplicationToken(value);
500
- return { [identifier]: appToken };
501
- }
502
- function tokenRequestErrorHandler(error) {
503
- if (error === "invalid_grant") {
504
- return new InvalidGrantError();
505
- }
506
- if (error === "invalid_request") {
507
- return new InvalidRequestError();
508
- }
509
- return new AbortError(error);
510
- }
511
- async function tokenRequest(params) {
512
- const fqdn = await identityFqdn();
513
- const url2 = new URL(`https://${fqdn}/oauth/token`);
514
- url2.search = new URLSearchParams(Object.entries(params)).toString();
515
- const res = await shopifyFetch(url2.href, { method: "POST" });
516
- const payload = await res.json();
517
- if (res.ok)
518
- return ok(payload);
519
- return err(payload.error);
520
- }
521
- function buildIdentityToken(result) {
522
- return {
523
- accessToken: result.access_token,
524
- refreshToken: result.refresh_token,
525
- expiresAt: new Date(Date.now() + result.expires_in * 1e3),
526
- scopes: result.scope.split(" ")
527
- };
528
- }
529
- function buildApplicationToken(result) {
530
- return {
531
- accessToken: result.access_token,
532
- expiresAt: new Date(Date.now() + result.expires_in * 1e3),
533
- scopes: result.scope.split(" ")
534
- };
535
- }
536
-
537
- // ../cli-kit/src/private/node/session.ts
538
- init_cjs_shims();
539
-
540
- // ../cli-kit/src/private/node/session/validate.ts
541
- init_cjs_shims();
542
-
543
- // ../cli-kit/src/private/node/session/identity-token-validation.ts
544
- init_cjs_shims();
545
- async function validateIdentityToken(token) {
546
- if (isSpin() && firstPartyDev())
547
- return true;
548
- try {
549
- return withIntrospectionURL(async (introspectionURL) => {
550
- const options = {
551
- method: "POST",
552
- headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
553
- body: JSON.stringify({ token })
554
- };
555
- outputDebug(`Sending Identity Introspection request to URL: ${introspectionURL}`);
556
- const response = await shopifyFetch(introspectionURL, options);
557
- if (response.ok && response.headers.get("content-type")?.includes("json")) {
558
- const json = await response.json();
559
- outputDebug(`The identity token is valid: ${json.valid}`);
560
- return ok(json.valid);
561
- } else if (response.status === 404 || response.status > 500) {
562
- return err(new AbortError(`The introspection endpoint returned a ${response.status}: ${introspectionURL}`));
563
- } else {
564
- const text = await response.text();
565
- outputDebug(`The Introspection request failed with:
566
- - status: ${response.status}
567
- - www-authenticate header: ${JSON.stringify(response.headers.get("www-authenticate"))}
568
- - body: ${JSON.stringify(text)}`);
569
- return ok(false);
570
- }
571
- });
572
- } catch (error) {
573
- outputDebug(`The identity token is invalid: ${error}`);
574
- return false;
575
- }
576
- }
577
- async function withIntrospectionURL(fn) {
578
- const week = 7 * 24 * 60 * 60 * 1e3;
579
- const cacheKey = `identity-introspection-url-${await identityFqdn()}`;
580
- let introspectionURL = await cacheRetrieveOrRepopulate(cacheKey, getIntrospectionURL, week);
581
- let result = await fn(introspectionURL);
582
- if (result.isErr()) {
583
- introspectionURL = await cacheRetrieveOrRepopulate(cacheKey, getIntrospectionURL, 0);
584
- result = await fn(introspectionURL);
585
- }
586
- if (result.isErr()) {
587
- throw result.error;
588
- } else {
589
- return result.value;
590
- }
591
- }
592
- async function getIntrospectionURL() {
593
- const response = await shopifyFetch(`https://${await identityFqdn()}/.well-known/openid-configuration.json`);
594
- const json = await response.json();
595
- return json.introspection_endpoint;
596
- }
597
-
598
- // ../cli-kit/src/private/node/session/validate.ts
599
- function validateScopes(requestedScopes, identity) {
600
- const currentScopes = identity.scopes;
601
- if (firstPartyDev() !== currentScopes.includes("employee"))
602
- return false;
603
- return requestedScopes.every((scope) => currentScopes.includes(scope));
604
- }
605
- async function validateSession(scopes, applications, session) {
606
- if (!session)
607
- return "needs_full_auth";
608
- const scopesAreValid = validateScopes(scopes, session.identity);
609
- const identityIsValid = await validateIdentityToken(session.identity.accessToken);
610
- if (!scopesAreValid)
611
- return "needs_full_auth";
612
- let tokensAreExpired = isTokenExpired(session.identity);
613
- if (applications.partnersApi) {
614
- const appId = applicationId("partners");
615
- const token = session.applications[appId];
616
- tokensAreExpired = tokensAreExpired || isTokenExpired(token);
617
- }
618
- if (applications.appManagementApi) {
619
- const appId = applicationId("app-management");
620
- const token = session.applications[appId];
621
- tokensAreExpired = tokensAreExpired || isTokenExpired(token);
622
- }
623
- if (applications.storefrontRendererApi) {
624
- const appId = applicationId("storefront-renderer");
625
- const token = session.applications[appId];
626
- tokensAreExpired = tokensAreExpired || isTokenExpired(token);
627
- }
628
- if (applications.adminApi) {
629
- const appId = applicationId("admin");
630
- const realAppId = `${applications.adminApi.storeFqdn}-${appId}`;
631
- const token = session.applications[realAppId];
632
- tokensAreExpired = tokensAreExpired || isTokenExpired(token);
633
- }
634
- outputDebug(`
635
- The validation of the token for application/identity completed with the following results:
636
- - It's expired: ${tokensAreExpired}
637
- - It's invalid in identity: ${!identityIsValid}
638
- `);
639
- if (tokensAreExpired)
640
- return "needs_refresh";
641
- if (!identityIsValid)
642
- return "needs_full_auth";
643
- return "ok";
644
- }
645
- function isTokenExpired(token) {
646
- if (!token)
647
- return true;
648
- return token.expiresAt < expireThreshold();
649
- }
650
- function expireThreshold() {
651
- return new Date(Date.now() + sessionConstants.expirationTimeMarginInMinutes * 60 * 1e3);
652
- }
653
-
654
- // ../cli-kit/src/private/node/session/scopes.ts
655
- init_cjs_shims();
656
- function allDefaultScopes(extraScopes = [], systemEnvironment = process.env) {
657
- let scopes = allAPIs.map((api) => defaultApiScopes(api, systemEnvironment)).flat();
658
- scopes = ["openid", ...scopes, ...extraScopes].map(scopeTransform);
659
- return Array.from(new Set(scopes));
660
- }
661
- function apiScopes(api, extraScopes = [], systemEnvironment = process.env) {
662
- const scopes = [...defaultApiScopes(api, systemEnvironment), ...extraScopes.map(scopeTransform)].map(scopeTransform);
663
- return Array.from(new Set(scopes));
664
- }
665
- function defaultApiScopes(api, systemEnvironment = process.env) {
666
- switch (api) {
667
- case "admin":
668
- return ["graphql", "themes", "collaborator"];
669
- case "storefront-renderer":
670
- return ["devtools"];
671
- case "partners":
672
- return ["cli"];
673
- case "business-platform":
674
- return ["destinations"];
675
- case "app-management":
676
- return isTruthy(systemEnvironment.USE_APP_MANAGEMENT_API) ? ["app-management"] : [];
677
- default:
678
- throw new BugError(`Unknown API: ${api}`);
679
- }
680
- }
681
- function scopeTransform(scope) {
682
- switch (scope) {
683
- case "graphql":
684
- return "https://api.shopify.com/auth/shop.admin.graphql";
685
- case "themes":
686
- return "https://api.shopify.com/auth/shop.admin.themes";
687
- case "collaborator":
688
- return "https://api.shopify.com/auth/partners.collaborator-relationships.readonly";
689
- case "cli":
690
- return "https://api.shopify.com/auth/partners.app.cli.access";
691
- case "devtools":
692
- return "https://api.shopify.com/auth/shop.storefront-renderer.devtools";
693
- case "destinations":
694
- return "https://api.shopify.com/auth/destinations.readonly";
695
- case "app-management":
696
- return "https://api.shopify.com/auth/organization.apps.manage";
697
- default:
698
- return scope;
699
- }
700
- }
701
-
702
- // ../cli-kit/src/private/node/session/authorize.ts
703
- init_cjs_shims();
704
-
705
- // ../cli-kit/src/private/node/session/redirect-listener.ts
706
- init_cjs_shims();
707
-
708
- // ../cli-kit/src/private/node/session/post-auth.ts
709
- init_cjs_shims();
710
- var HTMLFileNames = [
711
- "empty-url.html",
712
- "auth-error.html",
713
- "missing-code.html",
714
- "missing-state.html",
715
- "success.html"
716
- ];
717
- var StylesheetFilename = "style.css";
718
- var FaviconFileName = "favicon.svg";
719
- var getFilePath = async (fileName) => {
720
- const filePath = await findPathUp(`assets/${fileName}`, {
721
- type: "file",
722
- cwd: moduleDirectory(import.meta.url)
723
- });
724
- if (!filePath) {
725
- throw RedirectPageAssetNotFoundError();
726
- }
727
- return filePath;
728
- };
729
- var getEmptyUrlHTML = async () => {
730
- const filePath = await getFilePath(HTMLFileNames[0]);
731
- return readFile(filePath);
732
- };
733
- var getAuthErrorHTML = async () => {
734
- const filePath = await getFilePath(HTMLFileNames[1]);
735
- return readFile(filePath);
736
- };
737
- var getMissingCodeHTML = async () => {
738
- const filePath = await getFilePath(HTMLFileNames[2]);
739
- return readFile(filePath);
740
- };
741
- var getMissingStateHTML = async () => {
742
- const filePath = await getFilePath(HTMLFileNames[3]);
743
- return readFile(filePath);
744
- };
745
- var getSuccessHTML = async () => {
746
- const filePath = await getFilePath(HTMLFileNames[4]);
747
- return readFile(filePath);
748
- };
749
- var getStylesheet = async () => {
750
- const filePath = await getFilePath(StylesheetFilename);
751
- return readFile(filePath);
752
- };
753
- var getFavicon = async () => {
754
- const filePath = await getFilePath(FaviconFileName);
755
- return readFile(filePath);
756
- };
757
- var EmptyUrlString = "We received the authentication redirect but the URL is empty.";
758
- var MissingCodeString = "The authentication can't continue because the redirect doesn't include the code.";
759
- var MissingStateString = "The authentication can't continue because the redirect doesn't include the state.";
760
- var RedirectPageAssetNotFoundError = () => new BugError(`Redirect page asset not found`);
761
-
762
- // ../cli-kit/src/private/node/session/redirect-listener.ts
763
- import url from "url";
764
- import { createServer } from "http";
765
- var ResponseTimeoutSeconds = 10;
766
- var ServerStopDelaySeconds = 0.5;
767
- var RedirectListener = class _RedirectListener {
768
- static createServer(callback) {
769
- const app = async (request, response) => {
770
- const requestUrl = request.url;
771
- if (requestUrl?.includes("favicon")) {
772
- const faviconFile = await getFavicon();
773
- response.setHeader("Content-Type", "image/svg+xml");
774
- response.write(faviconFile);
775
- response.end();
776
- return {};
777
- } else if (requestUrl === "/style.css") {
778
- const stylesheetFile = await getStylesheet();
779
- response.setHeader("Content-Type", "text/css");
780
- response.write(stylesheetFile);
781
- response.end();
782
- return {};
783
- }
784
- const respond = async (contents, error, state, code) => {
785
- response.setHeader("Content-Type", "text/html");
786
- response.write(contents);
787
- response.end();
788
- callback(error, state, code);
789
- return {};
790
- };
791
- if (!requestUrl) {
792
- const file2 = await getEmptyUrlHTML();
793
- const err2 = new BugError(EmptyUrlString);
794
- return respond(file2, err2, void 0, void 0);
795
- }
796
- const queryObject = url.parse(requestUrl, true).query;
797
- if (queryObject.error && queryObject.error_description) {
798
- const file2 = await getAuthErrorHTML();
799
- const err2 = new AbortError(`${queryObject.error_description}`);
800
- return respond(file2, err2, void 0, void 0);
801
- }
802
- if (!queryObject.code) {
803
- const file2 = await getMissingCodeHTML();
804
- const err2 = new BugError(MissingCodeString);
805
- return respond(file2, err2, void 0, void 0);
806
- }
807
- if (!queryObject.state) {
808
- const file2 = await getMissingStateHTML();
809
- const err2 = new BugError(MissingStateString);
810
- return respond(file2, err2, void 0, void 0);
811
- }
812
- const file = await getSuccessHTML();
813
- return respond(file, void 0, `${queryObject.code}`, `${queryObject.state}`);
814
- };
815
- return createServer(app);
816
- }
817
- constructor(options) {
818
- this.port = options.port;
819
- this.host = options.host;
820
- this.server = _RedirectListener.createServer(options.callback);
821
- }
822
- start() {
823
- this.server.listen({ port: this.port, host: this.host }, () => {
824
- });
825
- }
826
- async stop() {
827
- await this.server.close();
828
- }
829
- };
830
- async function listenRedirect(host, port, url2) {
831
- const result = await new Promise((resolve, reject) => {
832
- const timeout = setTimeout(() => {
833
- const message = "\nAuto-open timed out. Open the login page: ";
834
- outputInfo(outputContent`${message}${outputToken.link("Log in to Shopify Partners", url2)}\n`);
835
- }, ResponseTimeoutSeconds * 1e3);
836
- const callback = (error, code, state) => {
837
- clearTimeout(timeout);
838
- setTimeout(() => {
839
- redirectListener.stop();
840
- if (error)
841
- reject(error);
842
- else
843
- resolve({ code, state });
844
- }, ServerStopDelaySeconds * 1e3);
845
- };
846
- const redirectListener = new RedirectListener({ host, port, callback });
847
- redirectListener.start();
848
- });
849
- return result;
850
- }
851
-
852
- // ../cli-kit/src/private/node/session/authorize.ts
853
- var import_find_process = __toESM(require_find_process(), 1);
854
- async function authorize(scopes, state = randomHex(30)) {
855
- const port = 3456;
856
- const host = "127.0.0.1";
857
- const redirectUri = `http://${host}:${port}`;
858
- const fqdn = await identityFqdn();
859
- const identityClientId = clientId();
860
- await validateRedirectionPortAvailability(port);
861
- let url2 = `http://${fqdn}/oauth/authorize`;
862
- const { codeVerifier, codeChallenge } = generateRandomChallengePair();
863
- const params = {
864
- client_id: identityClientId,
865
- scope: scopes.join(" "),
866
- redirect_uri: redirectUri,
867
- state,
868
- response_type: "code",
869
- code_challenge_method: "S256",
870
- code_challenge: codeChallenge
871
- };
872
- outputInfo("\nTo run this command, log in to Shopify.");
873
- outputInfo("\u{1F449} Press any key to open the login page on your browser");
874
- await keypress();
875
- url2 = `${url2}?${new URLSearchParams(params).toString()}`;
876
- await openURL(url2);
877
- return runWithTimer("cmd_all_timing_prompts_ms")(async () => {
878
- const result = await listenRedirect(host, port, url2);
879
- if (result.state !== state) {
880
- throw new AbortError(
881
- "The state received from the authentication doesn't match the one that initiated the authentication process."
882
- );
883
- }
884
- return { code: result.code, codeVerifier };
885
- });
886
- }
887
- function generateRandomChallengePair() {
888
- const codeVerifier = base64URLEncode(randomBytes(32));
889
- const codeChallenge = base64URLEncode(sha256(codeVerifier));
890
- return { codeVerifier, codeChallenge };
891
- }
892
- async function validateRedirectionPortAvailability(port) {
893
- const { killPortProcess } = await import("./lib-MUDJYT6A.js");
894
- if (await checkPort(port)) {
895
- return;
896
- }
897
- if (await terminateBlockingPortProcessPrompt(port, "Authentication")) {
898
- await killPortProcess(port);
899
- } else {
900
- throw new CancelExecution();
901
- }
902
- }
903
- async function terminateBlockingPortProcessPrompt(port, stepDescription) {
904
- const processInfo = await (0, import_find_process.default)("port", port);
905
- const formattedProcessName = processInfo && processInfo.length > 0 && processInfo[0]?.name ? ` (${processInfo[0].name})` : "";
906
- return renderConfirmationPrompt({
907
- message: `${stepDescription} requires a port ${port} that's unavailable because it's running another process${formattedProcessName}. Terminate that process?`,
908
- confirmationMessage: "Yes, terminate process in order to log in now",
909
- cancellationMessage: `No, cancel command and try later`
910
- });
911
- }
912
-
913
- // ../cli-kit/src/private/node/session/device-authorization.ts
914
- init_cjs_shims();
915
- async function requestDeviceAuthorization(scopes) {
916
- const fqdn = await identityFqdn();
917
- const identityClientId = await clientId();
918
- const queryParams = { client_id: identityClientId, scope: scopes.join(" ") };
919
- const url2 = `https://${fqdn}/oauth/device_authorization`;
920
- const response = await shopifyFetch(url2, {
921
- method: "POST",
922
- headers: { "Content-type": "application/x-www-form-urlencoded" },
923
- body: convertRequestToParams(queryParams)
924
- });
925
- const jsonResult = await response.json();
926
- outputDebug(outputContent`Received device authorization code: ${outputToken.json(jsonResult)}`);
927
- if (!jsonResult.device_code || !jsonResult.verification_uri_complete) {
928
- throw new BugError("Failed to start authorization process");
929
- }
930
- outputInfo("\nTo run this command, log in to Shopify.");
931
- outputInfo(outputContent`User verification code: ${jsonResult.user_code}`);
932
- outputInfo(
933
- outputContent`👉 Open this link to start the auth process: ${outputToken.green(
934
- jsonResult.verification_uri_complete
935
- )}`
936
- );
937
- return {
938
- deviceCode: jsonResult.device_code,
939
- userCode: jsonResult.user_code,
940
- verificationUri: jsonResult.verification_uri,
941
- expiresIn: jsonResult.expires_in,
942
- verificationUriComplete: jsonResult.verification_uri_complete,
943
- interval: jsonResult.interval
944
- };
945
- }
946
- async function pollForDeviceAuthorization(code, interval = 5) {
947
- let currentIntervalInSeconds = interval;
948
- return new Promise((resolve, reject) => {
949
- const onPoll = async () => {
950
- const result = await exchangeDeviceCodeForAccessToken(code);
951
- if (!result.isErr())
952
- return resolve(result.value);
953
- const error = result.error ?? "unknown_failure";
954
- outputDebug(outputContent`Polling for device authorization... status: ${error}`);
955
- switch (error) {
956
- case "authorization_pending":
957
- return startPolling();
958
- case "slow_down":
959
- currentIntervalInSeconds += 5;
960
- return startPolling();
961
- case "access_denied":
962
- case "expired_token":
963
- case "unknown_failure":
964
- return reject(result);
965
- }
966
- };
967
- const startPolling = () => {
968
- setTimeout(onPoll, currentIntervalInSeconds * 1e3);
969
- };
970
- startPolling();
971
- });
972
- }
973
- function convertRequestToParams(queryParams) {
974
- return Object.entries(queryParams).map(([key, value]) => value && `${key}=${value}`).filter((hasValue) => Boolean(hasValue)).join("&");
975
- }
976
-
977
- // ../cli-kit/src/public/node/api/partners.ts
978
- init_cjs_shims();
979
-
980
- // ../cli-kit/src/public/node/api/graphql.ts
981
- init_cjs_shims();
982
-
983
- // ../cli-kit/src/private/node/api/graphql.ts
984
- init_cjs_shims();
985
- function debugLogRequestInfo(api, query, variables, headers = {}) {
986
- outputDebug(outputContent`Sending ${outputToken.json(api)} GraphQL request:
987
- ${outputToken.raw(query.toString().trim())}
988
- ${variables ? `
989
- With variables:
990
- ${sanitizeVariables(variables)}
991
- ` : ""}
992
- With request headers:
993
- ${sanitizedHeadersOutput(headers)}
994
- `);
995
- }
996
- function sanitizeVariables(variables) {
997
- const result = { ...variables };
998
- if ("apiKey" in result) {
999
- result.apiKey = "*****";
1000
- }
1001
- return JSON.stringify(result, null, 2);
1002
- }
1003
- function errorHandler(api) {
1004
- return (error, requestId) => {
1005
- if (error instanceof ClientError) {
1006
- const { status } = error.response;
1007
- let errorMessage = stringifyMessage(outputContent`
1008
- The ${outputToken.raw(api)} GraphQL API responded unsuccessfully with${status === 200 ? "" : ` the HTTP status ${status} and`} errors:
1009
-
1010
- ${outputToken.json(error.response.errors)}
1011
- `);
1012
- if (requestId) {
1013
- errorMessage += `
1014
- Request ID: ${requestId}
1015
- `;
1016
- }
1017
- let mappedError;
1018
- if (status < 500) {
1019
- mappedError = new GraphQLClientError(errorMessage, status, error.response.errors);
1020
- } else {
1021
- mappedError = new AbortError(errorMessage);
1022
- }
1023
- mappedError.stack = error.stack;
1024
- return mappedError;
1025
- } else {
1026
- return error;
1027
- }
1028
- };
1029
- }
1030
-
1031
- // ../cli-kit/src/public/node/api/graphql.ts
1032
- async function performGraphQLRequest(options) {
1033
- const { token, addedHeaders, queryAsString, variables, api, url: url2, responseOptions } = options;
1034
- const headers = {
1035
- ...addedHeaders,
1036
- ...buildHeaders(token)
1037
- };
1038
- debugLogRequestInfo(api, queryAsString, variables, headers);
1039
- const clientOptions = { agent: await httpsAgent(), headers };
1040
- const client = new GraphQLClient(url2, clientOptions);
1041
- return runWithTimer("cmd_all_timing_network_ms")(async () => {
1042
- const response = await debugLogResponseInfo(
1043
- { request: client.rawRequest(queryAsString, variables), url: url2 },
1044
- responseOptions?.handleErrors === false ? void 0 : errorHandler(api)
1045
- );
1046
- if (responseOptions?.onResponse) {
1047
- responseOptions.onResponse(response);
1048
- }
1049
- return response.data;
1050
- });
1051
- }
1052
- async function graphqlRequest(options) {
1053
- return performGraphQLRequest({
1054
- ...options,
1055
- queryAsString: options.query
1056
- });
1057
- }
1058
- async function graphqlRequestDoc(options) {
1059
- return performGraphQLRequest({
1060
- ...options,
1061
- queryAsString: resolveRequestDocument(options.query).query
1062
- });
1063
- }
1064
-
1065
- // ../cli-kit/src/public/node/api/partners.ts
1066
- var import_bottleneck = __toESM(require_lib(), 1);
1067
- var limiter = new import_bottleneck.default({
1068
- minTime: 150,
1069
- maxConcurrent: 10
1070
- });
1071
- async function setupRequest(token) {
1072
- const api = "Partners";
1073
- const fqdn = await partnersFqdn();
1074
- const url2 = `https://${fqdn}/api/cli/graphql`;
1075
- return {
1076
- token,
1077
- api,
1078
- url: url2,
1079
- responseOptions: { onResponse: handleDeprecations }
1080
- };
1081
- }
1082
- async function partnersRequest(query, token, variables) {
1083
- const opts = await setupRequest(token);
1084
- const result = limiter.schedule(
1085
- () => graphqlRequest({
1086
- ...opts,
1087
- query,
1088
- variables
1089
- })
1090
- );
1091
- return result;
1092
- }
1093
- async function partnersRequestDoc(query, token, variables) {
1094
- const opts = await setupRequest(token);
1095
- const result = limiter.schedule(
1096
- () => graphqlRequestDoc({
1097
- ...opts,
1098
- query,
1099
- variables
1100
- })
1101
- );
1102
- return result;
1103
- }
1104
- var FunctionUploadUrlGenerateMutation = gql`
1105
- mutation functionUploadUrlGenerateMutation {
1106
- functionUploadUrlGenerate {
1107
- generatedUrlDetails {
1108
- url
1109
- moduleId
1110
- headers
1111
- maxBytes
1112
- maxSize
1113
- }
1114
- }
1115
- }
1116
- `;
1117
- function handleDeprecations(response) {
1118
- if (!response.extensions)
1119
- return;
1120
- const deprecationDates = [];
1121
- for (const deprecation of response.extensions.deprecations) {
1122
- if (deprecation.supportedUntilDate) {
1123
- deprecationDates.push(new Date(deprecation.supportedUntilDate));
1124
- }
1125
- }
1126
- setNextDeprecationDate(deprecationDates);
1127
- }
1128
-
1129
- // ../cli-kit/src/private/node/session.ts
1130
- async function ensureAuthenticated(applications, _env, { forceRefresh = false, noPrompt = false } = {}) {
1131
- const fqdn = await identityFqdn();
1132
- const previousStoreFqdn = applications.adminApi?.storeFqdn;
1133
- if (previousStoreFqdn) {
1134
- const normalizedStoreName = await normalizeStoreFqdn(previousStoreFqdn);
1135
- if (previousStoreFqdn === applications.adminApi?.storeFqdn) {
1136
- applications.adminApi.storeFqdn = normalizedStoreName;
1137
- }
1138
- }
1139
- const currentSession = await fetch() || {};
1140
- const fqdnSession = currentSession[fqdn];
1141
- const scopes = getFlattenScopes(applications);
1142
- outputDebug(outputContent`Validating existing session against the scopes:
1143
- ${outputToken.json(scopes)}
1144
- For applications:
1145
- ${outputToken.json(applications)}
1146
- `);
1147
- const validationResult = await validateSession(scopes, applications, fqdnSession);
1148
- let newSession = {};
1149
- function throwOnNoPrompt() {
1150
- if (!noPrompt || isSpin() && firstPartyDev())
1151
- return;
1152
- throw new AbortError(
1153
- `The currently available CLI credentials are invalid.
1154
-
1155
- The CLI is currently unable to prompt for reauthentication.`,
1156
- "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."
1157
- );
1158
- }
1159
- if (validationResult === "needs_full_auth") {
1160
- throwOnNoPrompt();
1161
- outputDebug(outputContent`Initiating the full authentication flow...`);
1162
- newSession = await executeCompleteFlow(applications, fqdn);
1163
- } else if (validationResult === "needs_refresh" || forceRefresh) {
1164
- outputDebug(outputContent`The current session is valid but needs refresh. Refreshing...`);
1165
- try {
1166
- newSession = await refreshTokens(fqdnSession.identity, applications, fqdn);
1167
- } catch (error) {
1168
- if (error instanceof InvalidGrantError) {
1169
- throwOnNoPrompt();
1170
- newSession = await executeCompleteFlow(applications, fqdn);
1171
- } else if (error instanceof InvalidRequestError) {
1172
- await remove();
1173
- throw new AbortError("\nError validating auth session", "We've cleared the current session, please try again");
1174
- } else {
1175
- throw error;
1176
- }
1177
- }
1178
- }
1179
- const completeSession = { ...currentSession, ...newSession };
1180
- if (Object.keys(newSession).length > 0)
1181
- await store(completeSession);
1182
- const tokens = await tokensFor(applications, completeSession, fqdn);
1183
- const envToken = getPartnersToken();
1184
- if (envToken && applications.partnersApi) {
1185
- tokens.partners = (await exchangeCustomPartnerToken(envToken)).accessToken;
1186
- }
1187
- if (!envToken && tokens.partners) {
1188
- await ensureUserHasPartnerAccount(tokens.partners);
1189
- }
1190
- return tokens;
1191
- }
1192
- async function executeCompleteFlow(applications, identityFqdn2) {
1193
- const scopes = getFlattenScopes(applications);
1194
- const exchangeScopes = getExchangeScopes(applications);
1195
- const store2 = applications.adminApi?.storeFqdn;
1196
- if (firstPartyDev()) {
1197
- outputDebug(outputContent`Authenticating as Shopify Employee...`);
1198
- scopes.push("employee");
1199
- }
1200
- let identityToken;
1201
- const identityTokenInformation = getIdentityTokenInformation();
1202
- if (identityTokenInformation) {
1203
- identityToken = buildIdentityTokenFromEnv(scopes, identityTokenInformation);
1204
- } else if (useDeviceAuth()) {
1205
- outputDebug(outputContent`Requesting device authorization code...`);
1206
- const deviceAuth = await requestDeviceAuthorization(scopes);
1207
- outputDebug(outputContent`Starting polling for the identity token...`);
1208
- identityToken = await pollForDeviceAuthorization(deviceAuth.deviceCode, deviceAuth.interval);
1209
- } else {
1210
- outputDebug(outputContent`Authorizing through Identity's website...`);
1211
- const code = await authorize(scopes);
1212
- outputDebug(outputContent`Authorization code received. Exchanging it for a CLI token...`);
1213
- identityToken = await exchangeCodeForAccessToken(code);
1214
- }
1215
- outputDebug(outputContent`CLI token received. Exchanging it for application tokens...`);
1216
- const result = await exchangeAccessForApplicationTokens(identityToken, exchangeScopes, store2);
1217
- const session = {
1218
- [identityFqdn2]: {
1219
- identity: identityToken,
1220
- applications: result
1221
- }
1222
- };
1223
- outputCompleted("Logged in.");
1224
- return session;
1225
- }
1226
- async function ensureUserHasPartnerAccount(partnersToken) {
1227
- if (isTruthy(process.env.USE_APP_MANAGEMENT_API))
1228
- return;
1229
- outputDebug(outputContent`Verifying that the user has a Partner organization`);
1230
- if (!await hasPartnerAccount(partnersToken)) {
1231
- outputInfo(`
1232
- A Shopify Partners organization is needed to proceed.`);
1233
- outputInfo(`\u{1F449} Press any key to create one`);
1234
- await keypress();
1235
- await openURL(`https://${await partnersFqdn()}/signup`);
1236
- outputInfo(outputContent`👉 Press any key when you have ${outputToken.cyan("created the organization")}`);
1237
- outputWarn(outputContent`Make sure you've confirmed your Shopify and the Partner organization from the email`);
1238
- await keypress();
1239
- if (!await hasPartnerAccount(partnersToken)) {
1240
- throw new AbortError(
1241
- `Couldn't find your Shopify Partners organization`,
1242
- `Have you confirmed your accounts from the emails you received?`
1243
- );
1244
- }
1245
- }
1246
- }
1247
- var getFirstOrganization = gql`
1248
- {
1249
- organizations(first: 1) {
1250
- nodes {
1251
- id
1252
- }
1253
- }
1254
- }
1255
- `;
1256
- async function hasPartnerAccount(partnersToken) {
1257
- try {
1258
- await partnersRequest(getFirstOrganization, partnersToken);
1259
- return true;
1260
- } catch (error) {
1261
- if (error instanceof RequestClientError && error.statusCode === 404) {
1262
- return false;
1263
- } else {
1264
- return true;
1265
- }
1266
- }
1267
- }
1268
- async function refreshTokens(token, applications, fqdn) {
1269
- const identityToken = await refreshAccessToken(token);
1270
- const exchangeScopes = getExchangeScopes(applications);
1271
- const applicationTokens = await exchangeAccessForApplicationTokens(
1272
- identityToken,
1273
- exchangeScopes,
1274
- applications.adminApi?.storeFqdn
1275
- );
1276
- return {
1277
- [fqdn]: {
1278
- identity: identityToken,
1279
- applications: applicationTokens
1280
- }
1281
- };
1282
- }
1283
- async function tokensFor(applications, session, fqdn) {
1284
- const fqdnSession = session[fqdn];
1285
- if (!fqdnSession) {
1286
- throw new BugError("No session found after ensuring authenticated");
1287
- }
1288
- const tokens = {};
1289
- if (applications.adminApi) {
1290
- const appId = applicationId("admin");
1291
- const realAppId = `${applications.adminApi.storeFqdn}-${appId}`;
1292
- const token = fqdnSession.applications[realAppId]?.accessToken;
1293
- if (token) {
1294
- tokens.admin = { token, storeFqdn: applications.adminApi.storeFqdn };
1295
- }
1296
- }
1297
- if (applications.partnersApi) {
1298
- const appId = applicationId("partners");
1299
- tokens.partners = fqdnSession.applications[appId]?.accessToken;
1300
- }
1301
- if (applications.storefrontRendererApi) {
1302
- const appId = applicationId("storefront-renderer");
1303
- tokens.storefront = fqdnSession.applications[appId]?.accessToken;
1304
- }
1305
- if (applications.businessPlatformApi) {
1306
- const appId = applicationId("business-platform");
1307
- tokens.businessPlatform = fqdnSession.applications[appId]?.accessToken;
1308
- }
1309
- if (applications.appManagementApi) {
1310
- const appId = applicationId("app-management");
1311
- tokens.appManagement = fqdnSession.applications[appId]?.accessToken;
1312
- }
1313
- return tokens;
1314
- }
1315
- function getFlattenScopes(apps) {
1316
- const admin = apps.adminApi?.scopes || [];
1317
- const partner = apps.partnersApi?.scopes || [];
1318
- const storefront = apps.storefrontRendererApi?.scopes || [];
1319
- const businessPlatform = apps.businessPlatformApi?.scopes || [];
1320
- const appManagement = apps.appManagementApi?.scopes || [];
1321
- const requestedScopes = [...admin, ...partner, ...storefront, ...businessPlatform, ...appManagement];
1322
- return allDefaultScopes(requestedScopes);
1323
- }
1324
- function getExchangeScopes(apps) {
1325
- const adminScope = apps.adminApi?.scopes || [];
1326
- const partnerScope = apps.partnersApi?.scopes || [];
1327
- const storefrontScopes = apps.storefrontRendererApi?.scopes || [];
1328
- const businessPlatformScopes = apps.businessPlatformApi?.scopes || [];
1329
- const appManagementScopes = apps.appManagementApi?.scopes || [];
1330
- return {
1331
- admin: apiScopes("admin", adminScope),
1332
- partners: apiScopes("partners", partnerScope),
1333
- storefront: apiScopes("storefront-renderer", storefrontScopes),
1334
- businessPlatform: apiScopes("business-platform", businessPlatformScopes),
1335
- appManagement: apiScopes("app-management", appManagementScopes)
1336
- };
1337
- }
1338
- function buildIdentityTokenFromEnv(scopes, identityTokenInformation) {
1339
- return {
1340
- ...identityTokenInformation,
1341
- expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1e3),
1342
- scopes
1343
- };
1344
- }
1345
-
1346
- // ../cli-kit/src/public/node/session.ts
1347
- async function ensureAuthenticatedPartners(scopes = [], env = process.env, options = {}) {
1348
- outputDebug(outputContent`Ensuring that the user is authenticated with the Partners API with the following scopes:
1349
- ${outputToken.json(scopes)}
1350
- `);
1351
- const envToken = getPartnersToken();
1352
- if (envToken) {
1353
- return (await exchangeCustomPartnerToken(envToken)).accessToken;
1354
- }
1355
- const tokens = await ensureAuthenticated({ partnersApi: { scopes } }, env, options);
1356
- if (!tokens.partners) {
1357
- throw new BugError("No partners token found after ensuring authenticated");
1358
- }
1359
- return tokens.partners;
1360
- }
1361
- async function ensureAuthenticatedAppManagement(scopes = [], env = process.env, options = {}) {
1362
- outputDebug(outputContent`Ensuring that the user is authenticated with the App Management API with the following scopes:
1363
- ${outputToken.json(scopes)}
1364
- `);
1365
- const tokens = await ensureAuthenticated({ appManagementApi: { scopes } }, env, options);
1366
- if (!tokens) {
1367
- throw new BugError("No App Management token found after ensuring authenticated");
1368
- }
1369
- return tokens.appManagement;
1370
- }
1371
- async function ensureAuthenticatedStorefront(scopes = [], password = void 0, forceRefresh = false) {
1372
- if (password)
1373
- return password;
1374
- outputDebug(outputContent`Ensuring that the user is authenticated with the Storefront API with the following scopes:
1375
- ${outputToken.json(scopes)}
1376
- `);
1377
- const tokens = await ensureAuthenticated({ storefrontRendererApi: { scopes } }, process.env, { forceRefresh });
1378
- if (!tokens.storefront) {
1379
- throw new BugError("No storefront token found after ensuring authenticated");
1380
- }
1381
- return tokens.storefront;
1382
- }
1383
- async function ensureAuthenticatedAdmin(store2, scopes = [], forceRefresh = false, options = {}) {
1384
- outputDebug(outputContent`Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${outputToken.raw(
1385
- store2
1386
- )}:
1387
- ${outputToken.json(scopes)}
1388
- `);
1389
- const tokens = await ensureAuthenticated({ adminApi: { scopes, storeFqdn: store2 } }, process.env, {
1390
- forceRefresh,
1391
- ...options
1392
- });
1393
- if (!tokens.admin) {
1394
- throw new BugError("No admin token found after ensuring authenticated");
1395
- }
1396
- return tokens.admin;
1397
- }
1398
- async function ensureAuthenticatedThemes(store2, password, scopes = [], forceRefresh = false) {
1399
- outputDebug(outputContent`Ensuring that the user is authenticated with the Theme API with the following scopes:
1400
- ${outputToken.json(scopes)}
1401
- `);
1402
- if (password)
1403
- return { token: password, storeFqdn: await normalizeStoreFqdn(store2) };
1404
- return ensureAuthenticatedAdmin(store2, scopes, forceRefresh);
1405
- }
1406
- async function ensureAuthenticatedBusinessPlatform(scopes = []) {
1407
- outputDebug(outputContent`Ensuring that the user is authenticated with the Business Platform API with the following scopes:
1408
- ${outputToken.json(scopes)}
1409
- `);
1410
- const tokens = await ensureAuthenticated({ businessPlatformApi: { scopes } }, process.env);
1411
- if (!tokens.businessPlatform) {
1412
- throw new BugError("No business-platform token found after ensuring authenticated");
1413
- }
1414
- return tokens.businessPlatform;
1415
- }
1416
- function logout() {
1417
- return remove();
1418
- }
1419
-
1420
- // src/cli/commands/auth/logout.ts
1421
- var Logout = class extends base_command_default {
1422
- static {
1423
- this.description = "Logs you out of the Shopify account or Partner account and store.";
1424
- }
1425
- async run() {
1426
- await logout();
1427
- outputSuccess("Logged out from Shopify");
1428
- }
1429
- };
1430
-
1431
- export {
1432
- partnersFqdn,
1433
- appManagementFqdn,
1434
- businessPlatformFqdn,
1435
- normalizeStoreFqdn,
1436
- ok,
1437
- err,
1438
- graphqlRequest,
1439
- graphqlRequestDoc,
1440
- partnersRequest,
1441
- partnersRequestDoc,
1442
- FunctionUploadUrlGenerateMutation,
1443
- handleDeprecations,
1444
- ensureAuthenticatedPartners,
1445
- ensureAuthenticatedAppManagement,
1446
- ensureAuthenticatedStorefront,
1447
- ensureAuthenticatedAdmin,
1448
- ensureAuthenticatedThemes,
1449
- ensureAuthenticatedBusinessPlatform,
1450
- logout,
1451
- Logout
1452
- };
1453
- //# sourceMappingURL=chunk-XSKJYEAZ.js.map