@shopify/cli-kit 4.1.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/assets/graphiql/favicon.ico +0 -0
  2. package/assets/graphiql/style.css +58 -0
  3. package/dist/private/common/array.js +2 -1
  4. package/dist/private/common/array.js.map +1 -1
  5. package/dist/private/node/api/headers.js +6 -3
  6. package/dist/private/node/api/headers.js.map +1 -1
  7. package/dist/private/node/session/device-authorization.js +4 -16
  8. package/dist/private/node/session/device-authorization.js.map +1 -1
  9. package/dist/private/node/ui.js +4 -1
  10. package/dist/private/node/ui.js.map +1 -1
  11. package/dist/public/common/gid.d.ts +24 -0
  12. package/dist/public/common/gid.js +32 -0
  13. package/dist/public/common/gid.js.map +1 -0
  14. package/dist/public/common/url.d.ts +16 -0
  15. package/dist/public/common/url.js +30 -0
  16. package/dist/public/common/url.js.map +1 -1
  17. package/dist/public/common/version.d.ts +1 -1
  18. package/dist/public/common/version.js +1 -1
  19. package/dist/public/common/version.js.map +1 -1
  20. package/dist/public/node/analytics.js +3 -5
  21. package/dist/public/node/analytics.js.map +1 -1
  22. package/dist/public/node/cli.d.ts +13 -0
  23. package/dist/public/node/cli.js +12 -0
  24. package/dist/public/node/cli.js.map +1 -1
  25. package/dist/public/node/error-handler.js +1 -1
  26. package/dist/public/node/error-handler.js.map +1 -1
  27. package/dist/public/node/graphiql/server.d.ts +80 -0
  28. package/dist/public/node/graphiql/server.js +234 -0
  29. package/dist/public/node/graphiql/server.js.map +1 -0
  30. package/dist/public/node/graphiql/templates/graphiql.d.ts +12 -0
  31. package/dist/public/node/graphiql/templates/graphiql.js +314 -0
  32. package/dist/public/node/graphiql/templates/graphiql.js.map +1 -0
  33. package/dist/public/node/graphiql/templates/unauthorized.d.ts +5 -0
  34. package/dist/public/node/graphiql/templates/unauthorized.js +111 -0
  35. package/dist/public/node/graphiql/templates/unauthorized.js.map +1 -0
  36. package/dist/public/node/graphiql/utilities.d.ts +12 -0
  37. package/dist/public/node/graphiql/utilities.js +44 -0
  38. package/dist/public/node/graphiql/utilities.js.map +1 -0
  39. package/dist/public/node/graphql.d.ts +19 -0
  40. package/dist/public/node/graphql.js +41 -0
  41. package/dist/public/node/graphql.js.map +1 -0
  42. package/dist/public/node/hooks/postrun.js +12 -2
  43. package/dist/public/node/hooks/postrun.js.map +1 -1
  44. package/dist/public/node/http.js +27 -31
  45. package/dist/public/node/http.js.map +1 -1
  46. package/dist/public/node/metadata.d.ts +3 -0
  47. package/dist/public/node/metadata.js.map +1 -1
  48. package/dist/public/node/monorail.d.ts +2 -1
  49. package/dist/public/node/monorail.js +1 -1
  50. package/dist/public/node/monorail.js.map +1 -1
  51. package/dist/public/node/output.js +20 -11
  52. package/dist/public/node/output.js.map +1 -1
  53. package/dist/public/node/system.js +3 -0
  54. package/dist/public/node/system.js.map +1 -1
  55. package/dist/public/node/tcp.js +11 -3
  56. package/dist/public/node/tcp.js.map +1 -1
  57. package/dist/public/node/themes/api.js +76 -4
  58. package/dist/public/node/themes/api.js.map +1 -1
  59. package/dist/public/node/toml/toml-file.d.ts +3 -2
  60. package/dist/public/node/toml/toml-file.js +3 -2
  61. package/dist/public/node/toml/toml-file.js.map +1 -1
  62. package/dist/tsconfig.tsbuildinfo +1 -1
  63. package/package.json +34 -29
@@ -5,6 +5,7 @@ import { isTruthy } from './context/utilities.js';
5
5
  import { renderWarning } from './ui.js';
6
6
  import { platformAndArch } from './os.js';
7
7
  import { shouldDisplayColors, outputDebug } from './output.js';
8
+ import { isCloudEnvironment } from './context/local.js';
8
9
  import { execa } from 'execa';
9
10
  import supportsHyperlinks from 'supports-hyperlinks';
10
11
  import which from 'which';
@@ -23,6 +24,8 @@ const MAX_STDIN_SIZE = 10 * 1024 * 1024;
23
24
  * @returns A promise that resolves true if the URL was opened successfully, false otherwise.
24
25
  */
