@shopify/cli-kit 4.9.5 → 5.0.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 (127) hide show
  1. package/dist/cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.d.ts +5 -0
  2. package/dist/cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.js +22 -0
  3. package/dist/cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.js.map +1 -1
  4. package/dist/private/node/api/graphql.d.ts +2 -1
  5. package/dist/private/node/api/graphql.js +12 -1
  6. package/dist/private/node/api/graphql.js.map +1 -1
  7. package/dist/private/node/api.d.ts +2 -0
  8. package/dist/private/node/api.js +49 -22
  9. package/dist/private/node/api.js.map +1 -1
  10. package/dist/private/node/command-json-schema.js +1 -0
  11. package/dist/private/node/command-json-schema.js.map +1 -1
  12. package/dist/private/node/constants.d.ts +1 -0
  13. package/dist/private/node/constants.js +1 -0
  14. package/dist/private/node/constants.js.map +1 -1
  15. package/dist/private/node/dev-instance-output.d.ts +47 -0
  16. package/dist/private/node/dev-instance-output.js +143 -0
  17. package/dist/private/node/dev-instance-output.js.map +1 -0
  18. package/dist/private/node/json-error.d.ts +1 -15
  19. package/dist/private/node/json-error.js +4 -98
  20. package/dist/private/node/json-error.js.map +1 -1
  21. package/dist/private/node/output-context.d.ts +8 -0
  22. package/dist/private/node/output-context.js +10 -0
  23. package/dist/private/node/output-context.js.map +1 -0
  24. package/dist/private/node/output.test.js +4 -4
  25. package/dist/private/node/output.test.js.map +1 -1
  26. package/dist/private/node/session/automation-token.d.ts +50 -0
  27. package/dist/private/node/session/automation-token.js +77 -0
  28. package/dist/private/node/session/automation-token.js.map +1 -0
  29. package/dist/private/node/session/exchange.d.ts +5 -1
  30. package/dist/private/node/session/exchange.js +97 -7
  31. package/dist/private/node/session/exchange.js.map +1 -1
  32. package/dist/private/node/session/permanent-store-domain.d.ts +21 -0
  33. package/dist/private/node/session/permanent-store-domain.js +72 -0
  34. package/dist/private/node/session/permanent-store-domain.js.map +1 -0
  35. package/dist/private/node/session.d.ts +3 -2
  36. package/dist/private/node/session.js +12 -3
  37. package/dist/private/node/session.js.map +1 -1
  38. package/dist/private/node/themes/trust-challenge.d.ts +31 -0
  39. package/dist/private/node/themes/trust-challenge.js +143 -0
  40. package/dist/private/node/themes/trust-challenge.js.map +1 -0
  41. package/dist/private/node/ui/alert.js +1 -1
  42. package/dist/private/node/ui/alert.js.map +1 -1
  43. package/dist/private/node/ui/components/ConcurrentOutput.d.ts +2 -7
  44. package/dist/private/node/ui/components/ConcurrentOutput.js +4 -8
  45. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  46. package/dist/private/node/ui/components/LoadingBar.js +9 -15
  47. package/dist/private/node/ui/components/LoadingBar.js.map +1 -1
  48. package/dist/private/node/ui/components/LoadingBar.test.js +45 -107
  49. package/dist/private/node/ui/components/LoadingBar.test.js.map +1 -1
  50. package/dist/private/node/ui/components/LoadingIndicator.d.ts +7 -0
  51. package/dist/private/node/ui/components/LoadingIndicator.js +22 -0
  52. package/dist/private/node/ui/components/LoadingIndicator.js.map +1 -0
  53. package/dist/private/node/ui/components/Table/Table.d.ts +8 -0
  54. package/dist/private/node/ui/components/Table/Table.js +18 -2
  55. package/dist/private/node/ui/components/Table/Table.js.map +1 -1
  56. package/dist/public/common/version.d.ts +1 -1
  57. package/dist/public/common/version.js +1 -1
  58. package/dist/public/common/version.js.map +1 -1
  59. package/dist/public/node/api/admin.js +13 -0
  60. package/dist/public/node/api/admin.js.map +1 -1
  61. package/dist/public/node/api/graphql.js +38 -7
  62. package/dist/public/node/api/graphql.js.map +1 -1
  63. package/dist/public/node/archiver.js +13 -6
  64. package/dist/public/node/archiver.js.map +1 -1
  65. package/dist/public/node/base-command.d.ts +6 -0
  66. package/dist/public/node/base-command.js +97 -16
  67. package/dist/public/node/base-command.js.map +1 -1
  68. package/dist/public/node/dev-instance.d.ts +138 -0
  69. package/dist/public/node/dev-instance.js +365 -0
  70. package/dist/public/node/dev-instance.js.map +1 -0
  71. package/dist/public/node/environment.d.ts +6 -3
  72. package/dist/public/node/environment.js +11 -4
  73. package/dist/public/node/environment.js.map +1 -1
  74. package/dist/public/node/error/index.js +2 -1
  75. package/dist/public/node/error/index.js.map +1 -1
  76. package/dist/public/node/error/schema.d.ts +24 -24
  77. package/dist/public/node/error/serialization.d.ts +8 -0
  78. package/dist/public/node/error/serialization.js +103 -0
  79. package/dist/public/node/error/serialization.js.map +1 -0
  80. package/dist/public/node/graphiql/server.js +18 -2
  81. package/dist/public/node/graphiql/server.js.map +1 -1
  82. package/dist/public/node/is-global.js +2 -1
  83. package/dist/public/node/is-global.js.map +1 -1
  84. package/dist/public/node/notifications-system.d.ts +6 -6
  85. package/dist/public/node/path.d.ts +19 -3
  86. package/dist/public/node/path.js +21 -3
  87. package/dist/public/node/path.js.map +1 -1
  88. package/dist/public/node/session.d.ts +38 -3
  89. package/dist/public/node/session.js +56 -9
  90. package/dist/public/node/session.js.map +1 -1
  91. package/dist/public/node/system.d.ts +4 -0
  92. package/dist/public/node/system.js +39 -9
  93. package/dist/public/node/system.js.map +1 -1
  94. package/dist/public/node/themes/api.d.ts +9 -0
  95. package/dist/public/node/themes/api.js +50 -22
  96. package/dist/public/node/themes/api.js.map +1 -1
  97. package/dist/public/node/themes/theme-manager.d.ts +8 -1
  98. package/dist/public/node/themes/theme-manager.js +1 -1
  99. package/dist/public/node/themes/theme-manager.js.map +1 -1
  100. package/dist/public/node/tree-kill.js +12 -2
  101. package/dist/public/node/tree-kill.js.map +1 -1
  102. package/dist/public/node/ui/components.d.ts +1 -0
  103. package/dist/public/node/ui/components.js +1 -0
  104. package/dist/public/node/ui/components.js.map +1 -1
  105. package/dist/public/node/ui.d.ts +24 -4
  106. package/dist/public/node/ui.js +54 -21
  107. package/dist/public/node/ui.js.map +1 -1
  108. package/dist/public/node/upgrade/output.d.ts +17 -0
  109. package/dist/public/node/upgrade/output.js +51 -0
  110. package/dist/public/node/upgrade/output.js.map +1 -0
  111. package/dist/public/node/upgrade/result.d.ts +8 -0
  112. package/dist/public/node/upgrade/result.js +21 -0
  113. package/dist/public/node/upgrade/result.js.map +1 -0
  114. package/dist/public/node/upgrade/types.d.ts +61 -0
  115. package/dist/public/node/upgrade/types.js +46 -0
  116. package/dist/public/node/upgrade/types.js.map +1 -0
  117. package/dist/public/node/upgrade.d.ts +8 -0
  118. package/dist/public/node/upgrade.js +57 -22
  119. package/dist/public/node/upgrade.js.map +1 -1
  120. package/dist/tsconfig.tsbuildinfo +1 -1
  121. package/package.json +3 -3
  122. package/dist/private/node/ui/components/TextAnimation.d.ts +0 -10
  123. package/dist/private/node/ui/components/TextAnimation.js +0 -56
  124. package/dist/private/node/ui/components/TextAnimation.js.map +0 -1
  125. package/dist/private/node/ui/components/TextAnimation.test.d.ts +0 -1
  126. package/dist/private/node/ui/components/TextAnimation.test.js +0 -73
  127. package/dist/private/node/ui/components/TextAnimation.test.js.map +0 -1