25
26
  export async function openURL(url) {
27
+ if (isCloudEnvironment())
28
+ return false;
26
29
  const externalOpen = await import('open');
27
30
  try {
28
31
  await externalOpen.default(url);
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/public/node/system.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,UAAU,EAAE,aAAa,EAAC,MAAM,YAAY,CAAA;AACpD,OAAO,EAAC,GAAG,EAAE,OAAO,EAAC,MAAM,WAAW,CAAA;AACtC,OAAO,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAA;AACvC,OAAO,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAA;AAC/C,OAAO,EAAC,aAAa,EAAC,MAAM,SAAS,CAAA;AACrC,OAAO,EAAC,eAAe,EAAC,MAAM,SAAS,CAAA;AACvC,OAAO,EAAC,mBAAmB,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AAC5D,OAAO,EAAC,KAAK,EAAoB,MAAM,OAAO,CAAA;AAC9C,OAAO,kBAAkB,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,SAAS,EAAC,MAAM,OAAO,CAAA;AAE/B,OAAO,EAAC,SAAS,EAAC,MAAM,IAAI,CAAA;AAG5B;;;;GAIG;AACH,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;AAyBvC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW;IACvC,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAA;IACzC,IAAI,CAAC;QACH,MAAM,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC/B,OAAO,IAAI,CAAA;QACX,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAe,EAAE,IAAc,EAAE,OAAqB;IACxF,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;IACtD,OAAO,MAAM,CAAC,MAAM,CAAA;AACtB,CAAC;AAcD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,OAAe,EACf,IAAc,EACd,OAAqB;IAErB,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAC,MAAM,EAAE,KAAK,EAAC,CAAC,CAAA;IACvE,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,CAAC;KAC/B,CAAA;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,YAAY,CAAC,OAAe;IACnC,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,IAAI,OAAO,GAAG,EAAE,CAAA;IAChB,IAAI,OAAO,GAAkB,IAAI,CAAA;IAEjC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,wBAAwB;gBACxB,OAAO,GAAG,IAAI,CAAA;YAChB,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,IAAI,CAAA;YACjB,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxC,0BAA0B;YAC1B,OAAO,GAAG,IAAI,CAAA;QAChB,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACzC,gDAAgD;YAChD,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACpB,OAAO,GAAG,EAAE,CAAA;YACd,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,IAAI,CAAA;QACjB,CAAC;IACH,CAAC;IAED,8BAA8B;IAC9B,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,OAAe,EAAE,OAAqB;IACrF,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,EAAC,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,EAAC,CAAA;IAC3D,CAAC;IACD,OAAO,yBAAyB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;AACtD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,OAAqB;IACtE,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,UAAU,CAAC,eAAe,CAAC,CAAA;IACvC,CAAC;IACD,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;AAChC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAe,EAAE,IAAc,EAAE,OAAqB;IAC/E,IAAI,OAAO,EAAE,CAAC;QACZ,iGAAiG;QACjG,MAAM,gBAAgB,GAAG,eAAe,EAAE,CAAC,QAAQ,KAAK,SAAS,CAAA;QACjE,OAAO,CAAC,UAAU,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAA;IACpE,CAAC;IAED,MAAM,cAAc,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;IAExD,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;QACxB,cAAc,CAAC,KAAK,EAAE,CAAA;IACxB,CAAC;IAED,IAAI,OAAO,EAAE,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACpD,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAC,GAAG,EAAE,KAAK,EAAC,CAAC,CAAA;IAC3D,CAAC;IACD,IAAI,OAAO,EAAE,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACpD,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAC,GAAG,EAAE,KAAK,EAAC,CAAC,CAAA;IAC3D,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;QAC9C,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAA;QAC9B,IAAI,GAAG,EAAE,CAAC;YACR,WAAW,CAAC,mBAAmB,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACnE,OAAO,GAAG,IAAI,CAAA;YACd,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC,CAAC,CAAA;IACF,IAAI,CAAC;QACH,MAAM,cAAc,CAAA;QACpB,8DAA8D;IAChE,CAAC;IAAC,OAAO,YAAiB,EAAE,CAAC;QAC3B,oFAAoF;QACpF,2EAA2E;QAC3E,IAAI,OAAO;YAAE,OAAM;QACnB,IAAI,OAAO,EAAE,oBAAoB,EAAE,CAAC;YAClC,MAAM,OAAO,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAA;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,IAAI,aAAa,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;YACzE,UAAU,CAAC,KAAK,GAAG,YAAY,CAAC,KAAK,CAAA;YACrC,MAAM,UAAU,CAAA;QAClB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,SAAS,CAChB,OAAe,EACf,IAAc,EACd,OAAqB,EACrB,YAA+B;IAE/B,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAA;IACvC,IAAI,mBAAmB,EAAE,EAAE,CAAC;QAC1B,GAAG,CAAC,WAAW,GAAG,GAAG,CAAA;IACvB,CAAC;IACD,MAAM,YAAY,GAAG,OAAO,EAAE,GAAG,IAAI,GAAG,EAAE,CAAA;IAC1C,kBAAkB,CAAC,OAAO,EAAE,EAAC,GAAG,EAAE,YAAY,EAAC,CAAC,CAAA;IAChD,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;QAC1C,GAAG;QACH,GAAG,EAAE,YAAY;QACjB,KAAK,EAAE,OAAO,EAAE,KAAK;QACrB,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK;QACtD,KAAK,EAAE,OAAO,EAAE,KAAK;QACrB,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC7D,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC7D,mEAAmE;QACnE,mDAAmD;QACnD,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE,OAAO,EAAE,UAAU;QAC7B,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU;QAC7B,GAAG,YAAY;KAChB,CAAC,CAAA;IACF,WAAW,CAAC,yBAAyB,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE;eACnE,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;yBACf,YAAY;CACpC,CAAC,CAAA;IACA,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAe,EAAE,QAAuB;IAClE,MAAM,kBAAkB,GAAG,GAAG,QAAQ,CAAC,GAAG,GAAG,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;IAC3E,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE;QACtC,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,kBAAkB;KACzB,CAAC,CAAA;IACF,IAAI,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,KAAK,QAAQ,CAAC,GAAG,EAAE,CAAC;QACzD,MAAM,QAAQ,GAAG,CAAC,gCAAgC,EAAE,EAAC,OAAO,EAAC,EAAE,iCAAiC,CAAC,CAAA;QACjG,MAAM,IAAI,GAAG,sDAAsD,CAAA;QACnE,aAAa,CAAC,EAAC,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAA;QAC/B,MAAM,IAAI,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACtC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,OAAe;IACzC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,UAAU,CAAC,OAAO,EAAE,IAAI,GAAG,OAAO,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B;IACxC,OAAO,kBAAkB,CAAC,MAAM,CAAA;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB;IACvC,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,IAAI;IAClB,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;IAClC,OAAO,GAAG,CAAC,OAAO,CAAA;AACpB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;QAC1B,OAAO,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,MAAM,EAAE,CAAA;QACvC,qDAAqD;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QACpB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,IAAI,IAAI,GAAG,EAAE,CAAA;IACb,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QACjC,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QACnD,IAAI,SAAS,GAAG,cAAc,EAAE,CAAC;YAC/B,MAAM,IAAI,UAAU,CAAC,gDAAgD,CAAC,CAAA;QACxE,CAAC;QACD,IAAI,IAAI,WAAW,CAAA;IACrB,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAA;AACpB,CAAC","sourcesContent":["import {AbortSignal} from './abort.js'\nimport {AbortError, ExternalError} from './error.js'\nimport {cwd, dirname} from './path.js'\nimport {treeKill} from './tree-kill.js'\nimport {isTruthy} from './context/utilities.js'\nimport {renderWarning} from './ui.js'\nimport {platformAndArch} from './os.js'\nimport {shouldDisplayColors, outputDebug} from './output.js'\nimport {execa, ExecaChildProcess} from 'execa'\nimport supportsHyperlinks from 'supports-hyperlinks'\nimport which from 'which'\nimport {delimiter} from 'pathe'\n\nimport {fstatSync} from 'fs'\nimport type {Writable, Readable} from 'stream'\n\n/**\n * The maximum size of data that can be read from stdin in bytes.\n * This is to prevent memory exhaustion when reading from stdin.\n * 10MB.\n */\nconst MAX_STDIN_SIZE = 10 * 1024 * 1024\n\nexport interface ExecOptions {\n cwd?: string\n env?: Record<string, string | undefined>\n stdin?: Readable | 'inherit'\n stdout?: Writable | 'inherit'\n stderr?: Writable | 'inherit'\n stdio?: 'inherit'\n input?: string\n signal?: AbortSignal\n // Custom handler if process exits with a non-zero code\n externalErrorHandler?: (error: unknown) => Promise<void>\n // Ignored on Windows\n background?: boolean\n}\n\n/**\n * Options passed directly to execa.\n */\ninterface BuildExecOptions {\n /** Whether to throw on non-zero exit codes (default: true). */\n reject?: boolean\n}\n\n/**\n * Opens a URL in the user's default browser.\n *\n * @param url - URL to open.\n * @returns A promise that resolves true if the URL was opened successfully, false otherwise.\n */\nexport async function openURL(url: string): Promise<boolean> {\n const externalOpen = await import('open')\n try {\n await externalOpen.default(url)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Runs a command asynchronously, aggregates the stdout data, and returns it.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with the aggregatted stdout of the command.\n */\nexport async function captureOutput(command: string, args: string[], options?: ExecOptions): Promise<string> {\n const result = await buildExec(command, args, options)\n return result.stdout\n}\n\n/**\n * Result from running a command with captureOutputWithExitCode.\n */\nexport interface CaptureOutputResult {\n /** Standard output. */\n stdout: string\n /** Standard error. */\n stderr: string\n /** Exit code (0 = success). */\n exitCode: number\n}\n\n/**\n * Runs a command asynchronously and returns stdout, stderr, and exit code.\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureOutputWithExitCode('ls', ['-la'])\n * if (result.exitCode !== 0) \\{\n * console.error('Command failed:', result.stderr)\n * \\}\n * ```\n */\nexport async function captureOutputWithExitCode(\n command: string,\n args: string[],\n options?: ExecOptions,\n): Promise<CaptureOutputResult> {\n const result = await buildExec(command, args, options, {reject: false})\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode ?? 0,\n }\n}\n\n/**\n * Parse a command string into an array of arguments, respecting quoted strings.\n * Handles both single and double quotes, preserving spaces within quoted sections.\n *\n * @param command - The command string to parse (e.g., 'ls -la \"my folder\"').\n * @returns An array of command parts with quotes removed.\n *\n * @example\n * parseCommand('shopify theme push --theme \"My Theme Name\"') // ['shopify', 'theme', 'push', '--theme', 'My Theme Name']\n */\nfunction parseCommand(command: string): string[] {\n const result: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (const char of command) {\n if (inQuote) {\n if (char === inQuote) {\n // End of quoted section\n inQuote = null\n } else {\n current += char\n }\n } else if (char === '\"' || char === \"'\") {\n // Start of quoted section\n inQuote = char\n } else if (char === ' ' || char === '\\t') {\n // Whitespace outside quotes - end current token\n if (current) {\n result.push(current)\n current = ''\n }\n } else {\n current += char\n }\n }\n\n // Don't forget the last token\n if (current) {\n result.push(current)\n }\n\n return result\n}\n\n/**\n * Runs a command string asynchronously and returns stdout, stderr, and exit code.\n * Parses the command string into command and arguments (handles quoted strings).\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureCommandWithExitCode('shopify theme push --theme \"My Theme\"')\n * if (result.exitCode !== 0) {\n * console.error('Command failed:', result.stderr)\n * }\n * ```\n */\nexport async function captureCommandWithExitCode(command: string, options?: ExecOptions): Promise<CaptureOutputResult> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n return {stdout: '', stderr: 'Empty command', exitCode: 1}\n }\n return captureOutputWithExitCode(cmd, args, options)\n}\n\n/**\n * Runs a command string asynchronously (parses command and arguments from the string).\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n */\nexport async function execCommand(command: string, options?: ExecOptions): Promise<void> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n throw new AbortError('Empty command')\n }\n await exec(cmd, args, options)\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n */\nexport async function exec(command: string, args: string[], options?: ExecOptions): Promise<void> {\n if (options) {\n // Windows opens a new console window when running a command in the background, so we disable it.\n const runningOnWindows = platformAndArch().platform === 'windows'\n options.background = runningOnWindows ? false : options.background\n }\n\n const commandProcess = buildExec(command, args, options)\n\n if (options?.background) {\n commandProcess.unref()\n }\n\n if (options?.stderr && options.stderr !== 'inherit') {\n commandProcess.stderr?.pipe(options.stderr, {end: false})\n }\n if (options?.stdout && options.stdout !== 'inherit') {\n commandProcess.stdout?.pipe(options.stdout, {end: false})\n }\n let aborted = false\n options?.signal?.addEventListener('abort', () => {\n const pid = commandProcess.pid\n if (pid) {\n outputDebug(`Killing process ${pid}: ${command} ${args.join(' ')}`)\n aborted = true\n treeKill(pid, 'SIGTERM')\n }\n })\n try {\n await commandProcess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (processError: any) {\n // Windows will throw an error whenever the process is killed, no matter the reason.\n // The aborted flag tell use that we killed it, so we can ignore the error.\n if (aborted) return\n if (options?.externalErrorHandler) {\n await options.externalErrorHandler(processError)\n } else {\n const abortError = new ExternalError(processError.message, command, args)\n abortError.stack = processError.stack\n throw abortError\n }\n }\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @param execaOptions - Options passed directly to execa.\n * @returns A promise for a result with stdout and stderr properties.\n */\nfunction buildExec(\n command: string,\n args: string[],\n options?: ExecOptions,\n execaOptions?: BuildExecOptions,\n): ExecaChildProcess {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n checkCommandSafety(command, {cwd: executionCwd})\n const commandProcess = execa(command, args, {\n env,\n cwd: executionCwd,\n input: options?.input,\n stdio: options?.background ? 'ignore' : options?.stdio,\n stdin: options?.stdin,\n stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,\n stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,\n // Setting this to false makes it possible to kill the main process\n // and all its sub-processes with Ctrl+C on Windows\n windowsHide: false,\n detached: options?.background,\n cleanup: !options?.background,\n ...execaOptions,\n })\n outputDebug(`Running system process${options?.background ? ' in background' : ''}:\n · Command: ${command} ${args.join(' ')}\n · Working directory: ${executionCwd}\n`)\n return commandProcess\n}\n\nfunction checkCommandSafety(command: string, _options: {cwd: string}): void {\n const pathIncludingLocal = `${_options.cwd}${delimiter}${process.env.PATH}`\n const commandPath = which.sync(command, {\n nothrow: true,\n path: pathIncludingLocal,\n })\n if (commandPath && dirname(commandPath) === _options.cwd) {\n const headline = ['Skipped run of unsecure binary', {command}, 'found in the current directory.']\n const body = 'Please remove that file or review your current PATH.'\n renderWarning({headline, body})\n throw new AbortError(headline, body)\n }\n}\n\n/**\n * Waits for a given number of seconds.\n *\n * @param seconds - Number of seconds to wait.\n * @returns A Promise resolving after the number of seconds.\n */\nexport async function sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, 1000 * seconds)\n })\n}\n\n/**\n * Check if the terminal supports OSC 8 hyperlinks.\n *\n * @returns True if the terminal supports hyperlinks.\n */\nexport function terminalSupportsHyperlinks(): boolean {\n return supportsHyperlinks.stdout\n}\n\n/**\n * Check if the standard input and output streams support prompting.\n *\n * @returns True if the standard input and output streams support prompting.\n */\nexport function terminalSupportsPrompting(): boolean {\n if (isTruthy(process.env.CI)) {\n return false\n }\n return Boolean(process.stdin.isTTY && process.stdout.isTTY)\n}\n\n/**\n * Check if the current environment is a CI environment.\n *\n * @returns True if the current environment is a CI environment.\n */\nexport function isCI(): boolean {\n return isTruthy(process.env.CI)\n}\n\n/**\n * Check if the current environment is a WSL environment.\n *\n * @returns True if the current environment is a WSL environment.\n */\nexport async function isWsl(): Promise<boolean> {\n const wsl = await import('is-wsl')\n return wsl.default\n}\n\n/**\n * Check if stdin has piped data available.\n * This distinguishes between actual piped input (e.g., `echo \"query\" | cmd`)\n * and non-TTY environments without input (e.g., CI).\n *\n * @returns True if stdin is receiving piped data or file redirect, false otherwise.\n */\nexport function isStdinPiped(): boolean {\n try {\n const stats = fstatSync(0)\n return stats.isFIFO() || stats.isFile()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * Reads all data from stdin and returns it as a string.\n * This is useful for commands that accept input via piping.\n *\n * @example\n * // Usage: echo \"your query\" | shopify app execute\n * const query = await readStdin()\n *\n * @returns A promise that resolves with the stdin content, or undefined if stdin is a TTY.\n */\nexport async function readStdinString(): Promise<string | undefined> {\n if (!isStdinPiped()) {\n return undefined\n }\n\n let data = ''\n let totalSize = 0\n process.stdin.setEncoding('utf8')\n for await (const chunk of process.stdin) {\n const chunkString = String(chunk)\n totalSize += Buffer.byteLength(chunkString, 'utf8')\n if (totalSize > MAX_STDIN_SIZE) {\n throw new AbortError('Stdin input exceeded the maximum allowed size.')\n }\n data += chunkString\n }\n return data.trim()\n}\n"]}
1
+ {"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/public/node/system.ts"],"names":[],"mappings":"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","sourcesContent":["import {AbortSignal} from './abort.js'\nimport {AbortError, ExternalError} from './error.js'\nimport {cwd, dirname} from './path.js'\nimport {treeKill} from './tree-kill.js'\nimport {isTruthy} from './context/utilities.js'\nimport {renderWarning} from './ui.js'\nimport {platformAndArch} from './os.js'\nimport {shouldDisplayColors, outputDebug} from './output.js'\nimport {isCloudEnvironment} from './context/local.js'\nimport {execa, ExecaChildProcess} from 'execa'\nimport supportsHyperlinks from 'supports-hyperlinks'\nimport which from 'which'\nimport {delimiter} from 'pathe'\n\nimport {fstatSync} from 'fs'\nimport type {Writable, Readable} from 'stream'\n\n/**\n * The maximum size of data that can be read from stdin in bytes.\n * This is to prevent memory exhaustion when reading from stdin.\n * 10MB.\n */\nconst MAX_STDIN_SIZE = 10 * 1024 * 1024\n\nexport interface ExecOptions {\n cwd?: string\n env?: Record<string, string | undefined>\n stdin?: Readable | 'inherit'\n stdout?: Writable | 'inherit'\n stderr?: Writable | 'inherit'\n stdio?: 'inherit'\n input?: string\n signal?: AbortSignal\n // Custom handler if process exits with a non-zero code\n externalErrorHandler?: (error: unknown) => Promise<void>\n // Ignored on Windows\n background?: boolean\n}\n\n/**\n * Options passed directly to execa.\n */\ninterface BuildExecOptions {\n /** Whether to throw on non-zero exit codes (default: true). */\n reject?: boolean\n}\n\n/**\n * Opens a URL in the user's default browser.\n *\n * @param url - URL to open.\n * @returns A promise that resolves true if the URL was opened successfully, false otherwise.\n */\nexport async function openURL(url: string): Promise<boolean> {\n if (isCloudEnvironment()) return false\n\n const externalOpen = await import('open')\n try {\n await externalOpen.default(url)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Runs a command asynchronously, aggregates the stdout data, and returns it.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with the aggregatted stdout of the command.\n */\nexport async function captureOutput(command: string, args: string[], options?: ExecOptions): Promise<string> {\n const result = await buildExec(command, args, options)\n return result.stdout\n}\n\n/**\n * Result from running a command with captureOutputWithExitCode.\n */\nexport interface CaptureOutputResult {\n /** Standard output. */\n stdout: string\n /** Standard error. */\n stderr: string\n /** Exit code (0 = success). */\n exitCode: number\n}\n\n/**\n * Runs a command asynchronously and returns stdout, stderr, and exit code.\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureOutputWithExitCode('ls', ['-la'])\n * if (result.exitCode !== 0) \\{\n * console.error('Command failed:', result.stderr)\n * \\}\n * ```\n */\nexport async function captureOutputWithExitCode(\n command: string,\n args: string[],\n options?: ExecOptions,\n): Promise<CaptureOutputResult> {\n const result = await buildExec(command, args, options, {reject: false})\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode ?? 0,\n }\n}\n\n/**\n * Parse a command string into an array of arguments, respecting quoted strings.\n * Handles both single and double quotes, preserving spaces within quoted sections.\n *\n * @param command - The command string to parse (e.g., 'ls -la \"my folder\"').\n * @returns An array of command parts with quotes removed.\n *\n * @example\n * parseCommand('shopify theme push --theme \"My Theme Name\"') // ['shopify', 'theme', 'push', '--theme', 'My Theme Name']\n */\nfunction parseCommand(command: string): string[] {\n const result: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (const char of command) {\n if (inQuote) {\n if (char === inQuote) {\n // End of quoted section\n inQuote = null\n } else {\n current += char\n }\n } else if (char === '\"' || char === \"'\") {\n // Start of quoted section\n inQuote = char\n } else if (char === ' ' || char === '\\t') {\n // Whitespace outside quotes - end current token\n if (current) {\n result.push(current)\n current = ''\n }\n } else {\n current += char\n }\n }\n\n // Don't forget the last token\n if (current) {\n result.push(current)\n }\n\n return result\n}\n\n/**\n * Runs a command string asynchronously and returns stdout, stderr, and exit code.\n * Parses the command string into command and arguments (handles quoted strings).\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureCommandWithExitCode('shopify theme push --theme \"My Theme\"')\n * if (result.exitCode !== 0) {\n * console.error('Command failed:', result.stderr)\n * }\n * ```\n */\nexport async function captureCommandWithExitCode(command: string, options?: ExecOptions): Promise<CaptureOutputResult> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n return {stdout: '', stderr: 'Empty command', exitCode: 1}\n }\n return captureOutputWithExitCode(cmd, args, options)\n}\n\n/**\n * Runs a command string asynchronously (parses command and arguments from the string).\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n */\nexport async function execCommand(command: string, options?: ExecOptions): Promise<void> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n throw new AbortError('Empty command')\n }\n await exec(cmd, args, options)\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n */\nexport async function exec(command: string, args: string[], options?: ExecOptions): Promise<void> {\n if (options) {\n // Windows opens a new console window when running a command in the background, so we disable it.\n const runningOnWindows = platformAndArch().platform === 'windows'\n options.background = runningOnWindows ? false : options.background\n }\n\n const commandProcess = buildExec(command, args, options)\n\n if (options?.background) {\n commandProcess.unref()\n }\n\n if (options?.stderr && options.stderr !== 'inherit') {\n commandProcess.stderr?.pipe(options.stderr, {end: false})\n }\n if (options?.stdout && options.stdout !== 'inherit') {\n commandProcess.stdout?.pipe(options.stdout, {end: false})\n }\n let aborted = false\n options?.signal?.addEventListener('abort', () => {\n const pid = commandProcess.pid\n if (pid) {\n outputDebug(`Killing process ${pid}: ${command} ${args.join(' ')}`)\n aborted = true\n treeKill(pid, 'SIGTERM')\n }\n })\n try {\n await commandProcess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (processError: any) {\n // Windows will throw an error whenever the process is killed, no matter the reason.\n // The aborted flag tell use that we killed it, so we can ignore the error.\n if (aborted) return\n if (options?.externalErrorHandler) {\n await options.externalErrorHandler(processError)\n } else {\n const abortError = new ExternalError(processError.message, command, args)\n abortError.stack = processError.stack\n throw abortError\n }\n }\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @param execaOptions - Options passed directly to execa.\n * @returns A promise for a result with stdout and stderr properties.\n */\nfunction buildExec(\n command: string,\n args: string[],\n options?: ExecOptions,\n execaOptions?: BuildExecOptions,\n): ExecaChildProcess {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n checkCommandSafety(command, {cwd: executionCwd})\n const commandProcess = execa(command, args, {\n env,\n cwd: executionCwd,\n input: options?.input,\n stdio: options?.background ? 'ignore' : options?.stdio,\n stdin: options?.stdin,\n stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,\n stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,\n // Setting this to false makes it possible to kill the main process\n // and all its sub-processes with Ctrl+C on Windows\n windowsHide: false,\n detached: options?.background,\n cleanup: !options?.background,\n ...execaOptions,\n })\n outputDebug(`Running system process${options?.background ? ' in background' : ''}:\n · Command: ${command} ${args.join(' ')}\n · Working directory: ${executionCwd}\n`)\n return commandProcess\n}\n\nfunction checkCommandSafety(command: string, _options: {cwd: string}): void {\n const pathIncludingLocal = `${_options.cwd}${delimiter}${process.env.PATH}`\n const commandPath = which.sync(command, {\n nothrow: true,\n path: pathIncludingLocal,\n })\n if (commandPath && dirname(commandPath) === _options.cwd) {\n const headline = ['Skipped run of unsecure binary', {command}, 'found in the current directory.']\n const body = 'Please remove that file or review your current PATH.'\n renderWarning({headline, body})\n throw new AbortError(headline, body)\n }\n}\n\n/**\n * Waits for a given number of seconds.\n *\n * @param seconds - Number of seconds to wait.\n * @returns A Promise resolving after the number of seconds.\n */\nexport async function sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, 1000 * seconds)\n })\n}\n\n/**\n * Check if the terminal supports OSC 8 hyperlinks.\n *\n * @returns True if the terminal supports hyperlinks.\n */\nexport function terminalSupportsHyperlinks(): boolean {\n return supportsHyperlinks.stdout\n}\n\n/**\n * Check if the standard input and output streams support prompting.\n *\n * @returns True if the standard input and output streams support prompting.\n */\nexport function terminalSupportsPrompting(): boolean {\n if (isTruthy(process.env.CI)) {\n return false\n }\n return Boolean(process.stdin.isTTY && process.stdout.isTTY)\n}\n\n/**\n * Check if the current environment is a CI environment.\n *\n * @returns True if the current environment is a CI environment.\n */\nexport function isCI(): boolean {\n return isTruthy(process.env.CI)\n}\n\n/**\n * Check if the current environment is a WSL environment.\n *\n * @returns True if the current environment is a WSL environment.\n */\nexport async function isWsl(): Promise<boolean> {\n const wsl = await import('is-wsl')\n return wsl.default\n}\n\n/**\n * Check if stdin has piped data available.\n * This distinguishes between actual piped input (e.g., `echo \"query\" | cmd`)\n * and non-TTY environments without input (e.g., CI).\n *\n * @returns True if stdin is receiving piped data or file redirect, false otherwise.\n */\nexport function isStdinPiped(): boolean {\n try {\n const stats = fstatSync(0)\n return stats.isFIFO() || stats.isFile()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * Reads all data from stdin and returns it as a string.\n * This is useful for commands that accept input via piping.\n *\n * @example\n * // Usage: echo \"your query\" | shopify app execute\n * const query = await readStdin()\n *\n * @returns A promise that resolves with the stdin content, or undefined if stdin is a TTY.\n */\nexport async function readStdinString(): Promise<string | undefined> {\n if (!isStdinPiped()) {\n return undefined\n }\n\n let data = ''\n let totalSize = 0\n process.stdin.setEncoding('utf8')\n for await (const chunk of process.stdin) {\n const chunkString = String(chunk)\n totalSize += Buffer.byteLength(chunkString, 'utf8')\n if (totalSize > MAX_STDIN_SIZE) {\n throw new AbortError('Stdin input exceeded the maximum allowed size.')\n }\n data += chunkString\n }\n return data.trim()\n}\n"]}
@@ -39,9 +39,17 @@ export async function checkPortAvailability(portNumber) {
39
39
  const server = createServer();
40
40
  server.unref();
41
41
  server.once('error', () => resolve(false));
42
- server.listen(portNumber, 'localhost', () => {
43
- server.close(() => resolve(true));
44
- });
42
+ try {
43
+ server.listen(portNumber, 'localhost', () => {
44
+ server.close(() => resolve(true));
45
+ });
46
+ }
47
+ catch (error) {
48
+ if (!(error instanceof RangeError)) {
49
+ throw error;
50
+ }
51
+ resolve(false);
52
+ }
45
53
  });
46
54
  }