@@ -30,24 +30,24 @@ export declare const JsonAbortErrorSchema: zod.ZodObject<{
30
30
  type: "abort";
31
31
  message: string;
32
32
  code?: string | undefined;
33
+ tryMessage?: string | undefined;
33
34
  nextSteps?: string[] | undefined;
34
35
  customSections?: {
35
36
  body: string | string[][];
36
37
  title?: string | undefined;
37
38
  }[] | undefined;
38
39
  details?: unknown;
39
- tryMessage?: string | undefined;
40
40
  }, {
41
41
  type: "abort";
42
42
  message: string;
43
43
  code?: string | undefined;
44
+ tryMessage?: string | undefined;
44
45
  nextSteps?: string[] | undefined;
45
46
  customSections?: {
46
47
  body: string | string[][];
47
48
  title?: string | undefined;
48
49
  }[] | undefined;
49
50
  details?: unknown;
50
- tryMessage?: string | undefined;
51
51
  }>;
52
52
  export declare const JsonBugErrorSchema: zod.ZodObject<{
53
53
  stack: zod.ZodOptional<zod.ZodString>;
@@ -71,6 +71,7 @@ export declare const JsonBugErrorSchema: zod.ZodObject<{
71
71
  type: "bug";
72
72
  message: string;
73
73
  code?: string | undefined;
74
+ tryMessage?: string | undefined;
74
75
  stack?: string | undefined;
75
76
  nextSteps?: string[] | undefined;
76
77
  customSections?: {
@@ -78,11 +79,11 @@ export declare const JsonBugErrorSchema: zod.ZodObject<{
78
79
  title?: string | undefined;
79
80
  }[] | undefined;
80
81
  details?: unknown;
81
- tryMessage?: string | undefined;
82
82
  }, {
83
83
  type: "bug";
84
84
  message: string;
85
85
  code?: string | undefined;
86
+ tryMessage?: string | undefined;
86
87
  stack?: string | undefined;
87
88
  nextSteps?: string[] | undefined;
88
89
  customSections?: {
@@ -90,7 +91,6 @@ export declare const JsonBugErrorSchema: zod.ZodObject<{
90
91
  title?: string | undefined;
91
92
  }[] | undefined;
92
93
  details?: unknown;
93
- tryMessage?: string | undefined;
94
94
  }>;
95
95
  export declare const JsonExternalErrorSchema: zod.ZodObject<{
96
96
  command: zod.ZodString;
@@ -117,26 +117,26 @@ export declare const JsonExternalErrorSchema: zod.ZodObject<{
117
117
  command: string;
118
118
  args: string[];
119
119
  code?: string | undefined;
120
+ tryMessage?: string | undefined;
120
121
  nextSteps?: string[] | undefined;
121
122
  customSections?: {
122
123
  body: string | string[][];
123
124
  title?: string | undefined;
124
125
  }[] | undefined;
125
126
  details?: unknown;
126
- tryMessage?: string | undefined;
127
127
  }, {
128
128
  type: "external";
129
129
  message: string;
130
130
  command: string;
131
131
  args: string[];
132
132
  code?: string | undefined;
133
+ tryMessage?: string | undefined;
133
134
  nextSteps?: string[] | undefined;
134
135
  customSections?: {
135
136
  body: string | string[][];
136
137
  title?: string | undefined;
137
138
  }[] | undefined;
138
139
  details?: unknown;
139
- tryMessage?: string | undefined;
140
140
  }>;
141
141
  export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
142
142
  message: zod.ZodString;
@@ -159,24 +159,24 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
159
159
  type: "abort";
160
160
  message: string;
161
161
  code?: string | undefined;
162
+ tryMessage?: string | undefined;
162
163
  nextSteps?: string[] | undefined;
163
164
  customSections?: {
164
165
  body: string | string[][];
165
166
  title?: string | undefined;
166
167
  }[] | undefined;
167
168
  details?: unknown;
168
- tryMessage?: string | undefined;
169
169
  }, {
170
170
  type: "abort";
171
171
  message: string;
172
172
  code?: string | undefined;
173
+ tryMessage?: string | undefined;
173
174
  nextSteps?: string[] | undefined;
174
175
  customSections?: {
175
176
  body: string | string[][];
176
177
  title?: string | undefined;
177
178
  }[] | undefined;
178
179
  details?: unknown;
179
- tryMessage?: string | undefined;
180
180
  }>, zod.ZodObject<{
181
181
  stack: zod.ZodOptional<zod.ZodString>;
182
182
  message: zod.ZodString;
@@ -199,6 +199,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
199
199
  type: "bug";
200
200
  message: string;
201
201
  code?: string | undefined;
202
+ tryMessage?: string | undefined;
202
203
  stack?: string | undefined;
203
204
  nextSteps?: string[] | undefined;
204
205
  customSections?: {
@@ -206,11 +207,11 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
206
207
  title?: string | undefined;
207
208
  }[] | undefined;
208
209
  details?: unknown;
209
- tryMessage?: string | undefined;
210
210
  }, {
211
211
  type: "bug";
212
212
  message: string;
213
213
  code?: string | undefined;
214
+ tryMessage?: string | undefined;
214
215
  stack?: string | undefined;
215
216
  nextSteps?: string[] | undefined;
216
217
  customSections?: {
@@ -218,7 +219,6 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
218
219
  title?: string | undefined;
219
220
  }[] | undefined;
220
221
  details?: unknown;
221
- tryMessage?: string | undefined;
222
222
  }>, zod.ZodObject<{
223
223
  command: zod.ZodString;
224
224
  args: zod.ZodArray<zod.ZodString, "many">;
@@ -244,26 +244,26 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
244
244
  command: string;
245
245
  args: string[];
246
246
  code?: string | undefined;
247
+ tryMessage?: string | undefined;
247
248
  nextSteps?: string[] | undefined;
248
249
  customSections?: {
249
250
  body: string | string[][];
250
251
  title?: string | undefined;
251
252
  }[] | undefined;
252
253
  details?: unknown;
253
- tryMessage?: string | undefined;
254
254
  }, {
255
255
  type: "external";
256
256
  message: string;
257
257
  command: string;
258
258
  args: string[];
259
259
  code?: string | undefined;
260
+ tryMessage?: string | undefined;
260
261
  nextSteps?: string[] | undefined;
261
262
  customSections?: {
262
263
  body: string | string[][];
263
264
  title?: string | undefined;
264
265
  }[] | undefined;
265
266
  details?: unknown;
266
- tryMessage?: string | undefined;
267
267
  }>]>;
268
268
  export declare const jsonErrorOutputSchema: import("../json-output-schema.js").JsonOutputSchema<zod.ZodObject<{
269
269
  error: zod.ZodUnion<[zod.ZodObject<{
@@ -287,24 +287,24 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
287
287
  type: "abort";
288
288
  message: string;
289
289
  code?: string | undefined;
290
+ tryMessage?: string | undefined;
290
291
  nextSteps?: string[] | undefined;
291
292
  customSections?: {
292
293
  body: string | string[][];
293
294
  title?: string | undefined;
294
295
  }[] | undefined;
295
296
  details?: unknown;
296
- tryMessage?: string | undefined;
297
297
  }, {
298
298
  type: "abort";
299
299
  message: string;
300
300
  code?: string | undefined;
301
+ tryMessage?: string | undefined;
301
302
  nextSteps?: string[] | undefined;
302
303
  customSections?: {
303
304
  body: string | string[][];
304
305
  title?: string | undefined;
305
306
  }[] | undefined;
306
307
  details?: unknown;
307
- tryMessage?: string | undefined;
308
308
  }>, zod.ZodObject<{
309
309
  stack: zod.ZodOptional<zod.ZodString>;
310
310
  message: zod.ZodString;
@@ -327,6 +327,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
327
327
  type: "bug";
328
328
  message: string;
329
329
  code?: string | undefined;
330
+ tryMessage?: string | undefined;
330
331
  stack?: string | undefined;
331
332
  nextSteps?: string[] | undefined;
332
333
  customSections?: {
@@ -334,11 +335,11 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
334
335
  title?: string | undefined;
335
336
  }[] | undefined;
336
337
  details?: unknown;
337
- tryMessage?: string | undefined;
338
338
  }, {
339
339
  type: "bug";
340
340
  message: string;
341
341
  code?: string | undefined;
342
+ tryMessage?: string | undefined;
342
343
  stack?: string | undefined;
343
344
  nextSteps?: string[] | undefined;
344
345
  customSections?: {
@@ -346,7 +347,6 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
346
347
  title?: string | undefined;
347
348
  }[] | undefined;
348
349
  details?: unknown;
349
- tryMessage?: string | undefined;
350
350
  }>, zod.ZodObject<{
351
351
  command: zod.ZodString;
352
352
  args: zod.ZodArray<zod.ZodString, "many">;
@@ -372,43 +372,44 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
372
372
  command: string;
373
373
  args: string[];
374
374
  code?: string | undefined;
375
+ tryMessage?: string | undefined;
375
376
  nextSteps?: string[] | undefined;
376
377
  customSections?: {
377
378
  body: string | string[][];
378
379
  title?: string | undefined;
379
380
  }[] | undefined;
380
381
  details?: unknown;
381
- tryMessage?: string | undefined;
382
382
  }, {
383
383
  type: "external";
384
384
  message: string;
385
385
  command: string;
386
386
  args: string[];
387
387
  code?: string | undefined;
388
+ tryMessage?: string | undefined;
388
389
  nextSteps?: string[] | undefined;
389
390
  customSections?: {
390
391
  body: string | string[][];
391
392
  title?: string | undefined;
392
393
  }[] | undefined;
393
394
  details?: unknown;
394
- tryMessage?: string | undefined;
395
395
  }>]>;
396
396
  }, "strict", zod.ZodTypeAny, {
397
397
  error: {
398
398
  type: "abort";
399
399
  message: string;
400
400
  code?: string | undefined;
401
+ tryMessage?: string | undefined;
401
402
  nextSteps?: string[] | undefined;
402
403
  customSections?: {
403
404
  body: string | string[][];
404
405
  title?: string | undefined;
405
406
  }[] | undefined;
406
407
  details?: unknown;
407
- tryMessage?: string | undefined;
408
408
  } | {
409
409
  type: "bug";
410
410
  message: string;
411
411
  code?: string | undefined;
412
+ tryMessage?: string | undefined;
412
413
  stack?: string | undefined;
413
414
  nextSteps?: string[] | undefined;
414
415
  customSections?: {
@@ -416,37 +417,37 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
416
417
  title?: string | undefined;
417
418
  }[] | undefined;
418
419
  details?: unknown;
419
- tryMessage?: string | undefined;
420
420
  } | {
421
421
  type: "external";
422
422
  message: string;
423
423
  command: string;
424
424
  args: string[];
425
425
  code?: string | undefined;
426
+ tryMessage?: string | undefined;
426
427
  nextSteps?: string[] | undefined;
427
428
  customSections?: {
428
429
  body: string | string[][];
429
430
  title?: string | undefined;
430
431
  }[] | undefined;
431
432
  details?: unknown;
432
- tryMessage?: string | undefined;
433
433
  };
434
434
  }, {
435
435
  error: {
436
436
  type: "abort";
437
437
  message: string;
438
438
  code?: string | undefined;
439
+ tryMessage?: string | undefined;
439
440
  nextSteps?: string[] | undefined;
440
441
  customSections?: {
441
442
  body: string | string[][];
442
443
  title?: string | undefined;
443
444
  }[] | undefined;
444
445
  details?: unknown;
445
- tryMessage?: string | undefined;
446
446
  } | {
447
447
  type: "bug";
448
448
  message: string;
449
449
  code?: string | undefined;
450
+ tryMessage?: string | undefined;
450
451
  stack?: string | undefined;
451
452
  nextSteps?: string[] | undefined;
452
453
  customSections?: {
@@ -454,19 +455,18 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
454
455
  title?: string | undefined;
455
456
  }[] | undefined;
456
457
  details?: unknown;
457
- tryMessage?: string | undefined;
458
458
  } | {
459
459
  type: "external";
460
460
  message: string;
461
461
  command: string;
462
462
  args: string[];
463
463
  code?: string | undefined;
464
+ tryMessage?: string | undefined;
464
465
  nextSteps?: string[] | undefined;
465
466
  customSections?: {
466
467
  body: string | string[][];
467
468
  title?: string | undefined;
468
469
  }[] | undefined;
469
470
  details?: unknown;
470
- tryMessage?: string | undefined;
471
471
  };
472
472
  }>>;
@@ -0,0 +1,8 @@
1
+ import type { JsonError } from './types.js';
2
+ /**
3
+ * Projects an error into the shared JSON error contract, retaining only allowlisted fields.
4
+ *
5
+ * @param source - Error to project.
6
+ * @returns The error classification, message, and available recovery information.
7
+ */
8
+ export declare function errorToJson(source: unknown): JsonError;
@@ -0,0 +1,103 @@
1
+ import { FatalErrorType } from './index.js';
2
+ import { tokenItemToJsonString } from '../../../private/node/ui/components/token-item.js';
3
+ import { unstyled } from '../output.js';
4
+ function externalCommand(error) {
5
+ if (typeof error.command !== 'string' || !Array.isArray(error.args))
6
+ return;
7
+ if (!error.args.every((arg) => typeof arg === 'string'))
8
+ return;
9
+ return { command: error.command, args: error.args };
10
+ }
11
+ function jsonErrorType(error, external) {
12
+ if (error.type === FatalErrorType.Abort) {
13
+ return external ? 'external' : 'abort';
14
+ }
15
+ return 'bug';
16
+ }
17
+ function jsonTokenItem(token) {
18
+ if (token === null || token === undefined)
19
+ return;
20
+ try {
21
+ const message = tokenItemToJsonString(token);
22
+ return typeof message === 'string' ? unstyled(message) : undefined;
23
+ }
24
+ catch (error) {
25
+ if (error instanceof TypeError)
26
+ return undefined;
27
+ throw error;
28
+ }
29
+ }
30
+ function jsonTokenItems(items) {
31
+ if (!Array.isArray(items))
32
+ return;
33
+ const renderedItems = items.map(jsonTokenItem).filter((item) => item !== undefined);
34
+ return renderedItems.length > 0 ? renderedItems : undefined;
35
+ }
36
+ function jsonTable(data) {
37
+ if (!Array.isArray(data))
38
+ return;
39
+ return data
40
+ .filter((row) => Array.isArray(row))
41
+ .map((row) => row.map((cell) => jsonTokenItem(cell) ?? ''));
42
+ }
43
+ function jsonCustomSection(section) {
44
+ if (typeof section !== 'object' || section === null || !('body' in section))
45
+ return;
46
+ const title = 'title' in section && typeof section.title === 'string' ? unstyled(section.title) : undefined;
47
+ const sectionBody = section.body;
48
+ const body = typeof sectionBody === 'object' && sectionBody !== null && 'tabularData' in sectionBody
49
+ ? jsonTable(sectionBody.tabularData)
50
+ : jsonTokenItem(sectionBody);
51
+ if (body === undefined)
52
+ return;
53
+ return { ...(title ? { title } : {}), body };
54
+ }
55
+ function jsonCustomSections(sections) {
56
+ if (!Array.isArray(sections))
57
+ return;
58
+ const renderedSections = sections
59
+ .map(jsonCustomSection)
60
+ .filter((section) => section !== undefined);
61
+ return renderedSections.length > 0 ? renderedSections : undefined;
62
+ }
63
+ /**
64
+ * Projects an error into the shared JSON error contract, retaining only allowlisted fields.
65
+ *
66
+ * @param source - Error to project.
67
+ * @returns The error classification, message, and available recovery information.
68
+ */
69
+ export function errorToJson(source) {
70
+ const error = typeof source === 'object' && source !== null ? source : { message: source };
71
+ const external = externalCommand(error);
72
+ const type = jsonErrorType(error, external);
73
+ const formattedMessage = jsonTokenItem(error.formattedMessage);
74
+ const message = formattedMessage ?? (typeof error.message === 'string' ? unstyled(error.message) : 'Unknown error');
75
+ const tryMessage = jsonTokenItem(error.tryMessage);
76
+ const nextSteps = jsonTokenItems(error.nextSteps);
77
+ const customSections = jsonCustomSections(error.customSections);
78
+ const details = error.details;
79
+ const commonFields = {
80
+ message,
81
+ ...(typeof error.code === 'string' && error.code.length > 0 ? { code: error.code } : {}),
82
+ ...(tryMessage === undefined ? {} : { tryMessage }),
83
+ ...(nextSteps === undefined ? {} : { nextSteps }),
84
+ ...(customSections === undefined ? {} : { customSections }),
85
+ ...(details === undefined ? {} : { details }),
86
+ };
87
+ let jsonError;
88
+ if (type === 'bug') {
89
+ jsonError = {
90
+ type,
91
+ ...commonFields,
92
+ ...(typeof error.stack === 'string' ? { stack: unstyled(error.stack) } : {}),
93
+ };
94
+ }
95
+ else if (type === 'external' && external) {
96
+ jsonError = { type, ...commonFields, ...external };
97
+ }
98
+ else {
99
+ jsonError = { type: 'abort', ...commonFields };
100
+ }
101
+ return jsonError;
102
+ }
103
+ //# sourceMappingURL=serialization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialization.js","sourceRoot":"","sources":["../../../../src/public/node/error/serialization.ts"],"names":[],"mappings":"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","sourcesContent":["import {FatalErrorType} from './index.js'\nimport {tokenItemToJsonString, type TokenItem} from '../../../private/node/ui/components/token-item.js'\nimport {unstyled} from '../output.js'\nimport type {JsonError, JsonErrorCustomSection, JsonErrorType} from './types.js'\n\ninterface FatalErrorLike {\n type?: number\n message?: unknown\n formattedMessage?: unknown\n tryMessage?: unknown\n nextSteps?: unknown\n customSections?: unknown\n stack?: unknown\n command?: unknown\n args?: unknown\n details?: unknown\n code?: unknown\n}\n\ninterface ExternalCommand {\n command: string\n args: string[]\n}\n\nfunction externalCommand(error: FatalErrorLike): ExternalCommand | undefined {\n if (typeof error.command !== 'string' || !Array.isArray(error.args)) return\n if (!error.args.every((arg) => typeof arg === 'string')) return\n\n return {command: error.command, args: error.args}\n}\n\nfunction jsonErrorType(error: FatalErrorLike, external: ExternalCommand | undefined): JsonErrorType {\n if (error.type === FatalErrorType.Abort) {\n return external ? 'external' : 'abort'\n }\n return 'bug'\n}\n\nfunction jsonTokenItem(token: unknown): string | undefined {\n if (token === null || token === undefined) return\n\n try {\n const message = tokenItemToJsonString(token as TokenItem)\n return typeof message === 'string' ? unstyled(message) : undefined\n } catch (error) {\n if (error instanceof TypeError) return undefined\n throw error\n }\n}\n\nfunction jsonTokenItems(items: unknown): string[] | undefined {\n if (!Array.isArray(items)) return\n\n const renderedItems = items.map(jsonTokenItem).filter((item): item is string => item !== undefined)\n return renderedItems.length > 0 ? renderedItems : undefined\n}\n\nfunction jsonTable(data: unknown): string[][] | undefined {\n if (!Array.isArray(data)) return\n\n return data\n .filter((row): row is unknown[] => Array.isArray(row))\n .map((row) => row.map((cell) => jsonTokenItem(cell) ?? ''))\n}\n\nfunction jsonCustomSection(section: unknown): JsonErrorCustomSection | undefined {\n if (typeof section !== 'object' || section === null || !('body' in section)) return\n\n const title = 'title' in section && typeof section.title === 'string' ? unstyled(section.title) : undefined\n const sectionBody = section.body\n const body =\n typeof sectionBody === 'object' && sectionBody !== null && 'tabularData' in sectionBody\n ? jsonTable(sectionBody.tabularData)\n : jsonTokenItem(sectionBody)\n\n if (body === undefined) return\n return {...(title ? {title} : {}), body}\n}\n\nfunction jsonCustomSections(sections: unknown): JsonErrorCustomSection[] | undefined {\n if (!Array.isArray(sections)) return\n\n const renderedSections = sections\n .map(jsonCustomSection)\n .filter((section): section is JsonErrorCustomSection => section !== undefined)\n return renderedSections.length > 0 ? renderedSections : undefined\n}\n\n/**\n * Projects an error into the shared JSON error contract, retaining only allowlisted fields.\n *\n * @param source - Error to project.\n * @returns The error classification, message, and available recovery information.\n */\nexport function errorToJson(source: unknown): JsonError {\n const error: FatalErrorLike = typeof source === 'object' && source !== null ? source : {message: source}\n\n const external = externalCommand(error)\n const type = jsonErrorType(error, external)\n const formattedMessage = jsonTokenItem(error.formattedMessage)\n const message = formattedMessage ?? (typeof error.message === 'string' ? unstyled(error.message) : 'Unknown error')\n const tryMessage = jsonTokenItem(error.tryMessage)\n const nextSteps = jsonTokenItems(error.nextSteps)\n const customSections = jsonCustomSections(error.customSections)\n const details = error.details\n\n const commonFields = {\n message,\n ...(typeof error.code === 'string' && error.code.length > 0 ? {code: error.code} : {}),\n ...(tryMessage === undefined ? {} : {tryMessage}),\n ...(nextSteps === undefined ? {} : {nextSteps}),\n ...(customSections === undefined ? {} : {customSections}),\n ...(details === undefined ? {} : {details}),\n }\n\n let jsonError: JsonError\n if (type === 'bug') {\n jsonError = {\n type,\n ...commonFields,\n ...(typeof error.stack === 'string' ? {stack: unstyled(error.stack)} : {}),\n }\n } else if (type === 'external' && external) {\n jsonError = {type, ...commonFields, ...external}\n } else {\n jsonError = {type: 'abort', ...commonFields}\n }\n\n return jsonError\n}\n"]}
@@ -40,6 +40,22 @@ export function resolveGraphiQLKey(providedKey, apiSecret, storeFqdn) {
40
40
  return providedKey?.trim() || deriveGraphiQLKey(apiSecret, storeFqdn);
41
41
  }
42
42
  const require = createRequire(import.meta.url);
43
+ /**
44
+ * Serializes a value as JSON that is safe to place inside an inline `<script>` element.
45
+ * `JSON.stringify` alone leaves `<`, `>` and `&` as-is, so a value could close the script element early. Escaping
46
+ * them (and the U+2028/U+2029 line separators) as `\uXXXX` sequences keeps the JavaScript value identical.
47
+ *
48
+ * @param value - The value to serialize.
49
+ * @returns A JSON string that can be interpolated into an inline script.
50
+ */
51
+ function serializeForInlineScript(value) {
52
+ return JSON.stringify(value)
53
+ .replace(/</g, '\\u003c')
54
+ .replace(/>/g, '\\u003e')
55
+ .replace(/&/g, '\\u0026')
56
+ .replace(/\u2028/g, '\\u2028')
57
+ .replace(/\u2029/g, '\\u2029');
58
+ }
43
59
  class TokenRefreshError extends AbortError {
44
60
  constructor() {
45
61
  super('Failed to refresh credentials. Check that your app is installed, and try again.');
@@ -152,8 +168,8 @@ export function setupGraphiQLServer(options) {
152
168
  }), {
153
169
  url,
154
170
  defaultQueries: [{ query: defaultQuery }],
155
- query: queryParam ? JSON.stringify(queryParam) : undefined,
156
- variables: variables ? JSON.stringify(variables) : undefined,
171
+ query: queryParam ? serializeForInlineScript(queryParam) : undefined,
172
+ variables: variables ? serializeForInlineScript(variables) : undefined,
157
173
  });
158
174
  }));