47
55
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"tcp.js","sourceRoot":"","sources":["../../../src/public/node/tcp.ts"],"names":[],"mappings":"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","sourcesContent":["import {sleep} from './system.js'\nimport {AbortError} from './error.js'\nimport {outputDebug, outputContent, outputToken} from './output.js'\nimport {createServer} from 'net'\n\ninterface GetTCPPortOptions {\n waitTimeInSeconds?: number\n maxTries?: number\n}\n\nconst obtainedRandomPorts = new Set<number>()\n\n/**\n * Returns an available port in the current environment.\n *\n * @param preferredPort - Number of the preferred port to be used if available.\n * @param options - Extra configuration for getting TCP ports.\n * @returns A promise that resolves with an availabe port.\n */\nexport async function getAvailableTCPPort(preferredPort?: number, options?: GetTCPPortOptions): Promise<number> {\n if (preferredPort && (await checkPortAvailability(preferredPort))) {\n outputDebug(outputContent`Port ${preferredPort.toString()} is free`)\n return preferredPort\n }\n outputDebug(outputContent`Getting a random port...`)\n let randomPort = await retryOnError(() => getRandomPort(), options?.maxTries, options?.waitTimeInSeconds)\n\n for (let i = 0; i < (options?.maxTries ?? 5); i++) {\n if (!obtainedRandomPorts.has(randomPort)) {\n break\n }\n // eslint-disable-next-line no-await-in-loop\n randomPort = await retryOnError(() => getRandomPort(), options?.maxTries, options?.waitTimeInSeconds)\n }\n\n outputDebug(outputContent`Random port obtained: ${outputToken.raw(`${randomPort}`)}`)\n obtainedRandomPorts.add(randomPort)\n return randomPort\n}\n\n/**\n * Checks if a port is available.\n *\n * @param portNumber - The port number to check.\n * @returns A promise that resolves with a boolean indicating if the port is available.\n */\nexport async function checkPortAvailability(portNumber: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer()\n server.unref()\n server.once('error', () => resolve(false))\n server.listen(portNumber, 'localhost', () => {\n server.close(() => resolve(true))\n })\n })\n}\n\n/**\n * Gets a random available port by binding to port 0 on localhost.\n *\n * @returns A promise that resolves with an available port number.\n */\nfunction getRandomPort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = createServer()\n server.unref()\n server.once('error', reject)\n server.listen(0, 'localhost', () => {\n const address = server.address()\n if (address && typeof address === 'object') {\n const assignedPort = address.port\n server.close(() => resolve(assignedPort))\n } else {\n server.close(() => reject(new Error('Unable to determine assigned port')))\n }\n })\n })\n}\n\n/**\n * Given a function, it runs it and retries in case of failiure up to the provided number of times.\n *\n * @param execute - The function to execute.\n * @param maxTries - The maximum retries.\n * @param waitTimeInSeconds - The time to wait between retries.\n */\nasync function retryOnError<T>(execute: () => T, maxTries = 5, waitTimeInSeconds = 1) {\n let retryCount = 1\n while (true) {\n try {\n // eslint-disable-next-line no-await-in-loop\n return await execute()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n if (retryCount++ < maxTries) {\n outputDebug(outputContent`Unknown problem getting a random port: ${error.message}`)\n // eslint-disable-next-line no-await-in-loop\n await sleep(waitTimeInSeconds)\n } else {\n throw new AbortError(error.message)\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"tcp.js","sourceRoot":"","sources":["../../../src/public/node/tcp.ts"],"names":[],"mappings":"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","sourcesContent":["import {sleep} from './system.js'\nimport {AbortError} from './error.js'\nimport {outputDebug, outputContent, outputToken} from './output.js'\nimport {createServer} from 'net'\n\ninterface GetTCPPortOptions {\n waitTimeInSeconds?: number\n maxTries?: number\n}\n\nconst obtainedRandomPorts = new Set<number>()\n\n/**\n * Returns an available port in the current environment.\n *\n * @param preferredPort - Number of the preferred port to be used if available.\n * @param options - Extra configuration for getting TCP ports.\n * @returns A promise that resolves with an availabe port.\n */\nexport async function getAvailableTCPPort(preferredPort?: number, options?: GetTCPPortOptions): Promise<number> {\n if (preferredPort && (await checkPortAvailability(preferredPort))) {\n outputDebug(outputContent`Port ${preferredPort.toString()} is free`)\n return preferredPort\n }\n outputDebug(outputContent`Getting a random port...`)\n let randomPort = await retryOnError(() => getRandomPort(), options?.maxTries, options?.waitTimeInSeconds)\n\n for (let i = 0; i < (options?.maxTries ?? 5); i++) {\n if (!obtainedRandomPorts.has(randomPort)) {\n break\n }\n // eslint-disable-next-line no-await-in-loop\n randomPort = await retryOnError(() => getRandomPort(), options?.maxTries, options?.waitTimeInSeconds)\n }\n\n outputDebug(outputContent`Random port obtained: ${outputToken.raw(`${randomPort}`)}`)\n obtainedRandomPorts.add(randomPort)\n return randomPort\n}\n\n/**\n * Checks if a port is available.\n *\n * @param portNumber - The port number to check.\n * @returns A promise that resolves with a boolean indicating if the port is available.\n */\nexport async function checkPortAvailability(portNumber: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer()\n server.unref()\n server.once('error', () => resolve(false))\n try {\n server.listen(portNumber, 'localhost', () => {\n server.close(() => resolve(true))\n })\n } catch (error) {\n if (!(error instanceof RangeError)) {\n throw error\n }\n resolve(false)\n }\n })\n}\n\n/**\n * Gets a random available port by binding to port 0 on localhost.\n *\n * @returns A promise that resolves with an available port number.\n */\nfunction getRandomPort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = createServer()\n server.unref()\n server.once('error', reject)\n server.listen(0, 'localhost', () => {\n const address = server.address()\n if (address && typeof address === 'object') {\n const assignedPort = address.port\n server.close(() => resolve(assignedPort))\n } else {\n server.close(() => reject(new Error('Unable to determine assigned port')))\n }\n })\n })\n}\n\n/**\n * Given a function, it runs it and retries in case of failiure up to the provided number of times.\n *\n * @param execute - The function to execute.\n * @param maxTries - The maximum retries.\n * @param waitTimeInSeconds - The time to wait between retries.\n */\nasync function retryOnError<T>(execute: () => T, maxTries = 5, waitTimeInSeconds = 1) {\n let retryCount = 1\n while (true) {\n try {\n // eslint-disable-next-line no-await-in-loop\n return await execute()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n if (retryCount++ < maxTries) {\n outputDebug(outputContent`Unknown problem getting a random port: ${error.message}`)\n // eslint-disable-next-line no-await-in-loop\n await sleep(waitTimeInSeconds)\n } else {\n throw new AbortError(error.message)\n }\n }\n }\n}\n"]}
@@ -19,6 +19,7 @@ import { adminRequestDoc } from '../api/admin.js';
19
19
  import { AbortError } from '../error.js';
20
20
  import { outputDebug } from '../output.js';
21
21
  import { recordTiming, recordEvent, recordError } from '../analytics.js';
22
+ import { ClientError } from 'graphql-request';
22
23
  const SkeletonThemeCdn = 'https://cdn.shopify.com/static/online-store/theme-skeleton.zip';
23
24
  const THEME_API_NETWORK_BEHAVIOUR = {
24
25
  useNetworkLevelRetry: true,
@@ -26,6 +27,7 @@ const THEME_API_NETWORK_BEHAVIOUR = {
26
27
  maxRetryTimeMs: 90 * 1000,
27
28
  recordCommandRetries: true,
28
29
  };
30
+ const DEFAULT_THEME_ACCESS_REQUIREMENT = 'the required theme access scope';
29
31
  export async function fetchTheme(id, session) {
30
32
  const gid = composeThemeGid(id);
31
33
  recordEvent('theme-api:fetch-theme');
@@ -48,6 +50,7 @@ export async function fetchTheme(id, session) {
48
50
  // eslint-disable-next-line no-catch-all/no-catch-all
49
51
  }
50
52
  catch (error) {
53
+ abortIfMissingThemeAccessScope(error);
51
54
  /**
52
55
  * Consumers of this and other theme APIs in this file expect either a theme
53
56
  * or `undefined`.
@@ -65,7 +68,7 @@ export async function fetchThemes(session) {
65
68
  recordEvent('theme-api:fetch-themes');
66
69
  while (true) {
67
70
  // eslint-disable-next-line no-await-in-loop
68
- const response = await adminRequestDoc({
71
+ const response = await requestThemeAdminDoc({
69
72
  query: GetThemes,
70
73
  session,
71
74
  variables: { after },
@@ -95,7 +98,7 @@ export async function fetchThemes(session) {
95
98
  }
96
99
  export async function findDevelopmentThemeByName(name, session) {
97
100
  recordEvent('theme-api:find-development-theme-by-name');
98
- const { themes } = await adminRequestDoc({
101
+ const { themes } = await requestThemeAdminDoc({
99
102
  query: FindDevelopmentThemeByName,
100
103
  session,
101
104
  variables: { name },
@@ -155,7 +158,7 @@ export async function fetchThemeAssets(id, filenames, session) {
155
158
  recordEvent('theme-api:fetch-assets');
156
159
  while (true) {
157
160
  // eslint-disable-next-line no-await-in-loop
158
- const response = await adminRequestDoc({
161
+ const response = await requestThemeAdminDoc({
159
162
  query: GetThemeFileBodies,
160
163
  session,
161
164
  variables: { id: themeGid(id), filenames, after },
@@ -306,7 +309,7 @@ export async function fetchChecksums(id, session) {
306
309
  recordEvent('theme-api:fetch-checksums');
307
310
  while (true) {
308
311
  // eslint-disable-next-line no-await-in-loop
309
- const response = await adminRequestDoc({
312
+ const response = await requestThemeAdminDoc({
310
313
  query: GetThemeFileChecksums,
311
314
  session,
312
315
  variables: { id: themeGid(id), after },
@@ -493,6 +496,75 @@ export async function passwordProtected(session) {
493
496
  function unexpectedGraphQLError(message) {
494
497
  throw recordError(new AbortError(message));
495
498
  }
499
+ async function requestThemeAdminDoc(options) {
500
+ try {
501
+ const response = await adminRequestDoc(options);
502
+ return response;
503
+ }
504
+ catch (error) {
505
+ abortIfMissingThemeAccessScope(error);
506
+ throw error;
507
+ }
508
+ }
509
+ function abortIfMissingThemeAccessScope(error) {
510
+ if (!(error instanceof ClientError))
511
+ return;
512
+ const requiredAccess = getThemeAccessRequirementForAccessDeniedError(error);
513
+ if (!requiredAccess)
514
+ return;
515
+ const nextSteps = [
516
+ [
517
+ 'If you authenticated with an Admin API access token, update the app or integration that issued the token to include the required theme access scopes, then reauthorize it or generate a new token.',
518
+ ],
519
+ [
520
+ 'For',
521
+ { command: 'theme pull' },
522
+ { char: ',' },
523
+ { command: 'theme list' },
524
+ { char: ',' },
525
+ 'and',
526
+ { command: 'theme info' },
527
+ { char: ',' },
528
+ 'add the',
529
+ { command: 'read_themes' },
530
+ 'scope',
531
+ { char: '.' },
532
+ ],
533
+ [
534
+ 'For',
535
+ { command: 'theme push' },
536
+ 'and',
537
+ { command: 'theme dev' },
538
+ { char: ',' },
539
+ 'add both the',
540
+ { command: 'read_themes' },
541
+ 'and',
542
+ { command: 'write_themes' },
543
+ 'scopes',
544
+ { char: '.' },
545
+ ],
546
+ [
547
+ 'If you authenticated with your Shopify account, make sure your staff or collaborator account can access Online Store themes, then run',
548
+ { command: 'shopify auth logout' },
549
+ 'and try again',
550
+ { char: '.' },
551
+ ],
552
+ ['See', { link: { label: 'Shopify access scopes', url: 'https://shopify.dev/api/usage/access-scopes' } }, { char: '.' }],
553
+ ];
554
+ throw recordError(new AbortError(`The authenticated account or access token is missing ${requiredAccess}.`, undefined, nextSteps));
555
+ }
556
+ function getThemeAccessRequirementForAccessDeniedError(error) {
557
+ const graphQLErrors = error.response.errors;
558
+ if (!Array.isArray(graphQLErrors))
559
+ return undefined;
560
+ const accessDeniedError = graphQLErrors.find((graphQLError) => graphQLError.extensions?.code === 'ACCESS_DENIED');
561
+ if (!accessDeniedError)
562
+ return undefined;
563
+ const requiredAccess = accessDeniedError.extensions?.requiredAccess;
564
+ if (typeof requiredAccess !== 'string')
565
+ return DEFAULT_THEME_ACCESS_REQUIREMENT;
566
+ return requiredAccess.trim().replace(/\.$/, '') || DEFAULT_THEME_ACCESS_REQUIREMENT;
567
+ }
496
568
  function themeGid(id) {
497
569
  return `gid://shopify/OnlineStoreTheme/${id}`;
498
570
  }
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../src/public/node/themes/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {Result, Checksum, Key, Theme, ThemeAsset, Operation} from './types.js'\nimport {buildTheme} from './factories.js'\nimport {composeThemeGid, parseGid, DEVELOPMENT_THEME_ROLE} from './utils.js'\nimport {ThemeUpdate} from '../../../cli/api/graphql/admin/generated/theme_update.js'\nimport {ThemeDelete} from '../../../cli/api/graphql/admin/generated/theme_delete.js'\nimport {ThemeDuplicate} from '../../../cli/api/graphql/admin/generated/theme_duplicate.js'\nimport {ThemePublish} from '../../../cli/api/graphql/admin/generated/theme_publish.js'\nimport {ThemeCreate} from '../../../cli/api/graphql/admin/generated/theme_create.js'\nimport {GetThemeFileBodies} from '../../../cli/api/graphql/admin/generated/get_theme_file_bodies.js'\nimport {GetThemeFileChecksums} from '../../../cli/api/graphql/admin/generated/get_theme_file_checksums.js'\nimport {\n ThemeFilesUpsert,\n ThemeFilesUpsertMutation,\n} from '../../../cli/api/graphql/admin/generated/theme_files_upsert.js'\nimport {ThemeFilesDelete} from '../../../cli/api/graphql/admin/generated/theme_files_delete.js'\nimport {\n OnlineStoreThemeFileBodyInputType,\n OnlineStoreThemeFilesUpsertFileInput,\n MetafieldOwnerType,\n ThemeRole,\n} from '../../../cli/api/graphql/admin/generated/types.js'\nimport {MetafieldDefinitionsByOwnerType} from '../../../cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.js'\nimport {GetThemes} from '../../../cli/api/graphql/admin/generated/get_themes.js'\nimport {GetTheme} from '../../../cli/api/graphql/admin/generated/get_theme.js'\nimport {FindDevelopmentThemeByName} from '../../../cli/api/graphql/admin/generated/find_development_theme_by_name.js'\nimport {OnlineStorePasswordProtection} from '../../../cli/api/graphql/admin/generated/online_store_password_protection.js'\nimport {RequestModeInput} from '../http.js'\nimport {adminRequestDoc} from '../api/admin.js'\nimport {AdminSession} from '../session.js'\nimport {AbortError} from '../error.js'\nimport {outputDebug} from '../output.js'\nimport {recordTiming, recordEvent, recordError} from '../analytics.js'\n\nexport type ThemeParams = Partial<Pick<Theme, 'name' | 'role' | 'processing' | 'src'>>\nexport type AssetParams = Pick<ThemeAsset, 'key'> & Partial<Pick<ThemeAsset, 'value' | 'attachment'>>\nconst SkeletonThemeCdn = 'https://cdn.shopify.com/static/online-store/theme-skeleton.zip'\nconst THEME_API_NETWORK_BEHAVIOUR: RequestModeInput = {\n useNetworkLevelRetry: true,\n useAbortSignal: false,\n maxRetryTimeMs: 90 * 1000,\n recordCommandRetries: true,\n}\n\nexport async function fetchTheme(id: number, session: AdminSession): Promise<Theme | undefined> {\n const gid = composeThemeGid(id)\n recordEvent('theme-api:fetch-theme')\n\n try {\n const {theme} = await adminRequestDoc({\n query: GetTheme,\n session,\n variables: {id: gid},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (theme) {\n return buildTheme({\n id: parseGid(theme.id),\n processing: theme.processing,\n role: theme.role.toLowerCase(),\n name: theme.name,\n })\n }\n\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n /**\n * Consumers of this and other theme APIs in this file expect either a theme\n * or `undefined`.\n *\n * Error handlers should not inspect GraphQL error messages directly, as\n * they are internationalized.\n */\n recordError(error)\n outputDebug(`Error fetching theme with ID: ${id}`)\n }\n}\n\nexport async function fetchThemes(session: AdminSession): Promise<Theme[]> {\n const themes: Theme[] = []\n let after: string | null = null\n recordEvent('theme-api:fetch-themes')\n\n while (true) {\n // eslint-disable-next-line no-await-in-loop\n const response = await adminRequestDoc({\n query: GetThemes,\n session,\n variables: {after},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n if (!response.themes) {\n unexpectedGraphQLError('Failed to fetch themes')\n }\n const {nodes, pageInfo} = response.themes\n nodes.forEach((theme) => {\n const t = buildTheme({\n id: parseGid(theme.id),\n processing: theme.processing,\n role: theme.role.toLowerCase(),\n name: theme.name,\n })\n if (t) {\n themes.push(t)\n }\n })\n if (!pageInfo.hasNextPage) {\n return themes\n }\n\n after = pageInfo.endCursor as string\n }\n}\n\nexport async function findDevelopmentThemeByName(name: string, session: AdminSession): Promise<Theme | undefined> {\n recordEvent('theme-api:find-development-theme-by-name')\n\n const {themes} = await adminRequestDoc({\n query: FindDevelopmentThemeByName,\n session,\n variables: {name},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!themes) {\n unexpectedGraphQLError('Failed to fetch themes')\n }\n\n if (themes.nodes.length > 1) {\n throw recordError(new AbortError(`More than one development theme is named \"${name}\"`))\n }\n\n if (themes.nodes.length === 1) {\n const {id, processing, role, name} = themes.nodes[0]!\n\n return buildTheme({\n id: parseGid(id),\n processing,\n role: role.toLowerCase(),\n name,\n })\n }\n}\n\nexport async function themeCreate(params: ThemeParams, session: AdminSession): Promise<Theme | undefined> {\n const themeSource = params.src ?? SkeletonThemeCdn\n recordEvent('theme-api:create-theme')\n const {themeCreate} = await adminRequestDoc({\n query: ThemeCreate,\n session,\n variables: {\n name: params.name ?? '',\n source: themeSource,\n role: (params.role ?? DEVELOPMENT_THEME_ROLE).toUpperCase() as ThemeRole,\n },\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!themeCreate) {\n unexpectedGraphQLError('Failed to create theme')\n }\n\n const {theme, userErrors} = themeCreate\n if (userErrors.length) {\n const userErrors = themeCreate.userErrors.map((error) => error.message).join(', ')\n throw recordError(new AbortError(userErrors))\n }\n\n if (!theme) {\n unexpectedGraphQLError('Failed to create theme')\n }\n\n return buildTheme({\n id: parseGid(theme.id),\n name: theme.name,\n role: theme.role.toLowerCase(),\n })\n}\n\nexport async function fetchThemeAssets(id: number, filenames: Key[], session: AdminSession): Promise<ThemeAsset[]> {\n const assets: ThemeAsset[] = []\n let after: string | null = null\n recordEvent('theme-api:fetch-assets')\n\n while (true) {\n // eslint-disable-next-line no-await-in-loop\n const response = await adminRequestDoc({\n query: GetThemeFileBodies,\n session,\n variables: {id: themeGid(id), filenames, after},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!response.theme?.files?.nodes || !response.theme?.files?.pageInfo) {\n const userErrors = response.theme?.files?.userErrors.map((error) => error.filename).join(', ')\n unexpectedGraphQLError(`Error fetching assets: ${userErrors}`)\n }\n\n const {nodes, pageInfo} = response.theme.files\n\n assets.push(\n // eslint-disable-next-line no-await-in-loop\n ...(await Promise.all(\n nodes.map(async (file) => {\n const {attachment, value} = await parseThemeFileContent(file.body)\n return {\n attachment,\n key: file.filename,\n checksum: file.checksumMd5 as string,\n value,\n }\n }),\n )),\n )\n\n if (!pageInfo.hasNextPage) {\n return assets\n }\n\n after = pageInfo.endCursor as string\n }\n}\n\nexport async function deleteThemeAssets(id: number, filenames: Key[], session: AdminSession): Promise<Result[]> {\n const batchSize = 50\n const results: Result[] = []\n recordEvent('theme-api:delete-assets')\n\n for (let i = 0; i < filenames.length; i += batchSize) {\n const batch = filenames.slice(i, i + batchSize)\n // eslint-disable-next-line no-await-in-loop\n const {themeFilesDelete} = await adminRequestDoc({\n query: ThemeFilesDelete,\n session,\n variables: {\n themeId: composeThemeGid(id),\n files: batch,\n },\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!themeFilesDelete) {\n unexpectedGraphQLError('Failed to delete theme assets')\n }\n\n const {deletedThemeFiles, userErrors} = themeFilesDelete\n\n if (deletedThemeFiles) {\n deletedThemeFiles.forEach((file) => {\n results.push({key: file.filename, success: true, operation: Operation.Delete})\n })\n }\n\n if (userErrors.length > 0) {\n userErrors.forEach((error) => {\n if (error.filename) {\n recordError(`Asset deletion failed for ${error.filename}: ${error.message}`)\n results.push({\n key: error.filename,\n success: false,\n operation: Operation.Delete,\n errors: {asset: [error.message]},\n })\n } else {\n unexpectedGraphQLError(`Failed to delete theme assets: ${error.message}`)\n }\n })\n }\n }\n\n return results\n}\n\nexport async function bulkUploadThemeAssets(\n id: number,\n assets: AssetParams[],\n session: AdminSession,\n): Promise<Result[]> {\n const results: Result[] = []\n recordEvent('theme-api:bulk-upload-assets')\n for (let i = 0; i < assets.length; i += 50) {\n const chunk = assets.slice(i, i + 50)\n const files = prepareFilesForUpload(chunk)\n\n recordTiming('theme-api:upload-files')\n // eslint-disable-next-line no-await-in-loop\n const uploadResults = await uploadFiles(id, files, session)\n recordTiming('theme-api:upload-files')\n\n results.push(...processUploadResults(uploadResults))\n }\n return results\n}\n\nfunction prepareFilesForUpload(assets: AssetParams[]): OnlineStoreThemeFilesUpsertFileInput[] {\n return assets.map((asset) => {\n if (asset.attachment) {\n return {\n filename: asset.key,\n body: {\n type: 'BASE64' as const,\n value: asset.attachment,\n },\n }\n } else {\n return {\n filename: asset.key,\n body: {\n type: 'TEXT' as const,\n value: asset.value ?? '',\n },\n }\n }\n })\n}\n\nasync function uploadFiles(\n themeId: number,\n files: {filename: string; body: {type: OnlineStoreThemeFileBodyInputType; value: string}}[],\n session: AdminSession,\n): Promise<ThemeFilesUpsertMutation> {\n return adminRequestDoc({\n query: ThemeFilesUpsert,\n session,\n variables: {themeId: themeGid(themeId), files},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n}\n\nfunction processUploadResults(uploadResults: ThemeFilesUpsertMutation): Result[] {\n const {themeFilesUpsert} = uploadResults\n\n if (!themeFilesUpsert) {\n unexpectedGraphQLError('Failed to upload theme files')\n }\n\n const {upsertedThemeFiles, userErrors} = themeFilesUpsert\n\n const results: Result[] = []\n\n upsertedThemeFiles?.forEach((file) => {\n results.push({\n key: file.filename,\n success: true,\n operation: Operation.Upload,\n })\n })\n\n userErrors.forEach((error) => {\n if (!error.filename) {\n unexpectedGraphQLError(`Error uploading theme files: ${error.message}`)\n }\n recordError(`Asset upload failed for ${error.filename}: ${error.message}`)\n results.push({\n key: error.filename,\n success: false,\n operation: Operation.Upload,\n errors: {asset: [error.message]},\n })\n })\n\n return results\n}\n\nexport async function fetchChecksums(id: number, session: AdminSession): Promise<Checksum[]> {\n const checksums: Checksum[] = []\n let after: string | null = null\n recordEvent('theme-api:fetch-checksums')\n\n while (true) {\n // eslint-disable-next-line no-await-in-loop\n const response = await adminRequestDoc({\n query: GetThemeFileChecksums,\n session,\n variables: {id: themeGid(id), after},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!response?.theme?.files?.nodes || !response?.theme?.files?.pageInfo) {\n const userErrors = response.theme?.files?.userErrors.map((error) => error.filename).join(', ')\n throw recordError(new AbortError(`Failed to fetch checksums for: ${userErrors}`))\n }\n\n const {nodes, pageInfo} = response.theme.files\n\n checksums.push(\n ...nodes.map((file) => ({\n key: file.filename,\n checksum: file.checksumMd5 as string,\n })),\n )\n\n if (!pageInfo.hasNextPage) {\n return checksums\n }\n\n after = pageInfo.endCursor as string\n }\n}\n\nexport async function themeUpdate(id: number, params: ThemeParams, session: AdminSession): Promise<Theme | undefined> {\n const name = params.name\n const input: Record<string, string> = {}\n if (name) {\n input.name = name\n }\n recordEvent('theme-api:update-theme')\n\n const {themeUpdate} = await adminRequestDoc({\n query: ThemeUpdate,\n session,\n variables: {id: composeThemeGid(id), input},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n if (!themeUpdate) {\n // An unexpected error occurred during the GraphQL request execution\n unexpectedGraphQLError('Failed to update theme')\n }\n\n const {theme, userErrors} = themeUpdate\n if (userErrors.length) {\n const userErrors = themeUpdate.userErrors.map((error) => error.message).join(', ')\n throw recordError(new AbortError(userErrors))\n }\n\n if (!theme) {\n // An unexpected error if neither theme nor userErrors are returned\n unexpectedGraphQLError('Failed to update theme')\n }\n\n return buildTheme({\n id: parseGid(theme.id),\n name: theme.name,\n role: theme.role.toLowerCase(),\n })\n}\n\nexport async function themePublish(id: number, session: AdminSession): Promise<Theme | undefined> {\n recordEvent('theme-api:publish-theme')\n const {themePublish} = await adminRequestDoc({\n query: ThemePublish,\n session,\n variables: {id: composeThemeGid(id)},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n if (!themePublish) {\n // An unexpected error occurred during the GraphQL request execution\n unexpectedGraphQLError('Failed to update theme')\n }\n\n const {theme, userErrors} = themePublish\n if (userErrors.length) {\n const userErrors = themePublish.userErrors.map((error) => error.message).join(', ')\n throw recordError(new AbortError(userErrors))\n }\n\n if (!theme) {\n // An unexpected error if neither theme nor userErrors are returned\n unexpectedGraphQLError('Failed to update theme')\n }\n\n return buildTheme({\n id: parseGid(theme.id),\n name: theme.name,\n role: theme.role.toLowerCase(),\n })\n}\n\nexport async function themeDelete(id: number, session: AdminSession): Promise<boolean | undefined> {\n recordEvent('theme-api:delete-theme')\n const {themeDelete} = await adminRequestDoc({\n query: ThemeDelete,\n session,\n variables: {id: composeThemeGid(id)},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n if (!themeDelete) {\n // An unexpected error occurred during the GraphQL request execution\n unexpectedGraphQLError('Failed to update theme')\n }\n\n const {deletedThemeId, userErrors} = themeDelete\n if (userErrors.length) {\n const userErrors = themeDelete.userErrors.map((error) => error.message).join(', ')\n throw recordError(new AbortError(userErrors))\n }\n\n if (!deletedThemeId) {\n // An unexpected error if neither theme nor userErrors are returned\n unexpectedGraphQLError('Failed to update theme')\n }\n\n return true\n}\n\nexport interface ThemeDuplicateResult {\n theme?: Theme\n userErrors: {field?: string[] | null; message: string}[]\n requestId?: string\n}\n\nexport async function themeDuplicate(\n id: number,\n name: string | undefined,\n session: AdminSession,\n): Promise<ThemeDuplicateResult> {\n let requestId: string | undefined\n recordEvent('theme-api:duplicate-theme')\n\n const {themeDuplicate} = await adminRequestDoc({\n query: ThemeDuplicate,\n session,\n variables: {id: composeThemeGid(id), name},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n responseOptions: {\n onResponse: (response) => {\n requestId = response.headers.get('x-request-id') ?? undefined\n },\n },\n })\n\n if (!themeDuplicate) {\n // An unexpected error occurred during the GraphQL request execution\n recordError('Failed to duplicate theme')\n return {\n theme: undefined,\n userErrors: [{message: 'Failed to duplicate theme'}],\n requestId,\n }\n }\n\n const {newTheme, userErrors} = themeDuplicate\n\n if (userErrors.length > 0) {\n return {\n theme: undefined,\n userErrors,\n requestId,\n }\n }\n\n if (!newTheme) {\n // An unexpected error if neither theme nor userErrors are returned\n return {\n theme: undefined,\n userErrors: [{message: 'Failed to duplicate theme'}],\n requestId,\n }\n }\n\n const theme = buildTheme({\n id: parseGid(newTheme.id),\n name: newTheme.name,\n role: newTheme.role.toLowerCase(),\n })\n\n return {\n theme,\n userErrors: [],\n requestId,\n }\n}\n\nexport async function metafieldDefinitionsByOwnerType(type: MetafieldOwnerType, session: AdminSession) {\n recordEvent('theme-api:fetch-metafield-definitions')\n const {metafieldDefinitions} = await adminRequestDoc({\n query: MetafieldDefinitionsByOwnerType,\n session,\n variables: {ownerType: type},\n })\n\n return metafieldDefinitions.nodes.map((definition) => ({\n key: definition.key,\n namespace: definition.namespace,\n name: definition.name,\n description: definition.description,\n type: {\n name: definition.type.name,\n category: definition.type.category,\n },\n }))\n}\n\nexport async function passwordProtected(session: AdminSession): Promise<boolean> {\n recordEvent('theme-api:check-password-protection')\n const {onlineStore} = await adminRequestDoc({\n query: OnlineStorePasswordProtection,\n session,\n })\n if (!onlineStore) {\n unexpectedGraphQLError(\"Unable to get details about the storefront's password protection\")\n }\n\n const {passwordProtection} = onlineStore\n\n return passwordProtection.enabled\n}\n\nfunction unexpectedGraphQLError(message: string): never {\n throw recordError(new AbortError(message))\n}\n\nfunction themeGid(id: number): string {\n return `gid://shopify/OnlineStoreTheme/${id}`\n}\n\ntype OnlineStoreThemeFileBody =\n | {__typename: 'OnlineStoreThemeFileBodyBase64'; contentBase64: string}\n | {__typename: 'OnlineStoreThemeFileBodyText'; content: string}\n | {__typename: 'OnlineStoreThemeFileBodyUrl'; url: string}\n\nexport async function parseThemeFileContent(\n body: OnlineStoreThemeFileBody,\n): Promise<{value?: string; attachment?: string}> {\n switch (body.__typename) {\n case 'OnlineStoreThemeFileBodyText':\n return {value: body.content}\n case 'OnlineStoreThemeFileBodyBase64':\n return {attachment: body.contentBase64}\n case 'OnlineStoreThemeFileBodyUrl':\n try {\n // eslint-disable-next-line no-restricted-globals\n const response = await fetch(body.url)\n\n const arrayBuffer = await response.arrayBuffer()\n return {attachment: Buffer.from(arrayBuffer).toString('base64')}\n } catch (error) {\n // Raise error if we can't download the file\n throw recordError(new AbortError(`Error downloading content from URL: ${body.url}`))\n }\n }\n}\n"]}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../src/public/node/themes/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {Result, Checksum, Key, Theme, ThemeAsset, Operation} from './types.js'\nimport {buildTheme} from './factories.js'\nimport {composeThemeGid, parseGid, DEVELOPMENT_THEME_ROLE} from './utils.js'\nimport {ThemeUpdate} from '../../../cli/api/graphql/admin/generated/theme_update.js'\nimport {ThemeDelete} from '../../../cli/api/graphql/admin/generated/theme_delete.js'\nimport {ThemeDuplicate} from '../../../cli/api/graphql/admin/generated/theme_duplicate.js'\nimport {ThemePublish} from '../../../cli/api/graphql/admin/generated/theme_publish.js'\nimport {ThemeCreate} from '../../../cli/api/graphql/admin/generated/theme_create.js'\nimport {GetThemeFileBodies} from '../../../cli/api/graphql/admin/generated/get_theme_file_bodies.js'\nimport {GetThemeFileChecksums} from '../../../cli/api/graphql/admin/generated/get_theme_file_checksums.js'\nimport {\n ThemeFilesUpsert,\n ThemeFilesUpsertMutation,\n} from '../../../cli/api/graphql/admin/generated/theme_files_upsert.js'\nimport {ThemeFilesDelete} from '../../../cli/api/graphql/admin/generated/theme_files_delete.js'\nimport {\n OnlineStoreThemeFileBodyInputType,\n OnlineStoreThemeFilesUpsertFileInput,\n MetafieldOwnerType,\n ThemeRole,\n} from '../../../cli/api/graphql/admin/generated/types.js'\nimport {MetafieldDefinitionsByOwnerType} from '../../../cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.js'\nimport {GetThemes} from '../../../cli/api/graphql/admin/generated/get_themes.js'\nimport {GetTheme} from '../../../cli/api/graphql/admin/generated/get_theme.js'\nimport {FindDevelopmentThemeByName} from '../../../cli/api/graphql/admin/generated/find_development_theme_by_name.js'\nimport {OnlineStorePasswordProtection} from '../../../cli/api/graphql/admin/generated/online_store_password_protection.js'\nimport {RequestModeInput} from '../http.js'\nimport {adminRequestDoc, type AdminRequestOptions} from '../api/admin.js'\nimport {AdminSession} from '../session.js'\nimport {AbortError} from '../error.js'\nimport {outputDebug} from '../output.js'\nimport {recordTiming, recordEvent, recordError} from '../analytics.js'\nimport {ClientError, type Variables} from 'graphql-request'\nimport type {InlineToken, TokenItem} from '../ui.js'\n\nexport type ThemeParams = Partial<Pick<Theme, 'name' | 'role' | 'processing' | 'src'>>\nexport type AssetParams = Pick<ThemeAsset, 'key'> & Partial<Pick<ThemeAsset, 'value' | 'attachment'>>\nconst SkeletonThemeCdn = 'https://cdn.shopify.com/static/online-store/theme-skeleton.zip'\nconst THEME_API_NETWORK_BEHAVIOUR: RequestModeInput = {\n useNetworkLevelRetry: true,\n useAbortSignal: false,\n maxRetryTimeMs: 90 * 1000,\n recordCommandRetries: true,\n}\nconst DEFAULT_THEME_ACCESS_REQUIREMENT = 'the required theme access scope'\n\nexport async function fetchTheme(id: number, session: AdminSession): Promise<Theme | undefined> {\n const gid = composeThemeGid(id)\n recordEvent('theme-api:fetch-theme')\n\n try {\n const {theme} = await adminRequestDoc({\n query: GetTheme,\n session,\n variables: {id: gid},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (theme) {\n return buildTheme({\n id: parseGid(theme.id),\n processing: theme.processing,\n role: theme.role.toLowerCase(),\n name: theme.name,\n })\n }\n\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n abortIfMissingThemeAccessScope(error)\n /**\n * Consumers of this and other theme APIs in this file expect either a theme\n * or `undefined`.\n *\n * Error handlers should not inspect GraphQL error messages directly, as\n * they are internationalized.\n */\n recordError(error)\n outputDebug(`Error fetching theme with ID: ${id}`)\n }\n}\n\nexport async function fetchThemes(session: AdminSession): Promise<Theme[]> {\n const themes: Theme[] = []\n let after: string | null = null\n recordEvent('theme-api:fetch-themes')\n\n while (true) {\n // eslint-disable-next-line no-await-in-loop\n const response = await requestThemeAdminDoc({\n query: GetThemes,\n session,\n variables: {after},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!response.themes) {\n unexpectedGraphQLError('Failed to fetch themes')\n }\n const {nodes, pageInfo} = response.themes\n nodes.forEach((theme) => {\n const t = buildTheme({\n id: parseGid(theme.id),\n processing: theme.processing,\n role: theme.role.toLowerCase(),\n name: theme.name,\n })\n if (t) {\n themes.push(t)\n }\n })\n if (!pageInfo.hasNextPage) {\n return themes\n }\n\n after = pageInfo.endCursor as string\n }\n}\n\nexport async function findDevelopmentThemeByName(name: string, session: AdminSession): Promise<Theme | undefined> {\n recordEvent('theme-api:find-development-theme-by-name')\n\n const {themes} = await requestThemeAdminDoc({\n query: FindDevelopmentThemeByName,\n session,\n variables: {name},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!themes) {\n unexpectedGraphQLError('Failed to fetch themes')\n }\n\n if (themes.nodes.length > 1) {\n throw recordError(new AbortError(`More than one development theme is named \"${name}\"`))\n }\n\n if (themes.nodes.length === 1) {\n const {id, processing, role, name} = themes.nodes[0]!\n\n return buildTheme({\n id: parseGid(id),\n processing,\n role: role.toLowerCase(),\n name,\n })\n }\n}\n\nexport async function themeCreate(params: ThemeParams, session: AdminSession): Promise<Theme | undefined> {\n const themeSource = params.src ?? SkeletonThemeCdn\n recordEvent('theme-api:create-theme')\n const {themeCreate} = await adminRequestDoc({\n query: ThemeCreate,\n session,\n variables: {\n name: params.name ?? '',\n source: themeSource,\n role: (params.role ?? DEVELOPMENT_THEME_ROLE).toUpperCase() as ThemeRole,\n },\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!themeCreate) {\n unexpectedGraphQLError('Failed to create theme')\n }\n\n const {theme, userErrors} = themeCreate\n if (userErrors.length) {\n const userErrors = themeCreate.userErrors.map((error) => error.message).join(', ')\n throw recordError(new AbortError(userErrors))\n }\n\n if (!theme) {\n unexpectedGraphQLError('Failed to create theme')\n }\n\n return buildTheme({\n id: parseGid(theme.id),\n name: theme.name,\n role: theme.role.toLowerCase(),\n })\n}\n\nexport async function fetchThemeAssets(id: number, filenames: Key[], session: AdminSession): Promise<ThemeAsset[]> {\n const assets: ThemeAsset[] = []\n let after: string | null = null\n recordEvent('theme-api:fetch-assets')\n\n while (true) {\n // eslint-disable-next-line no-await-in-loop\n const response = await requestThemeAdminDoc({\n query: GetThemeFileBodies,\n session,\n variables: {id: themeGid(id), filenames, after},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!response.theme?.files?.nodes || !response.theme?.files?.pageInfo) {\n const userErrors = response.theme?.files?.userErrors.map((error) => error.filename).join(', ')\n unexpectedGraphQLError(`Error fetching assets: ${userErrors}`)\n }\n\n const {nodes, pageInfo} = response.theme.files\n\n assets.push(\n // eslint-disable-next-line no-await-in-loop\n ...(await Promise.all(\n nodes.map(async (file) => {\n const {attachment, value} = await parseThemeFileContent(file.body)\n return {\n attachment,\n key: file.filename,\n checksum: file.checksumMd5 as string,\n value,\n }\n }),\n )),\n )\n\n if (!pageInfo.hasNextPage) {\n return assets\n }\n\n after = pageInfo.endCursor as string\n }\n}\n\nexport async function deleteThemeAssets(id: number, filenames: Key[], session: AdminSession): Promise<Result[]> {\n const batchSize = 50\n const results: Result[] = []\n recordEvent('theme-api:delete-assets')\n\n for (let i = 0; i < filenames.length; i += batchSize) {\n const batch = filenames.slice(i, i + batchSize)\n // eslint-disable-next-line no-await-in-loop\n const {themeFilesDelete} = await adminRequestDoc({\n query: ThemeFilesDelete,\n session,\n variables: {\n themeId: composeThemeGid(id),\n files: batch,\n },\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!themeFilesDelete) {\n unexpectedGraphQLError('Failed to delete theme assets')\n }\n\n const {deletedThemeFiles, userErrors} = themeFilesDelete\n\n if (deletedThemeFiles) {\n deletedThemeFiles.forEach((file) => {\n results.push({key: file.filename, success: true, operation: Operation.Delete})\n })\n }\n\n if (userErrors.length > 0) {\n userErrors.forEach((error) => {\n if (error.filename) {\n recordError(`Asset deletion failed for ${error.filename}: ${error.message}`)\n results.push({\n key: error.filename,\n success: false,\n operation: Operation.Delete,\n errors: {asset: [error.message]},\n })\n } else {\n unexpectedGraphQLError(`Failed to delete theme assets: ${error.message}`)\n }\n })\n }\n }\n\n return results\n}\n\nexport async function bulkUploadThemeAssets(\n id: number,\n assets: AssetParams[],\n session: AdminSession,\n): Promise<Result[]> {\n const results: Result[] = []\n recordEvent('theme-api:bulk-upload-assets')\n for (let i = 0; i < assets.length; i += 50) {\n const chunk = assets.slice(i, i + 50)\n const files = prepareFilesForUpload(chunk)\n\n recordTiming('theme-api:upload-files')\n // eslint-disable-next-line no-await-in-loop\n const uploadResults = await uploadFiles(id, files, session)\n recordTiming('theme-api:upload-files')\n\n results.push(...processUploadResults(uploadResults))\n }\n return results\n}\n\nfunction prepareFilesForUpload(assets: AssetParams[]): OnlineStoreThemeFilesUpsertFileInput[] {\n return assets.map((asset) => {\n if (asset.attachment) {\n return {\n filename: asset.key,\n body: {\n type: 'BASE64' as const,\n value: asset.attachment,\n },\n }\n } else {\n return {\n filename: asset.key,\n body: {\n type: 'TEXT' as const,\n value: asset.value ?? '',\n },\n }\n }\n })\n}\n\nasync function uploadFiles(\n themeId: number,\n files: {filename: string; body: {type: OnlineStoreThemeFileBodyInputType; value: string}}[],\n session: AdminSession,\n): Promise<ThemeFilesUpsertMutation> {\n return adminRequestDoc({\n query: ThemeFilesUpsert,\n session,\n variables: {themeId: themeGid(themeId), files},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n}\n\nfunction processUploadResults(uploadResults: ThemeFilesUpsertMutation): Result[] {\n const {themeFilesUpsert} = uploadResults\n\n if (!themeFilesUpsert) {\n unexpectedGraphQLError('Failed to upload theme files')\n }\n\n const {upsertedThemeFiles, userErrors} = themeFilesUpsert\n\n const results: Result[] = []\n\n upsertedThemeFiles?.forEach((file) => {\n results.push({\n key: file.filename,\n success: true,\n operation: Operation.Upload,\n })\n })\n\n userErrors.forEach((error) => {\n if (!error.filename) {\n unexpectedGraphQLError(`Error uploading theme files: ${error.message}`)\n }\n recordError(`Asset upload failed for ${error.filename}: ${error.message}`)\n results.push({\n key: error.filename,\n success: false,\n operation: Operation.Upload,\n errors: {asset: [error.message]},\n })\n })\n\n return results\n}\n\nexport async function fetchChecksums(id: number, session: AdminSession): Promise<Checksum[]> {\n const checksums: Checksum[] = []\n let after: string | null = null\n recordEvent('theme-api:fetch-checksums')\n\n while (true) {\n // eslint-disable-next-line no-await-in-loop\n const response = await requestThemeAdminDoc({\n query: GetThemeFileChecksums,\n session,\n variables: {id: themeGid(id), after},\n responseOptions: {handleErrors: false},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n\n if (!response?.theme?.files?.nodes || !response?.theme?.files?.pageInfo) {\n const userErrors = response.theme?.files?.userErrors.map((error) => error.filename).join(', ')\n throw recordError(new AbortError(`Failed to fetch checksums for: ${userErrors}`))\n }\n\n const {nodes, pageInfo} = response.theme.files\n\n checksums.push(\n ...nodes.map((file) => ({\n key: file.filename,\n checksum: file.checksumMd5 as string,\n })),\n )\n\n if (!pageInfo.hasNextPage) {\n return checksums\n }\n\n after = pageInfo.endCursor as string\n }\n}\n\nexport async function themeUpdate(id: number, params: ThemeParams, session: AdminSession): Promise<Theme | undefined> {\n const name = params.name\n const input: Record<string, string> = {}\n if (name) {\n input.name = name\n }\n recordEvent('theme-api:update-theme')\n\n const {themeUpdate} = await adminRequestDoc({\n query: ThemeUpdate,\n session,\n variables: {id: composeThemeGid(id), input},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n if (!themeUpdate) {\n // An unexpected error occurred during the GraphQL request execution\n unexpectedGraphQLError('Failed to update theme')\n }\n\n const {theme, userErrors} = themeUpdate\n if (userErrors.length) {\n const userErrors = themeUpdate.userErrors.map((error) => error.message).join(', ')\n throw recordError(new AbortError(userErrors))\n }\n\n if (!theme) {\n // An unexpected error if neither theme nor userErrors are returned\n unexpectedGraphQLError('Failed to update theme')\n }\n\n return buildTheme({\n id: parseGid(theme.id),\n name: theme.name,\n role: theme.role.toLowerCase(),\n })\n}\n\nexport async function themePublish(id: number, session: AdminSession): Promise<Theme | undefined> {\n recordEvent('theme-api:publish-theme')\n const {themePublish} = await adminRequestDoc({\n query: ThemePublish,\n session,\n variables: {id: composeThemeGid(id)},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n if (!themePublish) {\n // An unexpected error occurred during the GraphQL request execution\n unexpectedGraphQLError('Failed to update theme')\n }\n\n const {theme, userErrors} = themePublish\n if (userErrors.length) {\n const userErrors = themePublish.userErrors.map((error) => error.message).join(', ')\n throw recordError(new AbortError(userErrors))\n }\n\n if (!theme) {\n // An unexpected error if neither theme nor userErrors are returned\n unexpectedGraphQLError('Failed to update theme')\n }\n\n return buildTheme({\n id: parseGid(theme.id),\n name: theme.name,\n role: theme.role.toLowerCase(),\n })\n}\n\nexport async function themeDelete(id: number, session: AdminSession): Promise<boolean | undefined> {\n recordEvent('theme-api:delete-theme')\n const {themeDelete} = await adminRequestDoc({\n query: ThemeDelete,\n session,\n variables: {id: composeThemeGid(id)},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n })\n if (!themeDelete) {\n // An unexpected error occurred during the GraphQL request execution\n unexpectedGraphQLError('Failed to update theme')\n }\n\n const {deletedThemeId, userErrors} = themeDelete\n if (userErrors.length) {\n const userErrors = themeDelete.userErrors.map((error) => error.message).join(', ')\n throw recordError(new AbortError(userErrors))\n }\n\n if (!deletedThemeId) {\n // An unexpected error if neither theme nor userErrors are returned\n unexpectedGraphQLError('Failed to update theme')\n }\n\n return true\n}\n\nexport interface ThemeDuplicateResult {\n theme?: Theme\n userErrors: {field?: string[] | null; message: string}[]\n requestId?: string\n}\n\nexport async function themeDuplicate(\n id: number,\n name: string | undefined,\n session: AdminSession,\n): Promise<ThemeDuplicateResult> {\n let requestId: string | undefined\n recordEvent('theme-api:duplicate-theme')\n\n const {themeDuplicate} = await adminRequestDoc({\n query: ThemeDuplicate,\n session,\n variables: {id: composeThemeGid(id), name},\n preferredBehaviour: THEME_API_NETWORK_BEHAVIOUR,\n responseOptions: {\n onResponse: (response) => {\n requestId = response.headers.get('x-request-id') ?? undefined\n },\n },\n })\n\n if (!themeDuplicate) {\n // An unexpected error occurred during the GraphQL request execution\n recordError('Failed to duplicate theme')\n return {\n theme: undefined,\n userErrors: [{message: 'Failed to duplicate theme'}],\n requestId,\n }\n }\n\n const {newTheme, userErrors} = themeDuplicate\n\n if (userErrors.length > 0) {\n return {\n theme: undefined,\n userErrors,\n requestId,\n }\n }\n\n if (!newTheme) {\n // An unexpected error if neither theme nor userErrors are returned\n return {\n theme: undefined,\n userErrors: [{message: 'Failed to duplicate theme'}],\n requestId,\n }\n }\n\n const theme = buildTheme({\n id: parseGid(newTheme.id),\n name: newTheme.name,\n role: newTheme.role.toLowerCase(),\n })\n\n return {\n theme,\n userErrors: [],\n requestId,\n }\n}\n\nexport async function metafieldDefinitionsByOwnerType(type: MetafieldOwnerType, session: AdminSession) {\n recordEvent('theme-api:fetch-metafield-definitions')\n const {metafieldDefinitions} = await adminRequestDoc({\n query: MetafieldDefinitionsByOwnerType,\n session,\n variables: {ownerType: type},\n })\n\n return metafieldDefinitions.nodes.map((definition) => ({\n key: definition.key,\n namespace: definition.namespace,\n name: definition.name,\n description: definition.description,\n type: {\n name: definition.type.name,\n category: definition.type.category,\n },\n }))\n}\n\nexport async function passwordProtected(session: AdminSession): Promise<boolean> {\n recordEvent('theme-api:check-password-protection')\n const {onlineStore} = await adminRequestDoc({\n query: OnlineStorePasswordProtection,\n session,\n })\n if (!onlineStore) {\n unexpectedGraphQLError(\"Unable to get details about the storefront's password protection\")\n }\n\n const {passwordProtection} = onlineStore\n\n return passwordProtection.enabled\n}\n\nfunction unexpectedGraphQLError(message: string): never {\n throw recordError(new AbortError(message))\n}\n\nasync function requestThemeAdminDoc<TResult, TVariables extends Variables>(\n options: AdminRequestOptions<TResult, TVariables>,\n): Promise<TResult> {\n try {\n const response = await adminRequestDoc(options)\n return response\n } catch (error) {\n abortIfMissingThemeAccessScope(error)\n throw error\n }\n}\n\nfunction abortIfMissingThemeAccessScope(error: unknown): void {\n if (!(error instanceof ClientError)) return\n\n const requiredAccess = getThemeAccessRequirementForAccessDeniedError(error)\n if (!requiredAccess) return\n\n const nextSteps: TokenItem<InlineToken>[] = [\n [\n 'If you authenticated with an Admin API access token, update the app or integration that issued the token to include the required theme access scopes, then reauthorize it or generate a new token.',\n ],\n [\n 'For',\n {command: 'theme pull'},\n {char: ','},\n {command: 'theme list'},\n {char: ','},\n 'and',\n {command: 'theme info'},\n {char: ','},\n 'add the',\n {command: 'read_themes'},\n 'scope',\n {char: '.'},\n ],\n [\n 'For',\n {command: 'theme push'},\n 'and',\n {command: 'theme dev'},\n {char: ','},\n 'add both the',\n {command: 'read_themes'},\n 'and',\n {command: 'write_themes'},\n 'scopes',\n {char: '.'},\n ],\n [\n 'If you authenticated with your Shopify account, make sure your staff or collaborator account can access Online Store themes, then run',\n {command: 'shopify auth logout'},\n 'and try again',\n {char: '.'},\n ],\n ['See', {link: {label: 'Shopify access scopes', url: 'https://shopify.dev/api/usage/access-scopes'}}, {char: '.'}],\n ]\n\n throw recordError(\n new AbortError(`The authenticated account or access token is missing ${requiredAccess}.`, undefined, nextSteps),\n )\n}\n\nfunction getThemeAccessRequirementForAccessDeniedError(error: ClientError): string | undefined {\n const graphQLErrors = error.response.errors\n if (!Array.isArray(graphQLErrors)) return undefined\n\n const accessDeniedError = graphQLErrors.find((graphQLError) => graphQLError.extensions?.code === 'ACCESS_DENIED')\n if (!accessDeniedError) return undefined\n\n const requiredAccess = accessDeniedError.extensions?.requiredAccess\n if (typeof requiredAccess !== 'string') return DEFAULT_THEME_ACCESS_REQUIREMENT\n\n return requiredAccess.trim().replace(/\\.$/, '') || DEFAULT_THEME_ACCESS_REQUIREMENT\n}\n\nfunction themeGid(id: number): string {\n return `gid://shopify/OnlineStoreTheme/${id}`\n}\n\ntype OnlineStoreThemeFileBody =\n | {__typename: 'OnlineStoreThemeFileBodyBase64'; contentBase64: string}\n | {__typename: 'OnlineStoreThemeFileBodyText'; content: string}\n | {__typename: 'OnlineStoreThemeFileBodyUrl'; url: string}\n\nexport async function parseThemeFileContent(\n body: OnlineStoreThemeFileBody,\n): Promise<{value?: string; attachment?: string}> {\n switch (body.__typename) {\n case 'OnlineStoreThemeFileBodyText':\n return {value: body.content}\n case 'OnlineStoreThemeFileBodyBase64':\n return {attachment: body.contentBase64}\n case 'OnlineStoreThemeFileBodyUrl':\n try {\n // eslint-disable-next-line no-restricted-globals\n const response = await fetch(body.url)\n\n const arrayBuffer = await response.arrayBuffer()\n return {attachment: Buffer.from(arrayBuffer).toString('base64')}\n } catch (error) {\n // Raise error if we can't download the file\n throw recordError(new AbortError(`Error downloading content from URL: ${body.url}`))\n }\n }\n}\n"]}
@@ -1,9 +1,10 @@
1
1
  import { JsonMapType } from './codec.js';
2
+ import { AbortError } from '../error.js';
2
3
  /**
3
4
  * An error on a TOML file — missing or malformed.
4
- * Extends Error so it can be thrown. Carries path and a clean message suitable for JSON output.
5
+ * Carries path and a clean message suitable for JSON output.
5
6
  */
6
- export declare class TomlFileError extends Error {
7
+ export declare class TomlFileError extends AbortError {
7
8
  readonly path: string;
8
9
  constructor(path: string, message: string);
9
10
  }
@@ -1,11 +1,12 @@
1
1
  import { decodeToml, encodeToml } from './codec.js';
2
+ import { AbortError } from '../error.js';
2
3
  import { fileExists, readFile, writeFile } from '../fs.js';
3
4
  import { updateTomlValues } from '@shopify/toml-patch';
4
5
  /**
5
6
  * An error on a TOML file — missing or malformed.
6
- * Extends Error so it can be thrown. Carries path and a clean message suitable for JSON output.
7
+ * Carries path and a clean message suitable for JSON output.
7
8
  */
8
- export class TomlFileError extends Error {
9
+ export class TomlFileError extends AbortError {
9
10
  constructor(path, message) {
10
11
  super(message);
11
12
  this.name = 'TomlFileError';
@@ -1 +1 @@
1
- {"version":3,"file":"toml-file.js","sourceRoot":"","sources":["../../../../src/public/node/toml/toml-file.ts"],"names":[],"mappings":"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","sourcesContent":["import {JsonMapType, decodeToml, encodeToml} from './codec.js'\nimport {fileExists, readFile, writeFile} from '../fs.js'\nimport {updateTomlValues} from '@shopify/toml-patch'\n\ntype TomlPatchValue = string | number | boolean | undefined | (string | number | boolean)[]\n\n/**\n * An error on a TOML file — missing or malformed.\n * Extends Error so it can be thrown. Carries path and a clean message suitable for JSON output.\n */\nexport class TomlFileError extends Error {\n readonly path: string\n\n constructor(path: string, message: string) {\n super(message)\n this.name = 'TomlFileError'\n this.path = path\n }\n}\n\n/**\n * General-purpose TOML file abstraction.\n *\n * Provides a unified interface for reading, patching, removing keys from, and replacing\n * the content of TOML files on disk.\n *\n * - `read` populates content from disk\n * - `patch` does surgical WASM-based edits (preserves comments and formatting)\n * - `remove` deletes a key by dotted path (preserves comments and formatting)\n * - `replace` does a full re-serialization (comments and formatting are NOT preserved).\n * - `transformRaw` applies a function to the raw TOML string on disk.\n */\nexport class TomlFile {\n /**\n * Read and parse a TOML file from disk. Throws {@link TomlFileError} if the file\n * doesn't exist or contains invalid TOML.\n *\n * @param path - Absolute path to the TOML file.\n * @returns A TomlFile instance with parsed content.\n */\n static async read(path: string): Promise<TomlFile> {\n if (!(await fileExists(path))) {\n throw new TomlFileError(path, `TOML file not found: ${path}`)\n }\n const raw = await readFile(path)\n const file = new TomlFile(path, {})\n file.content = file.decode(raw)\n return file\n }\n\n readonly path: string\n content: JsonMapType\n readonly errors: TomlFileError[] = []\n\n constructor(path: string, content: JsonMapType) {\n this.path = path\n this.content = content\n }\n\n /**\n * Surgically patch values in the TOML file, preserving comments and formatting.\n *\n * Accepts a nested object whose leaf values are set in the TOML. Intermediate tables are\n * created automatically. Setting a leaf to `undefined` removes it (use `remove()` for a\n * clearer API when deleting keys).\n *\n * @example\n * ```ts\n * await file.patch({build: {dev_store_url: 'my-store.myshopify.com'}})\n * await file.patch({application_url: 'https://example.com', auth: {redirect_urls: ['...']}})\n * ```\n */\n async patch(changes: {[key: string]: unknown}): Promise<void> {\n const patches = flattenToPatchEntries(changes)\n const raw = await readFile(this.path)\n const updated = updateTomlValues(raw, patches)\n const parsed = this.decode(updated)\n await writeFile(this.path, updated)\n this.content = parsed\n }\n\n /**\n * Remove a key from the TOML file by dotted path, preserving comments and formatting.\n *\n * @param keyPath - Dotted key path to remove (e.g. 'build.include_config_on_deploy').\n * @example\n * ```ts\n * await file.remove('build.include_config_on_deploy')\n * ```\n */\n async remove(keyPath: string): Promise<void> {\n const keys = keyPath.split('.')\n const raw = await readFile(this.path)\n const updated = updateTomlValues(raw, [[keys, undefined]])\n const parsed = this.decode(updated)\n await writeFile(this.path, updated)\n this.content = parsed\n }\n\n /**\n * Replace the entire file content. The file is fully re-serialized — comments and formatting\n * are NOT preserved.\n *\n * @param content - The new content to write.\n * @example\n * ```ts\n * await file.replace({client_id: 'abc', name: 'My App'})\n * ```\n */\n async replace(content: JsonMapType): Promise<void> {\n const encoded = encodeToml(content)\n this.decode(encoded)\n await writeFile(this.path, encoded)\n this.content = content\n }\n\n /**\n * Transform the raw TOML string on disk. Reads the file, applies the transform function\n * to the raw text, writes back, and re-parses to keep `content` in sync.\n *\n * Use this for text-level operations that can't be expressed as structured edits —\n * e.g. Injecting comments or positional insertion of keys in arrays-of-tables.\n * Subsequent `patch()` calls will preserve any comments added this way.\n *\n * @param transform - A function that receives the raw TOML string and returns the modified string.\n * @example\n * ```ts\n * await file.transformRaw((raw) => `# Header comment\\n${raw}`)\n * ```\n */\n async transformRaw(transform: (raw: string) => string): Promise<void> {\n const raw = await readFile(this.path)\n const transformed = transform(raw)\n const parsed = this.decode(transformed)\n await writeFile(this.path, transformed)\n this.content = parsed\n }\n\n private decode(raw: string): JsonMapType {\n try {\n return decodeToml(raw)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n if (err.line !== undefined && err.col !== undefined) {\n const description = String(err.message).split('\\n')[0] ?? 'Invalid TOML'\n throw new TomlFileError(this.path, `${description} at row ${err.line}, col ${err.col}`)\n }\n throw err\n }\n }\n}\n\n/**\n * Flatten a nested object into an array of `[keyPath, value]` patch entries\n * suitable for `updateTomlValues`.\n *\n * @param obj - The nested object to flatten.\n * @param prefix - Key path prefix for recursion.\n * @returns Flattened patch entries.\n */\nfunction flattenToPatchEntries(obj: {[key: string]: unknown}, prefix: string[] = []): [string[], TomlPatchValue][] {\n const entries: [string[], TomlPatchValue][] = []\n for (const [key, value] of Object.entries(obj)) {\n const path = [...prefix, key]\n if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n entries.push(...flattenToPatchEntries(value as {[key: string]: unknown}, path))\n } else {\n entries.push([path, value as TomlPatchValue])\n }\n }\n return entries\n}\n"]}
1
+ {"version":3,"file":"toml-file.js","sourceRoot":"","sources":["../../../../src/public/node/toml/toml-file.ts"],"names":[],"mappings":"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","sourcesContent":["import {JsonMapType, decodeToml, encodeToml} from './codec.js'\nimport {AbortError} from '../error.js'\nimport {fileExists, readFile, writeFile} from '../fs.js'\nimport {updateTomlValues} from '@shopify/toml-patch'\n\ntype TomlPatchValue = string | number | boolean | undefined | (string | number | boolean)[]\n\n/**\n * An error on a TOML file — missing or malformed.\n * Carries path and a clean message suitable for JSON output.\n */\nexport class TomlFileError extends AbortError {\n readonly path: string\n\n constructor(path: string, message: string) {\n super(message)\n this.name = 'TomlFileError'\n this.path = path\n }\n}\n\n/**\n * General-purpose TOML file abstraction.\n *\n * Provides a unified interface for reading, patching, removing keys from, and replacing\n * the content of TOML files on disk.\n *\n * - `read` populates content from disk\n * - `patch` does surgical WASM-based edits (preserves comments and formatting)\n * - `remove` deletes a key by dotted path (preserves comments and formatting)\n * - `replace` does a full re-serialization (comments and formatting are NOT preserved).\n * - `transformRaw` applies a function to the raw TOML string on disk.\n */\nexport class TomlFile {\n /**\n * Read and parse a TOML file from disk. Throws {@link TomlFileError} if the file\n * doesn't exist or contains invalid TOML.\n *\n * @param path - Absolute path to the TOML file.\n * @returns A TomlFile instance with parsed content.\n */\n static async read(path: string): Promise<TomlFile> {\n if (!(await fileExists(path))) {\n throw new TomlFileError(path, `TOML file not found: ${path}`)\n }\n const raw = await readFile(path)\n const file = new TomlFile(path, {})\n file.content = file.decode(raw)\n return file\n }\n\n readonly path: string\n content: JsonMapType\n readonly errors: TomlFileError[] = []\n\n constructor(path: string, content: JsonMapType) {\n this.path = path\n this.content = content\n }\n\n /**\n * Surgically patch values in the TOML file, preserving comments and formatting.\n *\n * Accepts a nested object whose leaf values are set in the TOML. Intermediate tables are\n * created automatically. Setting a leaf to `undefined` removes it (use `remove()` for a\n * clearer API when deleting keys).\n *\n * @example\n * ```ts\n * await file.patch({build: {dev_store_url: 'my-store.myshopify.com'}})\n * await file.patch({application_url: 'https://example.com', auth: {redirect_urls: ['...']}})\n * ```\n */\n async patch(changes: {[key: string]: unknown}): Promise<void> {\n const patches = flattenToPatchEntries(changes)\n const raw = await readFile(this.path)\n const updated = updateTomlValues(raw, patches)\n const parsed = this.decode(updated)\n await writeFile(this.path, updated)\n this.content = parsed\n }\n\n /**\n * Remove a key from the TOML file by dotted path, preserving comments and formatting.\n *\n * @param keyPath - Dotted key path to remove (e.g. 'build.include_config_on_deploy').\n * @example\n * ```ts\n * await file.remove('build.include_config_on_deploy')\n * ```\n */\n async remove(keyPath: string): Promise<void> {\n const keys = keyPath.split('.')\n const raw = await readFile(this.path)\n const updated = updateTomlValues(raw, [[keys, undefined]])\n const parsed = this.decode(updated)\n await writeFile(this.path, updated)\n this.content = parsed\n }\n\n /**\n * Replace the entire file content. The file is fully re-serialized — comments and formatting\n * are NOT preserved.\n *\n * @param content - The new content to write.\n * @example\n * ```ts\n * await file.replace({client_id: 'abc', name: 'My App'})\n * ```\n */\n async replace(content: JsonMapType): Promise<void> {\n const encoded = encodeToml(content)\n this.decode(encoded)\n await writeFile(this.path, encoded)\n this.content = content\n }\n\n /**\n * Transform the raw TOML string on disk. Reads the file, applies the transform function\n * to the raw text, writes back, and re-parses to keep `content` in sync.\n *\n * Use this for text-level operations that can't be expressed as structured edits —\n * e.g. Injecting comments or positional insertion of keys in arrays-of-tables.\n * Subsequent `patch()` calls will preserve any comments added this way.\n *\n * @param transform - A function that receives the raw TOML string and returns the modified string.\n * @example\n * ```ts\n * await file.transformRaw((raw) => `# Header comment\\n${raw}`)\n * ```\n */\n async transformRaw(transform: (raw: string) => string): Promise<void> {\n const raw = await readFile(this.path)\n const transformed = transform(raw)\n const parsed = this.decode(transformed)\n await writeFile(this.path, transformed)\n this.content = parsed\n }\n\n private decode(raw: string): JsonMapType {\n try {\n return decodeToml(raw)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n if (err.line !== undefined && err.col !== undefined) {\n const description = String(err.message).split('\\n')[0] ?? 'Invalid TOML'\n throw new TomlFileError(this.path, `${description} at row ${err.line}, col ${err.col}`)\n }\n throw err\n }\n }\n}\n\n/**\n * Flatten a nested object into an array of `[keyPath, value]` patch entries\n * suitable for `updateTomlValues`.\n *\n * @param obj - The nested object to flatten.\n * @param prefix - Key path prefix for recursion.\n * @returns Flattened patch entries.\n */\nfunction flattenToPatchEntries(obj: {[key: string]: unknown}, prefix: string[] = []): [string[], TomlPatchValue][] {\n const entries: [string[], TomlPatchValue][] = []\n for (const [key, value] of Object.entries(obj)) {\n const path = [...prefix, key]\n if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n entries.push(...flattenToPatchEntries(value as {[key: string]: unknown}, path))\n } else {\n entries.push([path, value as TomlPatchValue])\n }\n }\n return entries\n}\n"]}