159
175
  router.post('/graphiql/graphql.json', defineEventHandler(async (event) => {
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/public/node/graphiql/server.ts"],"names":[],"mappings":"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","sourcesContent":["import {defaultQuery, graphiqlTemplate} from './templates/graphiql.js'\nimport {unauthorizedTemplate} from './templates/unauthorized.js'\nimport {filterCustomHeaders} from './utilities.js'\nimport {performActionWithRetryAfterRecovery} from '../../common/retry.js'\nimport {CLI_KIT_VERSION} from '../../common/version.js'\nimport {AbortError} from '../error.js'\nimport {adminUrl, supportedApiVersions} from '../api/admin.js'\nimport {fetch} from '../http.js'\nimport {renderLiquidTemplate} from '../liquid.js'\nimport {outputDebug} from '../output.js'\nimport {containsMutation} from '../graphql.js'\nimport {\n createApp,\n createRouter,\n defineEventHandler,\n getQuery,\n getRequestHeader,\n getRequestHeaders,\n readBody,\n setResponseHeader,\n setResponseStatus,\n toNodeListener,\n} from 'h3'\nimport {createHmac, randomBytes} from 'crypto'\nimport {createServer, Server} from 'http'\nimport {readFileSync} from 'fs'\nimport {Writable} from 'stream'\nimport {createRequire} from 'module'\n\n/**\n * Derives a deterministic GraphiQL authentication key from the app's API secret and store FQDN.\n * The key is stable across dev server restarts (so browser tabs survive restarts)\n * but is not guessable without the app secret.\n *\n * @param apiSecret - The Partners app's client secret used as the HMAC key.\n * @param storeFqdn - The myshopify.com domain the GraphiQL session targets.\n * @returns A 64-character hex string suitable for use as the `?key=` query param.\n */\nexport function deriveGraphiQLKey(apiSecret: string, storeFqdn: string): string {\n return createHmac('sha256', apiSecret).update(`graphiql:${storeFqdn}`).digest('hex')\n}\n\n/**\n * Resolves the GraphiQL authentication key. Uses the explicitly provided key\n * if non-empty, otherwise derives one deterministically from the app secret.\n *\n * @param providedKey - An explicit key supplied by the caller; takes precedence when non-empty.\n * @param apiSecret - The Partners app's client secret, used to derive a stable key as a fallback.\n * @param storeFqdn - The myshopify.com domain the GraphiQL session targets.\n * @returns The resolved key.\n */\nexport function resolveGraphiQLKey(providedKey: string | undefined, apiSecret: string, storeFqdn: string): string {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional: empty string after trim should fall through to deriveGraphiQLKey\n return providedKey?.trim() || deriveGraphiQLKey(apiSecret, storeFqdn)\n}\n\nconst require = createRequire(import.meta.url)\n\nclass TokenRefreshError extends AbortError {\n constructor() {\n super('Failed to refresh credentials. Check that your app is installed, and try again.')\n }\n}\n\n/**\n * Pluggable strategy for obtaining and refreshing the Admin API access token\n * that the GraphiQL proxy injects into every request.\n *\n * - `getToken` may return a cached token; the proxy calls it for every request.\n * - `refreshToken` (optional) is invoked when the upstream Admin API returns 401.\n * When omitted, the proxy falls back to calling `getToken` again on 401.\n *\n * Implementations must throw `TokenRefreshError` (or any thrown error) when the\n * token cannot be obtained; the proxy renders the unauthorized template in that case.\n */\nexport interface TokenProvider {\n getToken: () => Promise<string>\n refreshToken?: () => Promise<string>\n}\n\n/**\n * Optional app-specific context, used to render the app pill and scopes note in the\n * GraphiQL header and to drive the deterministic key derivation. Pass when the GraphiQL\n * server is hosted as part of `shopify app dev`; omit for app-less use cases such as\n * `shopify store execute`.\n */\nexport interface GraphiQLAppContext {\n appName: string\n appUrl: string\n apiSecret: string\n}\n\nexport interface SetupGraphiQLServerOptions {\n stdout: Writable\n port: number\n storeFqdn: string\n tokenProvider: TokenProvider\n /**\n * Authentication key required as a `?key=` query string on every request. When omitted:\n * - if `appContext` is provided, derived deterministically from `apiSecret` + `storeFqdn`\n * so browser tabs survive dev server restarts.\n * - otherwise, generated randomly per process.\n */\n key?: string\n appContext?: GraphiQLAppContext\n /**\n * When true, the proxy rejects mutation operations with HTTP 400 before forwarding\n * them to the Admin API. Use this to mirror non-interactive safety guarantees in the\n * interactive UI.\n */\n protectMutations?: boolean\n}\n\nexport const MUTATIONS_BLOCKED_MESSAGE = 'Mutations are disabled. Re-run with --allow-mutations to enable mutations.'\n\n/**\n * Starts a local HTTP server that hosts the GraphiQL UI and proxies requests to the\n * Admin API for the configured store. Authentication is delegated to the supplied\n * `tokenProvider`, so the same server can serve both `shopify app dev` and stored-session\n * use cases.\n *\n * @param options - Configuration for the server, including the target store, the\n * pluggable token provider, and the local port to bind to.\n * @returns The underlying Node `http.Server` instance, already listening on `options.port`.\n */\nexport function setupGraphiQLServer(options: SetupGraphiQLServerOptions): Server {\n const {stdout, port, storeFqdn, tokenProvider, key: providedKey, appContext, protectMutations = false} = options\n const key = resolveGraphiQLServerKey(providedKey, appContext, storeFqdn)\n outputDebug(`Setting up GraphiQL HTTP server on port ${port}...`, stdout)\n\n const app = createApp()\n const router = createRouter()\n\n const refreshUpstreamToken = async (): Promise<string> => {\n try {\n outputDebug('refreshing token', stdout)\n return await (tokenProvider.refreshToken ?? tokenProvider.getToken)()\n } catch (_error) {\n throw new TokenRefreshError()\n }\n }\n\n const currentToken = async (): Promise<string> => {\n try {\n return await tokenProvider.getToken()\n } catch (_error) {\n throw new TokenRefreshError()\n }\n }\n\n async function fetchApiVersionsWithTokenRefresh(): Promise<string[]> {\n return performActionWithRetryAfterRecovery(\n async () => supportedApiVersions({storeFqdn, token: await currentToken()}),\n refreshUpstreamToken,\n )\n }\n\n const faviconPath = require.resolve('../../../../assets/graphiql/favicon.ico')\n const faviconContent = readFileSync(faviconPath)\n const stylePath = require.resolve('../../../../assets/graphiql/style.css')\n const styleContent = readFileSync(stylePath, 'utf8')\n\n app.use(\n defineEventHandler((event) => {\n setResponseHeader(event, 'Access-Control-Allow-Origin', '*')\n setResponseHeader(event, 'Access-Control-Allow-Methods', 'GET, OPTIONS')\n setResponseHeader(\n event,\n 'Access-Control-Allow-Headers',\n 'Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, ngrok-skip-browser-warning',\n )\n }),\n )\n\n router.get(\n '/graphiql/ping',\n defineEventHandler(() => 'pong'),\n )\n\n router.get(\n '/graphiql/favicon.ico',\n defineEventHandler((event) => {\n setResponseHeader(event, 'Content-Type', 'image/x-icon')\n return faviconContent\n }),\n )\n\n router.get(\n '/graphiql/simple.css',\n defineEventHandler((event) => {\n setResponseHeader(event, 'Content-Type', 'text/css')\n return styleContent\n }),\n )\n\n router.get(\n '/graphiql/status',\n defineEventHandler(async () => {\n try {\n await fetchApiVersionsWithTokenRefresh()\n return {status: 'OK', storeFqdn, appName: appContext?.appName, appUrl: appContext?.appUrl}\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return {status: 'UNAUTHENTICATED'}\n }\n }),\n )\n\n router.get(\n '/graphiql',\n defineEventHandler(async (event) => {\n outputDebug('Handling /graphiql request', stdout)\n\n const query = getQuery(event)\n\n if (key && query.key !== key) {\n setResponseStatus(event, 404)\n return `Invalid path ${event.path}`\n }\n\n const forwardedProto = getRequestHeader(event, 'x-forwarded-proto')\n const usesHttps = forwardedProto === 'https'\n const host = getRequestHeader(event, 'host')\n const url = `http${usesHttps ? 's' : ''}://${host}`\n\n let apiVersions: string[]\n try {\n apiVersions = await fetchApiVersionsWithTokenRefresh()\n } catch (err) {\n if (err instanceof TokenRefreshError) {\n return renderLiquidTemplate(unauthorizedTemplate({hasAppContext: Boolean(appContext)}), {\n previewUrl: appContext?.appUrl ?? '',\n storeFqdn,\n url,\n })\n }\n throw err\n }\n\n const apiVersion = apiVersions.sort().reverse()[0]!\n\n function decodeQueryString(input: string | undefined) {\n return input ? decodeURIComponent(input).replace(/\\n/g, '\\\\n') : undefined\n }\n\n const queryParam = decodeQueryString(query.query as string | undefined)\n const variables = decodeQueryString(query.variables as string | undefined)\n\n return renderLiquidTemplate(\n graphiqlTemplate({\n apiVersion,\n apiVersions: [...apiVersions, 'unstable'],\n appName: appContext?.appName,\n appUrl: appContext?.appUrl,\n key,\n storeFqdn,\n protectMutations,\n }),\n {\n url,\n defaultQueries: [{query: defaultQuery}],\n query: queryParam ? JSON.stringify(queryParam) : undefined,\n variables: variables ? JSON.stringify(variables) : undefined,\n },\n )\n }),\n )\n\n router.post(\n '/graphiql/graphql.json',\n defineEventHandler(async (event) => {\n outputDebug('Handling /graphiql/graphql.json request', stdout)\n\n const query = getQuery(event)\n\n if (key && query.key !== key) {\n setResponseStatus(event, 404)\n return `Invalid path ${event.path}`\n }\n\n const graphqlUrl = adminUrl(storeFqdn, query.api_version as string)\n try {\n const body = await readBody(event)\n\n if (protectMutations && isMutationRequestBody(body)) {\n setResponseStatus(event, 400)\n return {errors: [{message: MUTATIONS_BLOCKED_MESSAGE}]}\n }\n\n const reqBody = JSON.stringify(body)\n\n const reqHeaders = getRequestHeaders(event)\n const customHeaders = filterCustomHeaders(reqHeaders)\n\n const runRequest = async (token: string) => {\n const headers = {\n ...customHeaders,\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Shopify-Access-Token': token,\n 'User-Agent': `ShopifyCLIGraphiQL/${CLI_KIT_VERSION}`,\n }\n\n return fetch(graphqlUrl, {\n method: 'POST',\n headers,\n body: reqBody,\n })\n }\n\n let result = await runRequest(await currentToken())\n if (result.status === 401) {\n outputDebug('Token expired, fetching new token', stdout)\n result = await runRequest(await refreshUpstreamToken())\n }\n\n setResponseHeader(event, 'Content-Type', 'application/json')\n setResponseStatus(event, result.status)\n return result.json()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error: unknown) {\n setResponseStatus(event, 500)\n if (error instanceof Error) {\n return {errors: [error.message]}\n }\n return {errors: ['Unknown error']}\n }\n }),\n )\n\n app.use(router)\n\n const server = createServer(toNodeListener(app))\n server.listen(port, 'localhost', () => stdout.write(`GraphiQL server started on port ${port}`))\n return server\n}\n\n// Picks the right key based on what the caller supplied:\n// - explicit non-empty key → use it\n// - app context with apiSecret → derive deterministically (stable across restarts)\n// - otherwise → random per-process key (browser tabs won't survive restarts, which is\n// the right tradeoff when there's no stable secret to derive from).\nfunction resolveGraphiQLServerKey(\n providedKey: string | undefined,\n appContext: GraphiQLAppContext | undefined,\n storeFqdn: string,\n): string {\n const trimmed = providedKey?.trim()\n if (trimmed) return trimmed\n if (appContext) return deriveGraphiQLKey(appContext.apiSecret, storeFqdn)\n return randomBytes(32).toString('hex')\n}\n\nfunction isMutationRequestBody(body: unknown): boolean {\n if (typeof body !== 'object' || body === null) return false\n const {query, operationName} = body as {query?: unknown; operationName?: unknown}\n if (typeof query !== 'string') return false\n return containsMutation(query, typeof operationName === 'string' ? operationName : undefined)\n}\n"]}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/public/node/graphiql/server.ts"],"names":[],"mappings":"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","sourcesContent":["import {defaultQuery, graphiqlTemplate} from './templates/graphiql.js'\nimport {unauthorizedTemplate} from './templates/unauthorized.js'\nimport {filterCustomHeaders} from './utilities.js'\nimport {performActionWithRetryAfterRecovery} from '../../common/retry.js'\nimport {CLI_KIT_VERSION} from '../../common/version.js'\nimport {AbortError} from '../error.js'\nimport {adminUrl, supportedApiVersions} from '../api/admin.js'\nimport {fetch} from '../http.js'\nimport {renderLiquidTemplate} from '../liquid.js'\nimport {outputDebug} from '../output.js'\nimport {containsMutation} from '../graphql.js'\nimport {\n createApp,\n createRouter,\n defineEventHandler,\n getQuery,\n getRequestHeader,\n getRequestHeaders,\n readBody,\n setResponseHeader,\n setResponseStatus,\n toNodeListener,\n} from 'h3'\nimport {createHmac, randomBytes} from 'crypto'\nimport {createServer, Server} from 'http'\nimport {readFileSync} from 'fs'\nimport {Writable} from 'stream'\nimport {createRequire} from 'module'\n\n/**\n * Derives a deterministic GraphiQL authentication key from the app's API secret and store FQDN.\n * The key is stable across dev server restarts (so browser tabs survive restarts)\n * but is not guessable without the app secret.\n *\n * @param apiSecret - The Partners app's client secret used as the HMAC key.\n * @param storeFqdn - The myshopify.com domain the GraphiQL session targets.\n * @returns A 64-character hex string suitable for use as the `?key=` query param.\n */\nexport function deriveGraphiQLKey(apiSecret: string, storeFqdn: string): string {\n return createHmac('sha256', apiSecret).update(`graphiql:${storeFqdn}`).digest('hex')\n}\n\n/**\n * Resolves the GraphiQL authentication key. Uses the explicitly provided key\n * if non-empty, otherwise derives one deterministically from the app secret.\n *\n * @param providedKey - An explicit key supplied by the caller; takes precedence when non-empty.\n * @param apiSecret - The Partners app's client secret, used to derive a stable key as a fallback.\n * @param storeFqdn - The myshopify.com domain the GraphiQL session targets.\n * @returns The resolved key.\n */\nexport function resolveGraphiQLKey(providedKey: string | undefined, apiSecret: string, storeFqdn: string): string {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional: empty string after trim should fall through to deriveGraphiQLKey\n return providedKey?.trim() || deriveGraphiQLKey(apiSecret, storeFqdn)\n}\n\nconst require = createRequire(import.meta.url)\n\n/**\n * Serializes a value as JSON that is safe to place inside an inline `<script>` element.\n * `JSON.stringify` alone leaves `<`, `>` and `&` as-is, so a value could close the script element early. Escaping\n * them (and the U+2028/U+2029 line separators) as `\\uXXXX` sequences keeps the JavaScript value identical.\n *\n * @param value - The value to serialize.\n * @returns A JSON string that can be interpolated into an inline script.\n */\nfunction serializeForInlineScript(value: unknown): string {\n return JSON.stringify(value)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029')\n}\n\nclass TokenRefreshError extends AbortError {\n constructor() {\n super('Failed to refresh credentials. Check that your app is installed, and try again.')\n }\n}\n\n/**\n * Pluggable strategy for obtaining and refreshing the Admin API access token\n * that the GraphiQL proxy injects into every request.\n *\n * - `getToken` may return a cached token; the proxy calls it for every request.\n * - `refreshToken` (optional) is invoked when the upstream Admin API returns 401.\n * When omitted, the proxy falls back to calling `getToken` again on 401.\n *\n * Implementations must throw `TokenRefreshError` (or any thrown error) when the\n * token cannot be obtained; the proxy renders the unauthorized template in that case.\n */\nexport interface TokenProvider {\n getToken: () => Promise<string>\n refreshToken?: () => Promise<string>\n}\n\n/**\n * Optional app-specific context, used to render the app pill and scopes note in the\n * GraphiQL header and to drive the deterministic key derivation. Pass when the GraphiQL\n * server is hosted as part of `shopify app dev`; omit for app-less use cases such as\n * `shopify store execute`.\n */\nexport interface GraphiQLAppContext {\n appName: string\n appUrl: string\n apiSecret: string\n}\n\nexport interface SetupGraphiQLServerOptions {\n stdout: Writable\n port: number\n storeFqdn: string\n tokenProvider: TokenProvider\n /**\n * Authentication key required as a `?key=` query string on every request. When omitted:\n * - if `appContext` is provided, derived deterministically from `apiSecret` + `storeFqdn`\n * so browser tabs survive dev server restarts.\n * - otherwise, generated randomly per process.\n */\n key?: string\n appContext?: GraphiQLAppContext\n /**\n * When true, the proxy rejects mutation operations with HTTP 400 before forwarding\n * them to the Admin API. Use this to mirror non-interactive safety guarantees in the\n * interactive UI.\n */\n protectMutations?: boolean\n}\n\nexport const MUTATIONS_BLOCKED_MESSAGE = 'Mutations are disabled. Re-run with --allow-mutations to enable mutations.'\n\n/**\n * Starts a local HTTP server that hosts the GraphiQL UI and proxies requests to the\n * Admin API for the configured store. Authentication is delegated to the supplied\n * `tokenProvider`, so the same server can serve both `shopify app dev` and stored-session\n * use cases.\n *\n * @param options - Configuration for the server, including the target store, the\n * pluggable token provider, and the local port to bind to.\n * @returns The underlying Node `http.Server` instance, already listening on `options.port`.\n */\nexport function setupGraphiQLServer(options: SetupGraphiQLServerOptions): Server {\n const {stdout, port, storeFqdn, tokenProvider, key: providedKey, appContext, protectMutations = false} = options\n const key = resolveGraphiQLServerKey(providedKey, appContext, storeFqdn)\n outputDebug(`Setting up GraphiQL HTTP server on port ${port}...`, stdout)\n\n const app = createApp()\n const router = createRouter()\n\n const refreshUpstreamToken = async (): Promise<string> => {\n try {\n outputDebug('refreshing token', stdout)\n return await (tokenProvider.refreshToken ?? tokenProvider.getToken)()\n } catch (_error) {\n throw new TokenRefreshError()\n }\n }\n\n const currentToken = async (): Promise<string> => {\n try {\n return await tokenProvider.getToken()\n } catch (_error) {\n throw new TokenRefreshError()\n }\n }\n\n async function fetchApiVersionsWithTokenRefresh(): Promise<string[]> {\n return performActionWithRetryAfterRecovery(\n async () => supportedApiVersions({storeFqdn, token: await currentToken()}),\n refreshUpstreamToken,\n )\n }\n\n const faviconPath = require.resolve('../../../../assets/graphiql/favicon.ico')\n const faviconContent = readFileSync(faviconPath)\n const stylePath = require.resolve('../../../../assets/graphiql/style.css')\n const styleContent = readFileSync(stylePath, 'utf8')\n\n app.use(\n defineEventHandler((event) => {\n setResponseHeader(event, 'Access-Control-Allow-Origin', '*')\n setResponseHeader(event, 'Access-Control-Allow-Methods', 'GET, OPTIONS')\n setResponseHeader(\n event,\n 'Access-Control-Allow-Headers',\n 'Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, ngrok-skip-browser-warning',\n )\n }),\n )\n\n router.get(\n '/graphiql/ping',\n defineEventHandler(() => 'pong'),\n )\n\n router.get(\n '/graphiql/favicon.ico',\n defineEventHandler((event) => {\n setResponseHeader(event, 'Content-Type', 'image/x-icon')\n return faviconContent\n }),\n )\n\n router.get(\n '/graphiql/simple.css',\n defineEventHandler((event) => {\n setResponseHeader(event, 'Content-Type', 'text/css')\n return styleContent\n }),\n )\n\n router.get(\n '/graphiql/status',\n defineEventHandler(async () => {\n try {\n await fetchApiVersionsWithTokenRefresh()\n return {status: 'OK', storeFqdn, appName: appContext?.appName, appUrl: appContext?.appUrl}\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return {status: 'UNAUTHENTICATED'}\n }\n }),\n )\n\n router.get(\n '/graphiql',\n defineEventHandler(async (event) => {\n outputDebug('Handling /graphiql request', stdout)\n\n const query = getQuery(event)\n\n if (key && query.key !== key) {\n setResponseStatus(event, 404)\n return `Invalid path ${event.path}`\n }\n\n const forwardedProto = getRequestHeader(event, 'x-forwarded-proto')\n const usesHttps = forwardedProto === 'https'\n const host = getRequestHeader(event, 'host')\n const url = `http${usesHttps ? 's' : ''}://${host}`\n\n let apiVersions: string[]\n try {\n apiVersions = await fetchApiVersionsWithTokenRefresh()\n } catch (err) {\n if (err instanceof TokenRefreshError) {\n return renderLiquidTemplate(unauthorizedTemplate({hasAppContext: Boolean(appContext)}), {\n previewUrl: appContext?.appUrl ?? '',\n storeFqdn,\n url,\n })\n }\n throw err\n }\n\n const apiVersion = apiVersions.sort().reverse()[0]!\n\n function decodeQueryString(input: string | undefined) {\n return input ? decodeURIComponent(input).replace(/\\n/g, '\\\\n') : undefined\n }\n\n const queryParam = decodeQueryString(query.query as string | undefined)\n const variables = decodeQueryString(query.variables as string | undefined)\n\n return renderLiquidTemplate(\n graphiqlTemplate({\n apiVersion,\n apiVersions: [...apiVersions, 'unstable'],\n appName: appContext?.appName,\n appUrl: appContext?.appUrl,\n key,\n storeFqdn,\n protectMutations,\n }),\n {\n url,\n defaultQueries: [{query: defaultQuery}],\n query: queryParam ? serializeForInlineScript(queryParam) : undefined,\n variables: variables ? serializeForInlineScript(variables) : undefined,\n },\n )\n }),\n )\n\n router.post(\n '/graphiql/graphql.json',\n defineEventHandler(async (event) => {\n outputDebug('Handling /graphiql/graphql.json request', stdout)\n\n const query = getQuery(event)\n\n if (key && query.key !== key) {\n setResponseStatus(event, 404)\n return `Invalid path ${event.path}`\n }\n\n const graphqlUrl = adminUrl(storeFqdn, query.api_version as string)\n try {\n const body = await readBody(event)\n\n if (protectMutations && isMutationRequestBody(body)) {\n setResponseStatus(event, 400)\n return {errors: [{message: MUTATIONS_BLOCKED_MESSAGE}]}\n }\n\n const reqBody = JSON.stringify(body)\n\n const reqHeaders = getRequestHeaders(event)\n const customHeaders = filterCustomHeaders(reqHeaders)\n\n const runRequest = async (token: string) => {\n const headers = {\n ...customHeaders,\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Shopify-Access-Token': token,\n 'User-Agent': `ShopifyCLIGraphiQL/${CLI_KIT_VERSION}`,\n }\n\n return fetch(graphqlUrl, {\n method: 'POST',\n headers,\n body: reqBody,\n })\n }\n\n let result = await runRequest(await currentToken())\n if (result.status === 401) {\n outputDebug('Token expired, fetching new token', stdout)\n result = await runRequest(await refreshUpstreamToken())\n }\n\n setResponseHeader(event, 'Content-Type', 'application/json')\n setResponseStatus(event, result.status)\n return result.json()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error: unknown) {\n setResponseStatus(event, 500)\n if (error instanceof Error) {\n return {errors: [error.message]}\n }\n return {errors: ['Unknown error']}\n }\n }),\n )\n\n app.use(router)\n\n const server = createServer(toNodeListener(app))\n server.listen(port, 'localhost', () => stdout.write(`GraphiQL server started on port ${port}`))\n return server\n}\n\n// Picks the right key based on what the caller supplied:\n// - explicit non-empty key → use it\n// - app context with apiSecret → derive deterministically (stable across restarts)\n// - otherwise → random per-process key (browser tabs won't survive restarts, which is\n// the right tradeoff when there's no stable secret to derive from).\nfunction resolveGraphiQLServerKey(\n providedKey: string | undefined,\n appContext: GraphiQLAppContext | undefined,\n storeFqdn: string,\n): string {\n const trimmed = providedKey?.trim()\n if (trimmed) return trimmed\n if (appContext) return deriveGraphiQLKey(appContext.apiSecret, storeFqdn)\n return randomBytes(32).toString('hex')\n}\n\nfunction isMutationRequestBody(body: unknown): boolean {\n if (typeof body !== 'object' || body === null) return false\n const {query, operationName} = body as {query?: unknown; operationName?: unknown}\n if (typeof query !== 'string') return false\n return containsMutation(query, typeof operationName === 'string' ? operationName : undefined)\n}\n"]}
@@ -48,9 +48,10 @@ export function currentProcessIsGlobal(argv = process.argv) {
48
48
  export async function installGlobalShopifyCLI(packageManager) {
49
49
  const { outputInfo } = await import('./output.js');
50
50
  const { exec } = await import('./system.js');
51
+ const { jsonOutputEnabled } = await import('./environment.js');
51
52
  const args = packageManager === 'yarn' ? ['global', 'add', '@shopify/cli@latest'] : ['install', '-g', '@shopify/cli@latest'];
52
53
  outputInfo(`Running ${packageManager} ${args.join(' ')}...`);
53
- await exec(packageManager, args, { stdio: 'inherit' });
54
+ await exec(packageManager, args, jsonOutputEnabled() ? {} : { stdio: 'inherit' });
54
55
  }
55
56
  /**
56
57
  * Prompts the user to install the global CLI.