@shopify/cli-kit 3.33.0 → 3.35.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 (212) hide show
  1. package/dist/git.js +3 -3
  2. package/dist/git.js.map +1 -1
  3. package/dist/http/fetch.js +1 -1
  4. package/dist/http/fetch.js.map +1 -1
  5. package/dist/http.js +2 -2
  6. package/dist/http.js.map +1 -1
  7. package/dist/index.d.ts +0 -7
  8. package/dist/index.js +0 -7
  9. package/dist/index.js.map +1 -1
  10. package/dist/metadata.js +1 -1
  11. package/dist/metadata.js.map +1 -1
  12. package/dist/npm.js +3 -3
  13. package/dist/npm.js.map +1 -1
  14. package/dist/output.js +4 -4
  15. package/dist/output.js.map +1 -1
  16. package/dist/path.d.ts +1 -1
  17. package/dist/path.js +5 -3
  18. package/dist/path.js.map +1 -1
  19. package/dist/private/node/analytics.js +6 -9
  20. package/dist/private/node/analytics.js.map +1 -1
  21. package/dist/private/node/api/graphql.js +2 -1
  22. package/dist/private/node/api/graphql.js.map +1 -1
  23. package/dist/private/node/api/headers.d.ts +2 -2
  24. package/dist/private/node/api/headers.js +4 -4
  25. package/dist/private/node/api/headers.js.map +1 -1
  26. package/dist/private/node/api/rest.d.ts +6 -4
  27. package/dist/private/node/api/rest.js +8 -7
  28. package/dist/private/node/api/rest.js.map +1 -1
  29. package/dist/private/node/constants.d.ts +42 -0
  30. package/dist/private/node/constants.js +58 -0
  31. package/dist/private/node/constants.js.map +1 -0
  32. package/dist/private/node/environment/service.d.ts +18 -0
  33. package/dist/private/node/environment/service.js +32 -0
  34. package/dist/private/node/environment/service.js.map +1 -0
  35. package/dist/{environment → private/node/environment}/spin-cache.d.ts +0 -0
  36. package/dist/{environment → private/node/environment}/spin-cache.js +0 -0
  37. package/dist/private/node/environment/spin-cache.js.map +1 -0
  38. package/dist/{environment → private/node/environment}/utilities.d.ts +0 -0
  39. package/dist/{environment → private/node/environment}/utilities.js +0 -0
  40. package/dist/private/node/environment/utilities.js.map +1 -0
  41. package/dist/{session → private/node/session}/authorize.d.ts +1 -5
  42. package/dist/{session → private/node/session}/authorize.js +9 -9
  43. package/dist/private/node/session/authorize.js.map +1 -0
  44. package/dist/{session → private/node/session}/device-authorization.d.ts +0 -0
  45. package/dist/{session → private/node/session}/device-authorization.js +7 -9
  46. package/dist/private/node/session/device-authorization.js.map +1 -0
  47. package/dist/{session → private/node/session}/exchange.d.ts +2 -2
  48. package/dist/{session → private/node/session}/exchange.js +5 -5
  49. package/dist/private/node/session/exchange.js.map +1 -0
  50. package/dist/{session → private/node/session}/identity-token-validation.d.ts +0 -0
  51. package/dist/{session → private/node/session}/identity-token-validation.js +4 -4
  52. package/dist/private/node/session/identity-token-validation.js.map +1 -0
  53. package/dist/{session → private/node/session}/identity.d.ts +1 -1
  54. package/dist/{session → private/node/session}/identity.js +2 -3
  55. package/dist/private/node/session/identity.js.map +1 -0
  56. package/dist/{session → private/node/session}/post-auth.d.ts +1 -1
  57. package/dist/{session → private/node/session}/post-auth.js +10 -10
  58. package/dist/private/node/session/post-auth.js.map +1 -0
  59. package/dist/{session → private/node/session}/redirect-listener.d.ts +0 -0
  60. package/dist/{session → private/node/session}/redirect-listener.js +2 -2
  61. package/dist/private/node/session/redirect-listener.js.map +1 -0
  62. package/dist/{session → private/node/session}/schema.d.ts +1 -1
  63. package/dist/{session → private/node/session}/schema.js +1 -1
  64. package/dist/private/node/session/schema.js.map +1 -0
  65. package/dist/{session → private/node/session}/scopes.d.ts +1 -1
  66. package/dist/{session → private/node/session}/scopes.js +2 -2
  67. package/dist/private/node/session/scopes.js.map +1 -0
  68. package/dist/{session → private/node/session}/store.d.ts +0 -0
  69. package/dist/{session → private/node/session}/store.js +10 -10
  70. package/dist/private/node/session/store.js.map +1 -0
  71. package/dist/{session → private/node/session}/validate.d.ts +0 -0
  72. package/dist/{session → private/node/session}/validate.js +4 -4
  73. package/dist/private/node/session/validate.js.map +1 -0
  74. package/dist/private/node/session.d.ts +56 -0
  75. package/dist/{session.js → private/node/session.js} +98 -134
  76. package/dist/private/node/session.js.map +1 -0
  77. package/dist/private/node/ui/components/SelectPrompt.d.ts +2 -1
  78. package/dist/private/node/ui/components/SelectPrompt.js +2 -1
  79. package/dist/private/node/ui/components/SelectPrompt.js.map +1 -1
  80. package/dist/private/node/ui/components/Table/Column.d.ts +5 -0
  81. package/dist/private/node/ui/components/Table/Column.js +2 -0
  82. package/dist/private/node/ui/components/Table/Column.js.map +1 -0
  83. package/dist/private/node/ui/components/Table/Row.d.ts +12 -0
  84. package/dist/private/node/ui/components/Table/Row.js +24 -0
  85. package/dist/private/node/ui/components/Table/Row.js.map +1 -0
  86. package/dist/private/node/ui/components/Table/ScalarDict.d.ts +5 -0
  87. package/dist/private/node/ui/components/Table/ScalarDict.js +2 -0
  88. package/dist/private/node/ui/components/Table/ScalarDict.js.map +1 -0
  89. package/dist/private/node/ui/components/Table/Table.d.ts +12 -0
  90. package/dist/private/node/ui/components/Table/Table.js +30 -0
  91. package/dist/private/node/ui/components/Table/Table.js.map +1 -0
  92. package/dist/private/node/ui/components/Table/Table.test.d.ts +1 -0
  93. package/dist/private/node/ui/components/Table/Table.test.js +41 -0
  94. package/dist/private/node/ui/components/Table/Table.test.js.map +1 -0
  95. package/dist/private/node/ui.js +1 -1
  96. package/dist/private/node/ui.js.map +1 -1
  97. package/dist/public/common/string.d.ts +11 -0
  98. package/dist/public/common/string.js +21 -0
  99. package/dist/public/common/string.js.map +1 -1
  100. package/dist/public/common/version.d.ts +1 -0
  101. package/dist/public/common/version.js +2 -0
  102. package/dist/public/common/version.js.map +1 -0
  103. package/dist/public/node/analytics.js +5 -5
  104. package/dist/public/node/analytics.js.map +1 -1
  105. package/dist/public/node/api/admin.d.ts +5 -2
  106. package/dist/public/node/api/admin.js +4 -3
  107. package/dist/public/node/api/admin.js.map +1 -1
  108. package/dist/public/node/api/partners.js +1 -1
  109. package/dist/public/node/api/partners.js.map +1 -1
  110. package/dist/public/node/base-command.js +2 -2
  111. package/dist/public/node/base-command.js.map +1 -1
  112. package/dist/public/node/cli.d.ts +8 -0
  113. package/dist/public/node/cli.js +25 -8
  114. package/dist/public/node/cli.js.map +1 -1
  115. package/dist/public/node/dot-env.js +2 -2
  116. package/dist/public/node/dot-env.js.map +1 -1
  117. package/dist/public/node/environment/fqdn.d.ts +26 -0
  118. package/dist/{environment → public/node/environment}/fqdn.js +15 -31
  119. package/dist/public/node/environment/fqdn.js.map +1 -0
  120. package/dist/{environment → public/node/environment}/local.d.ts +62 -15
  121. package/dist/{environment → public/node/environment}/local.js +81 -36
  122. package/dist/public/node/environment/local.js.map +1 -0
  123. package/dist/public/node/environment/spin.d.ts +43 -0
  124. package/dist/{environment → public/node/environment}/spin.js +31 -38
  125. package/dist/public/node/environment/spin.js.map +1 -0
  126. package/dist/public/node/error-handler.js +6 -5
  127. package/dist/public/node/error-handler.js.map +1 -1
  128. package/dist/public/node/fs.d.ts +222 -3
  129. package/dist/public/node/fs.js +338 -2
  130. package/dist/public/node/fs.js.map +1 -1
  131. package/dist/public/node/git.d.ts +90 -0
  132. package/dist/public/node/git.js +174 -0
  133. package/dist/public/node/git.js.map +1 -0
  134. package/dist/public/node/liquid.js +6 -6
  135. package/dist/public/node/liquid.js.map +1 -1
  136. package/dist/public/node/node-package-manager.d.ts +0 -10
  137. package/dist/public/node/node-package-manager.js +3 -20
  138. package/dist/public/node/node-package-manager.js.map +1 -1
  139. package/dist/public/node/presets.js +2 -2
  140. package/dist/public/node/presets.js.map +1 -1
  141. package/dist/public/node/ruby.d.ts +1 -1
  142. package/dist/public/node/ruby.js +19 -20
  143. package/dist/public/node/ruby.js.map +1 -1
  144. package/dist/public/node/session.d.ts +53 -0
  145. package/dist/public/node/session.js +95 -0
  146. package/dist/public/node/session.js.map +1 -0
  147. package/dist/public/node/system.d.ts +44 -0
  148. package/dist/{system.js → public/node/system.js} +34 -54
  149. package/dist/public/node/system.js.map +1 -0
  150. package/dist/public/node/tcp.js +1 -1
  151. package/dist/public/node/tcp.js.map +1 -1
  152. package/dist/public/node/ui.d.ts +13 -0
  153. package/dist/public/node/ui.js +14 -0
  154. package/dist/public/node/ui.js.map +1 -1
  155. package/dist/public/node/vscode.js +5 -5
  156. package/dist/public/node/vscode.js.map +1 -1
  157. package/dist/secure-store.js +4 -4
  158. package/dist/secure-store.js.map +1 -1
  159. package/dist/store.d.ts +10 -10
  160. package/dist/store.js +21 -22
  161. package/dist/store.js.map +1 -1
  162. package/dist/testing/store.js +3 -3
  163. package/dist/testing/store.js.map +1 -1
  164. package/dist/testing/ui.js +1 -1
  165. package/dist/testing/ui.js.map +1 -1
  166. package/dist/tsconfig.tsbuildinfo +1 -1
  167. package/dist/ui.js +4 -4
  168. package/dist/ui.js.map +1 -1
  169. package/package.json +10 -7
  170. package/dist/cli.d.ts +0 -8
  171. package/dist/cli.js +0 -18
  172. package/dist/cli.js.map +0 -1
  173. package/dist/constants.d.ts +0 -51
  174. package/dist/constants.js +0 -70
  175. package/dist/constants.js.map +0 -1
  176. package/dist/environment/fqdn.d.ts +0 -29
  177. package/dist/environment/fqdn.js.map +0 -1
  178. package/dist/environment/local.js.map +0 -1
  179. package/dist/environment/service.d.ts +0 -4
  180. package/dist/environment/service.js +0 -19
  181. package/dist/environment/service.js.map +0 -1
  182. package/dist/environment/spin-cache.js.map +0 -1
  183. package/dist/environment/spin.d.ts +0 -50
  184. package/dist/environment/spin.js.map +0 -1
  185. package/dist/environment/utilities.js.map +0 -1
  186. package/dist/environment.d.ts +0 -7
  187. package/dist/environment.js +0 -8
  188. package/dist/environment.js.map +0 -1
  189. package/dist/file.d.ts +0 -98
  190. package/dist/file.js +0 -216
  191. package/dist/file.js.map +0 -1
  192. package/dist/network/service.d.ts +0 -14
  193. package/dist/network/service.js +0 -11
  194. package/dist/network/service.js.map +0 -1
  195. package/dist/session/authorize.js.map +0 -1
  196. package/dist/session/device-authorization.js.map +0 -1
  197. package/dist/session/exchange.js.map +0 -1
  198. package/dist/session/identity-token-validation.js.map +0 -1
  199. package/dist/session/identity.js.map +0 -1
  200. package/dist/session/post-auth.js.map +0 -1
  201. package/dist/session/redirect-listener.js.map +0 -1
  202. package/dist/session/schema.js.map +0 -1
  203. package/dist/session/scopes.js.map +0 -1
  204. package/dist/session/store.js.map +0 -1
  205. package/dist/session/token.d.ts +0 -40
  206. package/dist/session/token.js +0 -22
  207. package/dist/session/token.js.map +0 -1
  208. package/dist/session/validate.js.map +0 -1
  209. package/dist/session.d.ts +0 -96
  210. package/dist/session.js.map +0 -1
  211. package/dist/system.d.ts +0 -51
  212. package/dist/system.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../../src/private/node/api/headers.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAC,aAAa,EAAC,MAAM,+BAA+B,CAAA;AAC3D,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAC,UAAU,EAAC,MAAM,gCAAgC,CAAA;AAEzD,MAAM,OAAO,kBAAmB,SAAQ,eAAe;IAErD,YAAmB,OAAe,EAAE,UAAkB;QACpD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,SAAS,GAA4B,EAAE,CAAA;IAC7C,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QACtC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,SAAS,EAAE;YAC1F,SAAS,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAE,CAAA;SACrC;IACH,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;SAC1B,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACd,OAAO,MAAM,MAAM,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,CAAA;IAC7C,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAc;IAC/C,MAAM,SAAS,GAAG,kBAAkB,MAAM,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAA;IAEvE,MAAM,OAAO,GAA+B;QAC1C,YAAY,EAAE,SAAS;QACvB,0DAA0D;QAC1D,oBAAoB,EAAE,OAAO,CAAC,QAAQ;QACtC,cAAc,EAAE,UAAU,EAAE;QAC5B,cAAc,EAAE,kBAAkB;QAClC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAC,wBAAwB,EAAE,GAAG,EAAC,CAAC;KACxD,CAAA;IACD,IAAI,KAAK,EAAE;QACT,wCAAwC;QACxC,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAA;QAC5C,OAAO,CAAC,wBAAwB,CAAC,GAAG,UAAU,KAAK,EAAE,CAAA;KACtD;IAED,OAAO,OAAO,CAAA;AAChB,CAAC","sourcesContent":["import constants from '../../../constants.js'\nimport {firstPartyDev} from '../../../environment/local.js'\nimport {ExtendableError} from '../../../error.js'\nimport {randomUUID} from '../../../public/node/crypto.js'\n\nexport class RequestClientError extends ExtendableError {\n statusCode: number\n public constructor(message: string, statusCode: number) {\n super(message)\n this.statusCode = statusCode\n }\n}\n\n/**\n * Removes the sensitive data from the headers and outputs them as a string.\n * @param headers - HTTP headers.\n * @returns A sanitized version of the headers as a string.\n */\nexport function sanitizedHeadersOutput(headers: {[key: string]: string}): string {\n const sanitized: {[key: string]: string} = {}\n const keywords = ['token', 'authorization']\n Object.keys(headers).forEach((header) => {\n if (keywords.find((keyword) => header.toLocaleLowerCase().includes(keyword)) === undefined) {\n sanitized[header] = headers[header]!\n }\n })\n return Object.keys(sanitized)\n .map((header) => {\n return ` - ${header}: ${sanitized[header]}`\n })\n .join('\\n')\n}\n\nexport async function buildHeaders(token?: string): Promise<{[key: string]: string}> {\n const userAgent = `Shopify CLI; v=${await constants.versions.cliKit()}`\n\n const headers: {[header: string]: string} = {\n 'User-Agent': userAgent,\n // 'Sec-CH-UA': secCHUA, This header requires the Git sha.\n 'Sec-CH-UA-PLATFORM': process.platform,\n 'X-Request-Id': randomUUID(),\n 'Content-Type': 'application/json',\n ...(firstPartyDev() && {'X-Shopify-Cli-Employee': '1'}),\n }\n if (token) {\n // eslint-disable-next-line dot-notation\n headers['authorization'] = `Bearer ${token}`\n headers['X-Shopify-Access-Token'] = `Bearer ${token}`\n }\n\n return headers\n}\n"]}
1
+ {"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../../src/private/node/api/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,mCAAmC,CAAA;AACjE,OAAO,EAAC,aAAa,EAAC,MAAM,2CAA2C,CAAA;AACvE,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAC,UAAU,EAAC,MAAM,gCAAgC,CAAA;AAEzD,MAAM,OAAO,kBAAmB,SAAQ,eAAe;IAErD,YAAmB,OAAe,EAAE,UAAkB;QACpD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,SAAS,GAA4B,EAAE,CAAA;IAC7C,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QACtC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,SAAS,EAAE;YAC1F,SAAS,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAE,CAAA;SACrC;IACH,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;SAC1B,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACd,OAAO,MAAM,MAAM,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,CAAA;IAC7C,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,MAAM,SAAS,GAAG,kBAAkB,eAAe,EAAE,CAAA;IAErD,MAAM,OAAO,GAA+B;QAC1C,YAAY,EAAE,SAAS;QACvB,0DAA0D;QAC1D,oBAAoB,EAAE,OAAO,CAAC,QAAQ;QACtC,cAAc,EAAE,UAAU,EAAE;QAC5B,cAAc,EAAE,kBAAkB;QAClC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAC,wBAAwB,EAAE,GAAG,EAAC,CAAC;KACxD,CAAA;IACD,IAAI,KAAK,EAAE;QACT,wCAAwC;QACxC,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAA;QAC5C,OAAO,CAAC,wBAAwB,CAAC,GAAG,UAAU,KAAK,EAAE,CAAA;KACtD;IAED,OAAO,OAAO,CAAA;AAChB,CAAC","sourcesContent":["import {CLI_KIT_VERSION} from '../../../public/common/version.js'\nimport {firstPartyDev} from '../../../public/node/environment/local.js'\nimport {ExtendableError} from '../../../error.js'\nimport {randomUUID} from '../../../public/node/crypto.js'\n\nexport class RequestClientError extends ExtendableError {\n statusCode: number\n public constructor(message: string, statusCode: number) {\n super(message)\n this.statusCode = statusCode\n }\n}\n\n/**\n * Removes the sensitive data from the headers and outputs them as a string.\n * @param headers - HTTP headers.\n * @returns A sanitized version of the headers as a string.\n */\nexport function sanitizedHeadersOutput(headers: {[key: string]: string}): string {\n const sanitized: {[key: string]: string} = {}\n const keywords = ['token', 'authorization']\n Object.keys(headers).forEach((header) => {\n if (keywords.find((keyword) => header.toLocaleLowerCase().includes(keyword)) === undefined) {\n sanitized[header] = headers[header]!\n }\n })\n return Object.keys(sanitized)\n .map((header) => {\n return ` - ${header}: ${sanitized[header]}`\n })\n .join('\\n')\n}\n\nexport function buildHeaders(token?: string): {[key: string]: string} {\n const userAgent = `Shopify CLI; v=${CLI_KIT_VERSION}`\n\n const headers: {[header: string]: string} = {\n 'User-Agent': userAgent,\n // 'Sec-CH-UA': secCHUA, This header requires the Git sha.\n 'Sec-CH-UA-PLATFORM': process.platform,\n 'X-Request-Id': randomUUID(),\n 'Content-Type': 'application/json',\n ...(firstPartyDev() && {'X-Shopify-Cli-Employee': '1'}),\n }\n if (token) {\n // eslint-disable-next-line dot-notation\n headers['authorization'] = `Bearer ${token}`\n headers['X-Shopify-Access-Token'] = `Bearer ${token}`\n }\n\n return headers\n}\n"]}
@@ -1,6 +1,8 @@
1
- import { AdminSession } from '../../../session.js';
1
+ import { AdminSession } from '@shopify/cli-kit/node/session';
2
2
  export declare function restRequestBody<T>(requestBody?: T): string | undefined;
3
- export declare function restRequestUrl(session: AdminSession, apiVersion: string, path: string): string;
4
- export declare function restRequestHeaders(session: AdminSession): Promise<{
3
+ export declare function restRequestUrl(session: AdminSession, apiVersion: string, path: string, searchParams?: {
4
+ [name: string]: string;
5
+ }): string;
6
+ export declare function restRequestHeaders(session: AdminSession): {
5
7
  [key: string]: string;
6
- }>;
8
+ };
@@ -5,16 +5,17 @@ export function restRequestBody(requestBody) {
5
5
  }
6
6
  return JSON.stringify(requestBody);
7
7
  }
8
- export function restRequestUrl(session, apiVersion, path) {
9
- if (isThemeAccessSession(session)) {
10
- return `https://theme-kit-access.shopifyapps.com/cli/admin/api/${apiVersion}${path}.json`;
11
- }
12
- return `https://${session.storeFqdn}/admin/api/${apiVersion}${path}.json`;
8
+ export function restRequestUrl(session, apiVersion, path, searchParams = {}) {
9
+ const url = new URL(isThemeAccessSession(session)
10
+ ? `https://theme-kit-access.shopifyapps.com/cli/admin/api/${apiVersion}${path}.json`
11
+ : `https://${session.storeFqdn}/admin/api/${apiVersion}${path}.json`);
12
+ Object.entries(searchParams).forEach(([name, value]) => url.searchParams.set(name, value));
13
+ return url.toString();
13
14
  }
14
- export async function restRequestHeaders(session) {
15
+ export function restRequestHeaders(session) {
15
16
  const store = session.storeFqdn;
16
17
  const token = session.token;
17
- const headers = await buildHeaders(session.token);
18
+ const headers = buildHeaders(session.token);
18
19
  if (isThemeAccessSession(session)) {
19
20
  headers['X-Shopify-Shop'] = store;
20
21
  headers['X-Shopify-Access-Token'] = token;
@@ -1 +1 @@
1
- {"version":3,"file":"rest.js","sourceRoot":"","sources":["../../../../src/private/node/api/rest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,cAAc,CAAA;AAGzC,MAAM,UAAU,eAAe,CAAI,WAAe;IAChD,IAAI,CAAC,WAAW,EAAE;QAChB,OAAM;KACP;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAqB,EAAE,UAAkB,EAAE,IAAY;IACpF,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE;QACjC,OAAO,0DAA0D,UAAU,GAAG,IAAI,OAAO,CAAA;KAC1F;IAED,OAAO,WAAW,OAAO,CAAC,SAAS,cAAc,UAAU,GAAG,IAAI,OAAO,CAAA;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAqB;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;IAC3B,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAEjD,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE;QACjC,OAAO,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAA;QACjC,OAAO,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAA;KAC1C;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAqB;IACjD,OAAO,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;AAC5C,CAAC","sourcesContent":["import {buildHeaders} from './headers.js'\nimport {AdminSession} from '../../../session.js'\n\nexport function restRequestBody<T>(requestBody?: T) {\n if (!requestBody) {\n return\n }\n return JSON.stringify(requestBody)\n}\n\nexport function restRequestUrl(session: AdminSession, apiVersion: string, path: string) {\n if (isThemeAccessSession(session)) {\n return `https://theme-kit-access.shopifyapps.com/cli/admin/api/${apiVersion}${path}.json`\n }\n\n return `https://${session.storeFqdn}/admin/api/${apiVersion}${path}.json`\n}\n\nexport async function restRequestHeaders(session: AdminSession) {\n const store = session.storeFqdn\n const token = session.token\n const headers = await buildHeaders(session.token)\n\n if (isThemeAccessSession(session)) {\n headers['X-Shopify-Shop'] = store\n headers['X-Shopify-Access-Token'] = token\n }\n\n return headers\n}\n\nfunction isThemeAccessSession(session: AdminSession) {\n return session.token.startsWith('shptka_')\n}\n"]}
1
+ {"version":3,"file":"rest.js","sourceRoot":"","sources":["../../../../src/private/node/api/rest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,cAAc,CAAA;AAGzC,MAAM,UAAU,eAAe,CAAI,WAAe;IAChD,IAAI,CAAC,WAAW,EAAE;QAChB,OAAM;KACP;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAqB,EACrB,UAAkB,EAClB,IAAY,EACZ,eAAyC,EAAE;IAE3C,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,oBAAoB,CAAC,OAAO,CAAC;QAC3B,CAAC,CAAC,0DAA0D,UAAU,GAAG,IAAI,OAAO;QACpF,CAAC,CAAC,WAAW,OAAO,CAAC,SAAS,cAAc,UAAU,GAAG,IAAI,OAAO,CACvE,CAAA;IACD,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;IAE1F,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAqB;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;IAC3B,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAE3C,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE;QACjC,OAAO,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAA;QACjC,OAAO,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAA;KAC1C;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAqB;IACjD,OAAO,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;AAC5C,CAAC","sourcesContent":["import {buildHeaders} from './headers.js'\nimport {AdminSession} from '@shopify/cli-kit/node/session'\n\nexport function restRequestBody<T>(requestBody?: T) {\n if (!requestBody) {\n return\n }\n return JSON.stringify(requestBody)\n}\n\nexport function restRequestUrl(\n session: AdminSession,\n apiVersion: string,\n path: string,\n searchParams: {[name: string]: string} = {},\n) {\n const url = new URL(\n isThemeAccessSession(session)\n ? `https://theme-kit-access.shopifyapps.com/cli/admin/api/${apiVersion}${path}.json`\n : `https://${session.storeFqdn}/admin/api/${apiVersion}${path}.json`,\n )\n Object.entries(searchParams).forEach(([name, value]) => url.searchParams.set(name, value))\n\n return url.toString()\n}\n\nexport function restRequestHeaders(session: AdminSession) {\n const store = session.storeFqdn\n const token = session.token\n const headers = buildHeaders(session.token)\n\n if (isThemeAccessSession(session)) {\n headers['X-Shopify-Shop'] = store\n headers['X-Shopify-Access-Token'] = token\n }\n\n return headers\n}\n\nfunction isThemeAccessSession(session: AdminSession) {\n return session.token.startsWith('shptka_')\n}\n"]}
@@ -0,0 +1,42 @@
1
+ export declare const environmentVariables: {
2
+ alwaysLogAnalytics: string;
3
+ deviceAuth: string;
4
+ enableCliRedirect: string;
5
+ env: string;
6
+ firstPartyDev: string;
7
+ noAnalytics: string;
8
+ partnersToken: string;
9
+ runAsUser: string;
10
+ serviceEnv: string;
11
+ skipCliRedirect: string;
12
+ spinInstance: string;
13
+ themeToken: string;
14
+ unitTest: string;
15
+ verbose: string;
16
+ themeBundling: string;
17
+ codespaceName: string;
18
+ codespaces: string;
19
+ gitpod: string;
20
+ spin: string;
21
+ };
22
+ export declare const pathConstants: {
23
+ executables: {
24
+ dev: string;
25
+ };
26
+ directories: {
27
+ cache: {
28
+ path: () => string;
29
+ vendor: {
30
+ path: () => any;
31
+ binaries: () => any;
32
+ };
33
+ };
34
+ };
35
+ };
36
+ export declare const keychainConstants: {
37
+ service: string;
38
+ };
39
+ export declare const sessionConstants: {
40
+ expirationTimeMarginInMinutes: number;
41
+ };
42
+ export declare const bugsnagApiKey = "9e1e6889176fd0c795d5c659225e0fae";
@@ -0,0 +1,58 @@
1
+ import { join as pathJoin } from '../../path.js';
2
+ import envPaths from 'env-paths';
3
+ const identifier = 'shopify-cli';
4
+ const cacheFolder = () => {
5
+ if (process.env.XDG_CACHE_HOME)
6
+ return process.env.XDG_CACHE_HOME;
7
+ return envPaths(identifier).cache;
8
+ };
9
+ export const environmentVariables = {
10
+ alwaysLogAnalytics: 'SHOPIFY_CLI_ALWAYS_LOG_ANALYTICS',
11
+ deviceAuth: 'SHOPIFY_CLI_DEVICE_AUTH',
12
+ enableCliRedirect: 'SHOPIFY_CLI_ENABLE_CLI_REDIRECT',
13
+ env: 'SHOPIFY_CLI_ENV',
14
+ firstPartyDev: 'SHOPIFY_CLI_1P_DEV',
15
+ noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS',
16
+ partnersToken: 'SHOPIFY_CLI_PARTNERS_TOKEN',
17
+ runAsUser: 'SHOPIFY_RUN_AS_USER',
18
+ serviceEnv: 'SHOPIFY_SERVICE_ENV',
19
+ skipCliRedirect: 'SHOPIFY_CLI_SKIP_CLI_REDIRECT',
20
+ spinInstance: 'SPIN_INSTANCE',
21
+ themeToken: 'SHOPIFY_CLI_THEME_TOKEN',
22
+ unitTest: 'SHOPIFY_UNIT_TEST',
23
+ verbose: 'SHOPIFY_FLAG_VERBOSE',
24
+ themeBundling: 'SHOPIFY_THEME_BUNDLING',
25
+ // Variables to detect if the CLI is running in a cloud environment
26
+ codespaceName: 'CODESPACE_NAME',
27
+ codespaces: 'CODESPACES',
28
+ gitpod: 'GITPOD_WORKSPACE_URL',
29
+ spin: 'SPIN',
30
+ };
31
+ export const pathConstants = {
32
+ executables: {
33
+ dev: '/opt/dev/bin/dev',
34
+ },
35
+ directories: {
36
+ cache: {
37
+ path: () => {
38
+ return cacheFolder();
39
+ },
40
+ vendor: {
41
+ path: () => {
42
+ return pathJoin(cacheFolder(), 'vendor');
43
+ },
44
+ binaries: () => {
45
+ return pathJoin(cacheFolder(), 'vendor', 'binaries');
46
+ },
47
+ },
48
+ },
49
+ },
50
+ };
51
+ export const keychainConstants = {
52
+ service: 'shopify-cli',
53
+ };
54
+ export const sessionConstants = {
55
+ expirationTimeMarginInMinutes: 4,
56
+ };
57
+ export const bugsnagApiKey = '9e1e6889176fd0c795d5c659225e0fae';
58
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/private/node/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,IAAI,QAAQ,EAAC,MAAM,eAAe,CAAA;AAC9C,OAAO,QAAQ,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,GAAG,aAAa,CAAA;AAEhC,MAAM,WAAW,GAAG,GAAG,EAAE;IACvB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IACjE,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,KAAK,CAAA;AACnC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,kBAAkB,EAAE,kCAAkC;IACtD,UAAU,EAAE,yBAAyB;IACrC,iBAAiB,EAAE,iCAAiC;IACpD,GAAG,EAAE,iBAAiB;IACtB,aAAa,EAAE,oBAAoB;IACnC,WAAW,EAAE,0BAA0B;IACvC,aAAa,EAAE,4BAA4B;IAC3C,SAAS,EAAE,qBAAqB;IAChC,UAAU,EAAE,qBAAqB;IACjC,eAAe,EAAE,+BAA+B;IAChD,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,yBAAyB;IACrC,QAAQ,EAAE,mBAAmB;IAC7B,OAAO,EAAE,sBAAsB;IAC/B,aAAa,EAAE,wBAAwB;IACvC,mEAAmE;IACnE,aAAa,EAAE,gBAAgB;IAC/B,UAAU,EAAE,YAAY;IACxB,MAAM,EAAE,sBAAsB;IAC9B,IAAI,EAAE,MAAM;CACb,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,WAAW,EAAE;QACX,GAAG,EAAE,kBAAkB;KACxB;IACD,WAAW,EAAE;QACX,KAAK,EAAE;YACL,IAAI,EAAE,GAAG,EAAE;gBACT,OAAO,WAAW,EAAE,CAAA;YACtB,CAAC;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,GAAG,EAAE;oBACT,OAAO,QAAQ,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAA;gBAC1C,CAAC;gBACD,QAAQ,EAAE,GAAG,EAAE;oBACb,OAAO,QAAQ,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;gBACtD,CAAC;aACF;SACF;KACF;CACF,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,OAAO,EAAE,aAAa;CACvB,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,6BAA6B,EAAE,CAAC;CACjC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,kCAAkC,CAAA","sourcesContent":["import {join as pathJoin} from '../../path.js'\nimport envPaths from 'env-paths'\n\nconst identifier = 'shopify-cli'\n\nconst cacheFolder = () => {\n if (process.env.XDG_CACHE_HOME) return process.env.XDG_CACHE_HOME\n return envPaths(identifier).cache\n}\n\nexport const environmentVariables = {\n alwaysLogAnalytics: 'SHOPIFY_CLI_ALWAYS_LOG_ANALYTICS',\n deviceAuth: 'SHOPIFY_CLI_DEVICE_AUTH',\n enableCliRedirect: 'SHOPIFY_CLI_ENABLE_CLI_REDIRECT',\n env: 'SHOPIFY_CLI_ENV',\n firstPartyDev: 'SHOPIFY_CLI_1P_DEV',\n noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS',\n partnersToken: 'SHOPIFY_CLI_PARTNERS_TOKEN',\n runAsUser: 'SHOPIFY_RUN_AS_USER',\n serviceEnv: 'SHOPIFY_SERVICE_ENV',\n skipCliRedirect: 'SHOPIFY_CLI_SKIP_CLI_REDIRECT',\n spinInstance: 'SPIN_INSTANCE',\n themeToken: 'SHOPIFY_CLI_THEME_TOKEN',\n unitTest: 'SHOPIFY_UNIT_TEST',\n verbose: 'SHOPIFY_FLAG_VERBOSE',\n themeBundling: 'SHOPIFY_THEME_BUNDLING',\n // Variables to detect if the CLI is running in a cloud environment\n codespaceName: 'CODESPACE_NAME',\n codespaces: 'CODESPACES',\n gitpod: 'GITPOD_WORKSPACE_URL',\n spin: 'SPIN',\n}\n\nexport const pathConstants = {\n executables: {\n dev: '/opt/dev/bin/dev',\n },\n directories: {\n cache: {\n path: () => {\n return cacheFolder()\n },\n vendor: {\n path: () => {\n return pathJoin(cacheFolder(), 'vendor')\n },\n binaries: () => {\n return pathJoin(cacheFolder(), 'vendor', 'binaries')\n },\n },\n },\n },\n}\n\nexport const keychainConstants = {\n service: 'shopify-cli',\n}\n\nexport const sessionConstants = {\n expirationTimeMarginInMinutes: 4,\n}\n\nexport const bugsnagApiKey = '9e1e6889176fd0c795d5c659225e0fae'\n"]}
@@ -0,0 +1,18 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * Enum that represents the environment to use for a given service.
4
+ *
5
+ * @readonly
6
+ */
7
+ export declare enum Environment {
8
+ Local = "local",
9
+ Production = "production",
10
+ Spin = "spin"
11
+ }
12
+ /**
13
+ * Returns the environment to use for a given service.
14
+ *
15
+ * @param env - Environment variables.
16
+ * @returns The environment to use for a given service.
17
+ */
18
+ export declare function serviceEnvironment(env?: NodeJS.ProcessEnv): Environment;
@@ -0,0 +1,32 @@
1
+ import { isSpin } from '../../../public/node/environment/spin.js';
2
+ import { environmentVariables } from '../constants.js';
3
+ /**
4
+ * Enum that represents the environment to use for a given service.
5
+ *
6
+ * @readonly
7
+ */
8
+ export var Environment;
9
+ (function (Environment) {
10
+ Environment["Local"] = "local";
11
+ Environment["Production"] = "production";
12
+ Environment["Spin"] = "spin";
13
+ })(Environment || (Environment = {}));
14
+ /**
15
+ * Returns the environment to use for a given service.
16
+ *
17
+ * @param env - Environment variables.
18
+ * @returns The environment to use for a given service.
19
+ */
20
+ export function serviceEnvironment(env = process.env) {
21
+ const value = env[environmentVariables.serviceEnv];
22
+ if (value === 'local') {
23
+ return Environment.Local;
24
+ }
25
+ else if (value === 'spin' || isSpin(env)) {
26
+ return Environment.Spin;
27
+ }
28
+ else {
29
+ return Environment.Production;
30
+ }
31
+ }
32
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../../src/private/node/environment/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,0CAA0C,CAAA;AAC/D,OAAO,EAAC,oBAAoB,EAAC,MAAM,iBAAiB,CAAA;AAEpD;;;;GAIG;AACH,MAAM,CAAN,IAAY,WAIX;AAJD,WAAY,WAAW;IACrB,8BAAe,CAAA;IACf,wCAAyB,CAAA;IACzB,4BAAa,CAAA;AACf,CAAC,EAJW,WAAW,KAAX,WAAW,QAItB;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG;IAClD,MAAM,KAAK,GAAG,GAAG,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAA;IAClD,IAAI,KAAK,KAAK,OAAO,EAAE;QACrB,OAAO,WAAW,CAAC,KAAK,CAAA;KACzB;SAAM,IAAI,KAAK,KAAK,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE;QAC1C,OAAO,WAAW,CAAC,IAAI,CAAA;KACxB;SAAM;QACL,OAAO,WAAW,CAAC,UAAU,CAAA;KAC9B;AACH,CAAC","sourcesContent":["import {isSpin} from '../../../public/node/environment/spin.js'\nimport {environmentVariables} from '../constants.js'\n\n/**\n * Enum that represents the environment to use for a given service.\n *\n * @readonly\n */\nexport enum Environment {\n Local = 'local',\n Production = 'production',\n Spin = 'spin',\n}\n\n/**\n * Returns the environment to use for a given service.\n *\n * @param env - Environment variables.\n * @returns The environment to use for a given service.\n */\nexport function serviceEnvironment(env = process.env): Environment {\n const value = env[environmentVariables.serviceEnv]\n if (value === 'local') {\n return Environment.Local\n } else if (value === 'spin' || isSpin(env)) {\n return Environment.Spin\n } else {\n return Environment.Production\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spin-cache.js","sourceRoot":"","sources":["../../../../src/private/node/environment/spin-cache.ts"],"names":[],"mappings":"AAAA,IAAI,cAAsB,CAAA;AAE1B,MAAM,UAAU,iBAAiB;IAC/B,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,cAAc,GAAG,IAAI,CAAA;AACvB,CAAC","sourcesContent":["let cachedSpinFQDN: string\n\nexport function getCachedSpinFqdn(): string | undefined {\n return cachedSpinFQDN\n}\n\nexport function setCachedSpinFqdn(fqdn: string) {\n cachedSpinFQDN = fqdn\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utilities.js","sourceRoot":"","sources":["../../../../src/private/node/environment/utilities.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,QAA4B;IACnD,IAAI,CAAC,QAAQ,EAAE;QACb,OAAO,KAAK,CAAA;KACb;IACD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,QAA4B;IAChD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACpD,OAAO,KAAK,CAAA;KACb;IACD,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["/**\n * Returns whether an environment variable value represents a truthy value.\n */\nexport function isTruthy(variable: string | undefined): boolean {\n if (!variable) {\n return false\n }\n return ['1', 'true', 'TRUE', 'yes', 'YES'].includes(variable)\n}\n\n/**\n * Returns whether an environment variable has been set and is non-empty\n */\nexport function isSet(variable: string | undefined): boolean {\n if (variable === undefined || variable.trim() === '') {\n return false\n }\n return true\n}\n"]}
@@ -1,11 +1,7 @@
1
- import { Abort } from '../error.js';
1
+ import { Abort } from '../../../error.js';
2
2
  export declare const MismatchStateError: Abort;
3
3
  export interface CodeAuthResult {
4
4
  code: string;
5
5
  codeVerifier: string;
6
6
  }
7
7
  export declare function authorize(scopes: string[], state?: string): Promise<CodeAuthResult>;
8
- export declare function generateRandomChallengePair(): {
9
- codeVerifier: string;
10
- codeChallenge: string;
11
- };
@@ -1,11 +1,11 @@
1
- import { listenRedirect } from './redirect-listener.js';
2
1
  import { clientId } from './identity.js';
3
- import { base64URLEncode, randomBytes, randomHex, sha256 } from '../public/node/crypto.js';
4
- import { open } from '../system.js';
5
- import { Abort, CancelExecution } from '../error.js';
6
- import { identity as identityFqdn } from '../environment/fqdn.js';
7
- import * as output from '../output.js';
8
- import { keypress, terminateBlockingPortProcessPrompt } from '../ui.js';
2
+ import { listenRedirect } from './redirect-listener.js';
3
+ import { base64URLEncode, randomBytes, randomHex, sha256 } from '../../../public/node/crypto.js';
4
+ import { openURL } from '../../../public/node/system.js';
5
+ import { Abort, CancelExecution } from '../../../error.js';
6
+ import { identityFqdn } from '../../../public/node/environment/fqdn.js';
7
+ import * as output from '../../../output.js';
8
+ import { keypress, terminateBlockingPortProcessPrompt } from '../../../ui.js';
9
9
  import { checkPort as isPortAvailable } from 'get-port-please';
10
10
  export const MismatchStateError = new Abort("The state received from the authentication doesn't match the one that initiated the authentication process.");
11
11
  export async function authorize(scopes, state = randomHex(30)) {
@@ -30,14 +30,14 @@ export async function authorize(scopes, state = randomHex(30)) {
30
30
  output.info('👉 Press any key to open the login page on your browser');
31
31
  await keypress();
32
32
  url = `${url}?${new URLSearchParams(params).toString()}`;
33
- await open(url);
33
+ await openURL(url);
34
34
  const result = await listenRedirect(host, port, url);
35
35
  if (result.state !== state) {
36
36
  throw MismatchStateError;
37
37
  }
38
38
  return { code: result.code, codeVerifier };
39
39
  }
40
- export function generateRandomChallengePair() {
40
+ function generateRandomChallengePair() {
41
41
  const codeVerifier = base64URLEncode(randomBytes(32));
42
42
  const codeChallenge = base64URLEncode(sha256(codeVerifier));
43
43
  return { codeVerifier, codeChallenge };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../../../src/private/node/session/authorize.ts"],"names":[],"mappings":"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","sourcesContent":["import {clientId} from './identity.js'\nimport {listenRedirect} from './redirect-listener.js'\nimport {base64URLEncode, randomBytes, randomHex, sha256} from '../../../public/node/crypto.js'\nimport {openURL} from '../../../public/node/system.js'\nimport {Abort, CancelExecution} from '../../../error.js'\nimport {identityFqdn} from '../../../public/node/environment/fqdn.js'\nimport * as output from '../../../output.js'\nimport {keypress, terminateBlockingPortProcessPrompt} from '../../../ui.js'\nimport {checkPort as isPortAvailable} from 'get-port-please'\n\nexport const MismatchStateError = new Abort(\n \"The state received from the authentication doesn't match the one that initiated the authentication process.\",\n)\n\nexport interface CodeAuthResult {\n code: string\n codeVerifier: string\n}\n\nexport async function authorize(scopes: string[], state: string = randomHex(30)): Promise<CodeAuthResult> {\n const port = 3456\n const host = '127.0.0.1'\n const redirectUri = `http://${host}:${port}`\n const fqdn = await identityFqdn()\n const identityClientId = clientId()\n\n await validateRedirectionPortAvailability(port)\n\n let url = `http://${fqdn}/oauth/authorize`\n\n const {codeVerifier, codeChallenge} = generateRandomChallengePair()\n\n const params = {\n client_id: identityClientId,\n scope: scopes.join(' '),\n redirect_uri: redirectUri,\n state,\n response_type: 'code',\n code_challenge_method: 'S256',\n code_challenge: codeChallenge,\n }\n\n output.info('\\nTo run this command, log in to Shopify Partners.')\n output.info('👉 Press any key to open the login page on your browser')\n await keypress()\n\n url = `${url}?${new URLSearchParams(params).toString()}`\n await openURL(url)\n\n const result = await listenRedirect(host, port, url)\n\n if (result.state !== state) {\n throw MismatchStateError\n }\n\n return {code: result.code, codeVerifier}\n}\n\nfunction generateRandomChallengePair() {\n const codeVerifier = base64URLEncode(randomBytes(32))\n const codeChallenge = base64URLEncode(sha256(codeVerifier))\n return {codeVerifier, codeChallenge}\n}\n\nasync function validateRedirectionPortAvailability(port: number) {\n const {killPortProcess} = await import('kill-port-process')\n\n if (await isPortAvailable(port)) {\n return\n }\n\n if (await terminateBlockingPortProcessPrompt(port, 'Authentication')) {\n await killPortProcess(port)\n } else {\n throw new CancelExecution()\n }\n}\n"]}
@@ -1,12 +1,9 @@
1
1
  import { clientId } from './identity.js';
2
2
  import { exchangeDeviceCodeForAccessToken } from './exchange.js';
3
- import { identity as identityFqdn } from '../environment/fqdn.js';
4
- import { shopifyFetch } from '../http.js';
5
- import { content, debug, info, token } from '../output.js';
6
- import { Bug } from '../error.js';
7
- const DeviceAuthError = () => {
8
- return new Bug('Failed to start authorization process');
9
- };
3
+ import { identityFqdn } from '../../../public/node/environment/fqdn.js';
4
+ import { shopifyFetch } from '../../../http.js';
5
+ import { content, debug, info, token } from '../../../output.js';
6
+ import { Bug } from '../../../error.js';
10
7
  /**
11
8
  * Initiate a device authorization flow.
12
9
  * This will return a DeviceAuthorizationResponse containing the URL where user
@@ -30,8 +27,9 @@ export async function requestDeviceAuthorization(scopes) {
30
27
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
28
  const jsonResult = await response.json();
32
29
  debug(content `Received device authorization code: ${token.json(jsonResult)}`);
33
- if (!jsonResult.device_code || !jsonResult.verification_uri_complete)
34
- throw DeviceAuthError();
30
+ if (!jsonResult.device_code || !jsonResult.verification_uri_complete) {
31
+ throw new Bug('Failed to start authorization process');
32
+ }
35
33
  info('\nTo run this command, log in to Shopify Partners.');
36
34
  info(content `User verification code: ${jsonResult.user_code}`);
37
35
  info(content `👉 Open this link to start the auth process: ${token.green(jsonResult.verification_uri_complete)}`);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-authorization.js","sourceRoot":"","sources":["../../../../src/private/node/session/device-authorization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AACtC,OAAO,EAAC,gCAAgC,EAAC,MAAM,eAAe,CAAA;AAE9D,OAAO,EAAC,YAAY,EAAC,MAAM,0CAA0C,CAAA;AACrE,OAAO,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAC,MAAM,oBAAoB,CAAA;AAC9D,OAAO,EAAC,GAAG,EAAC,MAAM,mBAAmB,CAAA;AAWrC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,MAAgB;IAC/D,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAA;IACjC,MAAM,gBAAgB,GAAG,MAAM,QAAQ,EAAE,CAAA;IACzC,MAAM,WAAW,GAAG,EAAC,SAAS,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAC,CAAA;IAC1E,MAAM,GAAG,GAAG,WAAW,IAAI,6BAA6B,CAAA;IAExD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE;QACvC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAC,cAAc,EAAE,mCAAmC,EAAC;QAC9D,IAAI,EAAE,sBAAsB,CAAC,WAAW,CAAC;KAC1C,CAAC,CAAA;IAEF,8DAA8D;IAC9D,MAAM,UAAU,GAAQ,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IAE7C,KAAK,CAAC,OAAO,CAAA,uCAAuC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IAC7E,IAAI,CAAC,UAAU,CAAC,WAAW,IAAI,CAAC,UAAU,CAAC,yBAAyB,EAAE;QACpE,MAAM,IAAI,GAAG,CAAC,uCAAuC,CAAC,CAAA;KACvD;IAED,IAAI,CAAC,oDAAoD,CAAC,CAAA;IAC1D,IAAI,CAAC,OAAO,CAAA,2BAA2B,UAAU,CAAC,SAAS,EAAE,CAAC,CAAA;IAC9D,IAAI,CAAC,OAAO,CAAA,gDAAgD,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,yBAAyB,CAAC,EAAE,CAAC,CAAA;IAEhH,OAAO;QACL,UAAU,EAAE,UAAU,CAAC,WAAW;QAClC,QAAQ,EAAE,UAAU,CAAC,SAAS;QAC9B,eAAe,EAAE,UAAU,CAAC,gBAAgB;QAC5C,SAAS,EAAE,UAAU,CAAC,UAAU;QAChC,uBAAuB,EAAE,UAAU,CAAC,yBAAyB;QAC7D,QAAQ,EAAE,UAAU,CAAC,QAAQ;KAC9B,CAAA;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,IAAY,EAAE,QAAQ,GAAG,CAAC;IACzE,IAAI,wBAAwB,GAAG,QAAQ,CAAA;IAEvC,OAAO,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACpD,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;YACxB,MAAM,MAAM,GAAG,MAAM,gCAAgC,CAAC,IAAI,CAAC,CAAA;YAC3D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;gBAAE,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAEjD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,iBAAiB,CAAA;YAE/C,KAAK,CAAC,OAAO,CAAA,+CAA+C,KAAK,EAAE,CAAC,CAAA;YACpE,QAAQ,KAAK,EAAE;gBACb,KAAK,uBAAuB;oBAC1B,OAAO,YAAY,EAAE,CAAA;gBACvB,KAAK,WAAW;oBACd,wBAAwB,IAAI,CAAC,CAAA;oBAC7B,OAAO,YAAY,EAAE,CAAA;gBACvB,KAAK,eAAe,CAAC;gBACrB,KAAK,eAAe,CAAC;gBACrB,KAAK,iBAAiB;oBACpB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;aACxB;QACH,CAAC,CAAA;QAED,MAAM,YAAY,GAAG,GAAG,EAAE;YACxB,kEAAkE;YAClE,UAAU,CAAC,MAAM,EAAE,wBAAwB,GAAG,IAAI,CAAC,CAAA;QACrD,CAAC,CAAA;QAED,YAAY,EAAE,CAAA;IAChB,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,WAA+C;IAC7E,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;SAC/B,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;SACjD,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;SACvC,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC","sourcesContent":["import {clientId} from './identity.js'\nimport {exchangeDeviceCodeForAccessToken} from './exchange.js'\nimport {IdentityToken} from './schema.js'\nimport {identityFqdn} from '../../../public/node/environment/fqdn.js'\nimport {shopifyFetch} from '../../../http.js'\nimport {content, debug, info, token} from '../../../output.js'\nimport {Bug} from '../../../error.js'\n\nexport interface DeviceAuthorizationResponse {\n deviceCode: string\n userCode: string\n verificationUri: string\n expiresIn: number\n verificationUriComplete?: string\n interval?: number\n}\n\n/**\n * Initiate a device authorization flow.\n * This will return a DeviceAuthorizationResponse containing the URL where user\n * should go to authorize the device without the need of a callback to the CLI.\n *\n * Also returns a `deviceCode` used for polling the token endpoint in the next step.\n *\n * @param scopes - The scopes to request\n * @returns An object with the device authorization response.\n */\nexport async function requestDeviceAuthorization(scopes: string[]): Promise<DeviceAuthorizationResponse> {\n const fqdn = await identityFqdn()\n const identityClientId = await clientId()\n const queryParams = {client_id: identityClientId, scope: scopes.join(' ')}\n const url = `https://${fqdn}/oauth/device_authorization`\n\n const response = await shopifyFetch(url, {\n method: 'POST',\n headers: {'Content-type': 'application/x-www-form-urlencoded'},\n body: convertRequestToParams(queryParams),\n })\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const jsonResult: any = await response.json()\n\n debug(content`Received device authorization code: ${token.json(jsonResult)}`)\n if (!jsonResult.device_code || !jsonResult.verification_uri_complete) {\n throw new Bug('Failed to start authorization process')\n }\n\n info('\\nTo run this command, log in to Shopify Partners.')\n info(content`User verification code: ${jsonResult.user_code}`)\n info(content`👉 Open this link to start the auth process: ${token.green(jsonResult.verification_uri_complete)}`)\n\n return {\n deviceCode: jsonResult.device_code,\n userCode: jsonResult.user_code,\n verificationUri: jsonResult.verification_uri,\n expiresIn: jsonResult.expires_in,\n verificationUriComplete: jsonResult.verification_uri_complete,\n interval: jsonResult.interval,\n }\n}\n\n/**\n * Poll the Oauth token endpoint with the device code obtained from a DeviceAuthorizationResponse.\n * The endpoint will return `authorization_pending` until the user completes the auth flow in the browser.\n * Once the user completes the auth flow, the endpoint will return the identity token.\n *\n * Timeout for the polling is defined by the server and is around 600 seconds.\n *\n * @param code - The device code obtained after starting a device identity flow\n * @param interval - The interval to poll the token endpoint\n * @returns The identity token\n */\nexport async function pollForDeviceAuthorization(code: string, interval = 5): Promise<IdentityToken> {\n let currentIntervalInSeconds = interval\n\n return new Promise<IdentityToken>((resolve, reject) => {\n const onPoll = async () => {\n const result = await exchangeDeviceCodeForAccessToken(code)\n if (!result.isErr()) return resolve(result.value)\n\n const error = result.error ?? 'unknown_failure'\n\n debug(content`Polling for device authorization... status: ${error}`)\n switch (error) {\n case 'authorization_pending':\n return startPolling()\n case 'slow_down':\n currentIntervalInSeconds += 5\n return startPolling()\n case 'access_denied':\n case 'expired_token':\n case 'unknown_failure':\n return reject(result)\n }\n }\n\n const startPolling = () => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(onPoll, currentIntervalInSeconds * 1000)\n }\n\n startPolling()\n })\n}\n\nfunction convertRequestToParams(queryParams: {client_id: string; scope: string}): string {\n return Object.entries(queryParams)\n .map(([key, value]) => value && `${key}=${value}`)\n .filter((hasValue) => Boolean(hasValue))\n .join('&')\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { ApplicationToken, IdentityToken } from './schema.js';
2
2
  import { CodeAuthResult } from './authorize.js';
3
- import { Result } from '../public/node/result.js';
4
- import { ExtendableError } from '../error.js';
3
+ import { Result } from '../../../public/node/result.js';
4
+ import { ExtendableError } from '../../../error.js';
5
5
  export declare class InvalidGrantError extends ExtendableError {
6
6
  }
7
7
  export declare class InvalidRequestError extends ExtendableError {
@@ -1,9 +1,9 @@
1
1
  import { applicationId, clientId as getIdentityClientId } from './identity.js';
2
- import { identity as identityFqdn } from '../environment/fqdn.js';
3
- import { shopifyFetch } from '../http.js';
4
- import { err, ok } from '../public/node/result.js';
5
- import { AbortError } from '../public/node/error.js';
6
- import { ExtendableError } from '../error.js';
2
+ import { identityFqdn } from '../../../public/node/environment/fqdn.js';
3
+ import { shopifyFetch } from '../../../http.js';
4
+ import { err, ok } from '../../../public/node/result.js';
5
+ import { AbortError } from '../../../public/node/error.js';
6
+ import { ExtendableError } from '../../../error.js';
7
7
  export class InvalidGrantError extends ExtendableError {
8
8
  }
9
9
  export class InvalidRequestError extends ExtendableError {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../../../src/private/node/session/exchange.ts"],"names":[],"mappings":"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","sourcesContent":["import {ApplicationToken, IdentityToken} from './schema.js'\nimport {applicationId, clientId as getIdentityClientId} from './identity.js'\nimport {CodeAuthResult} from './authorize.js'\nimport {API} from '../../../network/api.js'\nimport {identityFqdn} from '../../../public/node/environment/fqdn.js'\nimport {shopifyFetch} from '../../../http.js'\nimport {err, ok, Result} from '../../../public/node/result.js'\nimport {AbortError} from '../../../public/node/error.js'\nimport {ExtendableError} from '../../../error.js'\n\nexport class InvalidGrantError extends ExtendableError {}\nexport class InvalidRequestError extends ExtendableError {}\n\nexport interface ExchangeScopes {\n admin: string[]\n partners: string[]\n storefront: string[]\n}\n/**\n * Given a valid authorization code, request an identity access token.\n * This token can then be used to get API specific tokens.\n * @param codeData - code and codeVerifier from the authorize endpoint\n * @returns An instance with the identity access tokens.\n */\nexport async function exchangeCodeForAccessToken(codeData: CodeAuthResult): Promise<IdentityToken> {\n const clientId = await getIdentityClientId()\n const params = {\n grant_type: 'authorization_code',\n code: codeData.code,\n redirect_uri: 'http://127.0.0.1:3456',\n client_id: clientId,\n code_verifier: codeData.codeVerifier,\n }\n\n const tokenResult = await tokenRequest(params)\n const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug()\n return buildIdentityToken(value)\n}\n\n/**\n * Given an identity token, request an application token.\n * @param identityToken - access token obtained in a previous step\n * @param store - the store to use, only needed for admin API\n * @returns An array with the application access tokens.\n */\nexport async function exchangeAccessForApplicationTokens(\n identityToken: IdentityToken,\n scopes: ExchangeScopes,\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const token = identityToken.accessToken\n\n const [partners, storefront] = await Promise.all([\n requestAppToken('partners', token, scopes.partners),\n requestAppToken('storefront-renderer', token, scopes.storefront),\n ])\n\n const result = {\n ...partners,\n ...storefront,\n }\n\n if (store) {\n const admin = await requestAppToken('admin', token, scopes.admin, store)\n Object.assign(result, admin)\n }\n return result\n}\n\n/**\n * Given an expired access token, refresh it to get a new one.\n */\nexport async function refreshAccessToken(currentToken: IdentityToken): Promise<IdentityToken> {\n const clientId = getIdentityClientId()\n const params = {\n grant_type: 'refresh_token',\n access_token: currentToken.accessToken,\n refresh_token: currentToken.refreshToken,\n client_id: clientId,\n }\n const tokenResult = await tokenRequest(params)\n const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug()\n return buildIdentityToken(value)\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid partners API token\n * This token does not accept extra scopes, just the cli one.\n * @param token - The CLI token passed as ENV variable\n * @returns An instance with the application access tokens.\n */\nexport async function exchangeCustomPartnerToken(token: string): Promise<ApplicationToken> {\n const appId = applicationId('partners')\n const newToken = await requestAppToken('partners', token, ['https://api.shopify.com/auth/partners.app.cli.access'])\n return newToken[appId]!\n}\n\nexport type IdentityDeviceError =\n | 'authorization_pending'\n | 'access_denied'\n | 'expired_token'\n | 'slow_down'\n | 'unknown_failure'\n\n/**\n * Given a deviceCode obtained after starting a device identity flow, request an identity token.\n * @param deviceCode - The device code obtained after starting a device identity flow\n * @param scopes - The scopes to request\n * @returns An instance with the identity access tokens.\n */\nexport async function exchangeDeviceCodeForAccessToken(\n deviceCode: string,\n): Promise<Result<IdentityToken, IdentityDeviceError>> {\n const clientId = await getIdentityClientId()\n\n const params = {\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceCode,\n client_id: clientId,\n }\n\n const tokenResult = await tokenRequest(params)\n if (tokenResult.isErr()) {\n return err(tokenResult.error as IdentityDeviceError)\n }\n const identityToken = buildIdentityToken(tokenResult.value)\n return ok(identityToken)\n}\n\nasync function requestAppToken(\n api: API,\n token: string,\n scopes: string[] = [],\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const appId = applicationId(api)\n const clientId = await getIdentityClientId()\n\n const params = {\n grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',\n requested_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n subject_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n client_id: clientId,\n audience: appId,\n scope: scopes.join(' '),\n subject_token: token,\n ...(api === 'admin' && {destination: `https://${store}/admin`}),\n }\n\n let identifier = appId\n if (api === 'admin' && store) {\n identifier = `${store}-${appId}`\n }\n const tokenResult = await tokenRequest(params)\n const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug()\n const appToken = await buildApplicationToken(value)\n return {[identifier]: appToken}\n}\n\ninterface TokenRequestResult {\n access_token: string\n expires_in: number\n refresh_token: string\n scope: string\n}\n\nfunction tokenRequestErrorHandler(error: string) {\n if (error === 'invalid_grant') {\n // There's an scenario when Identity returns \"invalid_grant\" when trying to refresh the token\n // using a valid refresh token. When that happens, we take the user through the authentication flow.\n return new InvalidGrantError()\n }\n if (error === 'invalid_request') {\n // There's an scenario when Identity returns \"invalid_request\" when exchanging an identity token.\n // This means the token is invalid. We clear the session and throw an error to let the caller know.\n return new InvalidRequestError()\n }\n return new AbortError(error)\n}\n\nasync function tokenRequest(params: {[key: string]: string}): Promise<Result<TokenRequestResult, string>> {\n const fqdn = await identityFqdn()\n const url = new URL(`https://${fqdn}/oauth/token`)\n url.search = new URLSearchParams(Object.entries(params)).toString()\n const res = await shopifyFetch(url.href, {method: 'POST'})\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const payload: any = await res.json()\n\n if (res.ok) return ok(payload)\n return err(payload.error)\n}\n\nfunction buildIdentityToken(result: TokenRequestResult): IdentityToken {\n return {\n accessToken: result.access_token,\n refreshToken: result.refresh_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n }\n}\n\nfunction buildApplicationToken(result: TokenRequestResult): ApplicationToken {\n return {\n accessToken: result.access_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
- import { identity } from '../environment/fqdn.js';
2
- import { debug } from '../output.js';
3
- import { shopifyFetch } from '../http.js';
1
+ import { identityFqdn } from '../../../public/node/environment/fqdn.js';
2
+ import { debug } from '../../../output.js';
3
+ import { shopifyFetch } from '../../../http.js';
4
4
  export async function validateIdentityToken(token) {
5
5
  try {
6
6
  const instrospectionURL = await getInstrospectionEndpoint();
@@ -33,7 +33,7 @@ export async function validateIdentityToken(token) {
33
33
  }
34
34
  }
35
35
  async function getInstrospectionEndpoint() {
36
- const response = await shopifyFetch(`https://${await identity()}/.well-known/openid-configuration.json`);
36
+ const response = await shopifyFetch(`https://${await identityFqdn()}/.well-known/openid-configuration.json`);
37
37
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
38
  const json = await response.json();
39
39
  return json.introspection_endpoint;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-token-validation.js","sourceRoot":"","sources":["../../../../src/private/node/session/identity-token-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,0CAA0C,CAAA;AACrE,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAA;AACxC,OAAO,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAA;AAE7C,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAa;IACvD,IAAI;QACF,MAAM,iBAAiB,GAAG,MAAM,yBAAyB,EAAE,CAAA;QAC3D,MAAM,OAAO,GAAG;YACd,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAC,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAC;YAC/E,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAC,KAAK,EAAC,CAAC;SAC9B,CAAA;QACD,KAAK,CAAC,kDAAkD,iBAAiB,EAAE,CAAC,CAAA;QAE5E,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA;QAE/D,IAAI,QAAQ,CAAC,EAAE,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE;YACzE,8DAA8D;YAC9D,MAAM,IAAI,GAAQ,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;YACvC,KAAK,CAAC,gCAAgC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;YACnD,OAAO,IAAI,CAAC,KAAK,CAAA;SAClB;aAAM;YACL,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;YAClC,KAAK,CAAC;aACC,QAAQ,CAAC,MAAM;8BACE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;WAC3E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC5B,OAAO,KAAK,CAAA;SACb;QACD,qDAAqD;KACtD;IAAC,OAAO,KAAK,EAAE;QACd,KAAK,CAAC,kCAAkC,KAAK,EAAE,CAAC,CAAA;QAChD,OAAO,KAAK,CAAA;KACb;AACH,CAAC;AAED,KAAK,UAAU,yBAAyB;IACtC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,WAAW,MAAM,YAAY,EAAE,wCAAwC,CAAC,CAAA;IAC5G,8DAA8D;IAC9D,MAAM,IAAI,GAAQ,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IACvC,OAAO,IAAI,CAAC,sBAAsB,CAAA;AACpC,CAAC","sourcesContent":["import {identityFqdn} from '../../../public/node/environment/fqdn.js'\nimport {debug} from '../../../output.js'\nimport {shopifyFetch} from '../../../http.js'\n\nexport async function validateIdentityToken(token: string) {\n try {\n const instrospectionURL = await getInstrospectionEndpoint()\n const options = {\n method: 'POST',\n headers: {Authorization: `Bearer ${token}`, 'Content-Type': 'application/json'},\n body: JSON.stringify({token}),\n }\n debug(`Sending Identity Introspection request to URL: ${instrospectionURL}`)\n\n const response = await shopifyFetch(instrospectionURL, options)\n\n if (response.ok && response.headers.get('content-type')?.includes('json')) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const json: any = await response.json()\n debug(`The identity token is valid: ${json.valid}`)\n return json.valid\n } else {\n const text = await response.text()\n debug(`The Introspection request failed with:\n - status: ${response.status}\n - www-authenticate header: ${JSON.stringify(response.headers.get('www-authenticate'))}\n - body: ${JSON.stringify(text)}`)\n return false\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n debug(`The identity token is invalid: ${error}`)\n return false\n }\n}\n\nasync function getInstrospectionEndpoint(): Promise<string> {\n const response = await shopifyFetch(`https://${await identityFqdn()}/.well-known/openid-configuration.json`)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const json: any = await response.json()\n return json.introspection_endpoint\n}\n"]}
@@ -1,3 +1,3 @@
1
- import { API } from '../network/api.js';
1
+ import { API } from '../../../network/api.js';
2
2
  export declare function clientId(): string;
3
3
  export declare function applicationId(api: API): string;
@@ -1,6 +1,5 @@
1
- import { Bug } from '../error.js';
2
- import { Environment } from '../network/service.js';
3
- import { serviceEnvironment } from '../environment/service.js';
1
+ import { Bug } from '../../../error.js';
2
+ import { Environment, serviceEnvironment } from '../environment/service.js';
4
3
  export function clientId() {
5
4
  const environment = serviceEnvironment();
6
5
  if (environment === Environment.Local) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../../src/private/node/session/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,mBAAmB,CAAA;AAErC,OAAO,EAAC,WAAW,EAAE,kBAAkB,EAAC,MAAM,2BAA2B,CAAA;AAEzE,MAAM,UAAU,QAAQ;IACtB,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;IACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;QACrC,OAAO,sCAAsC,CAAA;KAC9C;SAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;QACjD,OAAO,sCAAsC,CAAA;KAC9C;SAAM;QACL,OAAO,sCAAsC,CAAA;KAC9C;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,QAAQ,GAAG,EAAE;QACX,KAAK,OAAO,CAAC,CAAC;YACZ,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;YACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;gBACrC,OAAO,kEAAkE,CAAA;aAC1E;iBAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;gBACjD,OAAO,kEAAkE,CAAA;aAC1E;iBAAM;gBACL,OAAO,kEAAkE,CAAA;aAC1E;SACF;QACD,KAAK,UAAU,CAAC,CAAC;YACf,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;YACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;gBACrC,OAAO,kEAAkE,CAAA;aAC1E;iBAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;gBACjD,OAAO,kEAAkE,CAAA;aAC1E;iBAAM;gBACL,OAAO,kEAAkE,CAAA;aAC1E;SACF;QACD,KAAK,qBAAqB,CAAC,CAAC;YAC1B,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAA;YACxC,IAAI,WAAW,KAAK,WAAW,CAAC,KAAK,EAAE;gBACrC,OAAO,sCAAsC,CAAA;aAC9C;iBAAM,IAAI,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE;gBACjD,OAAO,sCAAsC,CAAA;aAC9C;iBAAM;gBACL,OAAO,sCAAsC,CAAA;aAC9C;SACF;QACD;YACE,MAAM,IAAI,GAAG,CAAC,mCAAmC,GAAG,EAAE,CAAC,CAAA;KAC1D;AACH,CAAC","sourcesContent":["import {Bug} from '../../../error.js'\nimport {API} from '../../../network/api.js'\nimport {Environment, serviceEnvironment} from '../environment/service.js'\n\nexport function clientId(): string {\n const environment = serviceEnvironment()\n if (environment === Environment.Local) {\n return 'e5380e02-312a-7408-5718-e07017e9cf52'\n } else if (environment === Environment.Production) {\n return 'fbdb2649-e327-4907-8f67-908d24cfd7e3'\n } else {\n return 'e5380e02-312a-7408-5718-e07017e9cf52'\n }\n}\n\nexport function applicationId(api: API): string {\n switch (api) {\n case 'admin': {\n const environment = serviceEnvironment()\n if (environment === Environment.Local) {\n return 'e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52'\n } else if (environment === Environment.Production) {\n return '7ee65a63608843c577db8b23c4d7316ea0a01bd2f7594f8a9c06ea668c1b775c'\n } else {\n return 'e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52'\n }\n }\n case 'partners': {\n const environment = serviceEnvironment()\n if (environment === Environment.Local) {\n return 'df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978'\n } else if (environment === Environment.Production) {\n return '271e16d403dfa18082ffb3d197bd2b5f4479c3fc32736d69296829cbb28d41a6'\n } else {\n return 'df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978'\n }\n }\n case 'storefront-renderer': {\n const environment = serviceEnvironment()\n if (environment === Environment.Local) {\n return '46f603de-894f-488d-9471-5b721280ff49'\n } else if (environment === Environment.Production) {\n return 'ee139b3d-5861-4d45-b387-1bc3ada7811c'\n } else {\n return '46f603de-894f-488d-9471-5b721280ff49'\n }\n }\n default:\n throw new Bug(`Application id for API of type: ${api}`)\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { Bug } from '../error.js';
1
+ import { Bug } from '../../../error.js';
2
2
  export declare const getEmptyUrlHTML: () => Promise<string>;
3
3
  export declare const getAuthErrorHTML: () => Promise<string>;
4
4
  export declare const getMissingCodeHTML: () => Promise<string>;
@@ -1,6 +1,6 @@
1
- import { findUp, moduleDirectory } from '../path.js';
2
- import { read } from '../file.js';
3
- import { Bug } from '../error.js';
1
+ import { findUp, moduleDirectory } from '../../../path.js';
2
+ import { readFile } from '../../../public/node/fs.js';
3
+ import { Bug } from '../../../error.js';
4
4
  const HTMLFileNames = [
5
5
  'empty-url.html',
6
6
  'auth-error.html',
@@ -28,31 +28,31 @@ const getFilePath = async (fileName) => {
28
28
  };
29
29
  export const getEmptyUrlHTML = async () => {
30
30
  const filePath = await getFilePath(HTMLFileNames[0]);
31
- return read(filePath);
31
+ return readFile(filePath);
32
32
  };
33
33
  export const getAuthErrorHTML = async () => {
34
34
  const filePath = await getFilePath(HTMLFileNames[1]);
35
- return read(filePath);
35
+ return readFile(filePath);
36
36
  };
37
37
  export const getMissingCodeHTML = async () => {
38
38
  const filePath = await getFilePath(HTMLFileNames[2]);
39
- return read(filePath);
39
+ return readFile(filePath);
40
40
  };
41
41
  export const getMissingStateHTML = async () => {
42
42
  const filePath = await getFilePath(HTMLFileNames[3]);
43
- return read(filePath);
43
+ return readFile(filePath);
44
44
  };
45
45
  export const getSuccessHTML = async () => {
46
46
  const filePath = await getFilePath(HTMLFileNames[4]);
47
- return read(filePath);
47
+ return readFile(filePath);
48
48
  };
49
49
  export const getStylesheet = async () => {
50
50
  const filePath = await getFilePath(StylesheetFilename);
51
- return read(filePath);
51
+ return readFile(filePath);
52
52
  };
53
53
  export const getFavicon = async () => {
54
54
  const filePath = await getFilePath(FaviconFileName);
55
- return read(filePath);
55
+ return readFile(filePath);
56
56
  };
57
57
  export const EmptyUrlString = 'We received the authentication redirect but the URL is empty.';
58
58
  export const AuthErrorString = 'There was an issue while trying to authenticate.';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-auth.js","sourceRoot":"","sources":["../../../../src/private/node/session/post-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,eAAe,EAAC,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAC,QAAQ,EAAC,MAAM,4BAA4B,CAAA;AACnD,OAAO,EAAC,GAAG,EAAC,MAAM,mBAAmB,CAAA;AAErC,MAAM,aAAa,GAAG;IACpB,gBAAgB;IAChB,iBAAiB;IACjB,mBAAmB;IACnB,oBAAoB;IACpB,cAAc;CACN,CAAA;AACV,MAAM,kBAAkB,GAAG,WAAW,CAAA;AACtC,MAAM,eAAe,GAAG,aAAa,CAAA;AAErC;;;;;GAKG;AACH,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAmB,EAAE;IAC9D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,QAAQ,EAAE,EAAE;QAClD,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;KACtC,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,8BAA8B,EAAE,CAAA;KACvC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAqB,EAAE;IACzD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAAqB,EAAE;IAC1D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,IAAqB,EAAE;IAC5D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,IAAqB,EAAE;IAC7D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,IAAqB,EAAE;IACxD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,IAAqB,EAAE;IACvD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAA;IACtD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,IAAqB,EAAE;IACpD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,CAAA;IACnD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,+DAA+D,CAAA;AAE7F,MAAM,CAAC,MAAM,eAAe,GAAG,kDAAkD,CAAA;AAEjF,MAAM,CAAC,MAAM,iBAAiB,GAAG,kFAAkF,CAAA;AAEnH,MAAM,CAAC,MAAM,kBAAkB,GAAG,mFAAmF,CAAA;AAErH,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,+BAA+B,CAAC,CAAA","sourcesContent":["import {findUp, moduleDirectory} from '../../../path.js'\nimport {readFile} from '../../../public/node/fs.js'\nimport {Bug} from '../../../error.js'\n\nconst HTMLFileNames = [\n 'empty-url.html',\n 'auth-error.html',\n 'missing-code.html',\n 'missing-state.html',\n 'success.html',\n] as const\nconst StylesheetFilename = 'style.css'\nconst FaviconFileName = 'favicon.svg'\n\n/**\n * Finds the full path of the given file-name from the assets folder.\n *\n * @param fileName - The name of the file to look for.\n * @returns The full path of the file, or null if not found.\n */\nconst getFilePath = async (fileName: string): Promise<string> => {\n const filePath = await findUp(`assets/${fileName}`, {\n type: 'file',\n cwd: moduleDirectory(import.meta.url),\n })\n if (!filePath) {\n throw RedirectPageAssetNotFoundError()\n }\n return filePath\n}\n\nexport const getEmptyUrlHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[0])\n return readFile(filePath)\n}\n\nexport const getAuthErrorHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[1])\n return readFile(filePath)\n}\n\nexport const getMissingCodeHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[2])\n return readFile(filePath)\n}\n\nexport const getMissingStateHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[3])\n return readFile(filePath)\n}\n\nexport const getSuccessHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[4])\n return readFile(filePath)\n}\n\nexport const getStylesheet = async (): Promise<string> => {\n const filePath = await getFilePath(StylesheetFilename)\n return readFile(filePath)\n}\n\nexport const getFavicon = async (): Promise<string> => {\n const filePath = await getFilePath(FaviconFileName)\n return readFile(filePath)\n}\n\nexport const EmptyUrlString = 'We received the authentication redirect but the URL is empty.'\n\nexport const AuthErrorString = 'There was an issue while trying to authenticate.'\n\nexport const MissingCodeString = \"The authentication can't continue because the redirect doesn't include the code.\"\n\nexport const MissingStateString = \"The authentication can't continue because the redirect doesn't include the state.\"\n\nexport const RedirectPageAssetNotFoundError = () => new Bug(`Redirect page asset not found`)\n"]}
@@ -1,6 +1,6 @@
1
1
  import { getFavicon, getStylesheet, getEmptyUrlHTML, getAuthErrorHTML, getMissingCodeHTML, getMissingStateHTML, getSuccessHTML, EmptyUrlString, MissingCodeString, MissingStateString, } from './post-auth.js';
2
- import { Abort, Bug } from '../error.js';
3
- import { content, info, token } from '../output.js';
2
+ import { Abort, Bug } from '../../../error.js';
3
+ import { content, info, token } from '../../../output.js';
4
4
  import { createApp } from 'h3';
5
5
  import url from 'url';
6
6
  import { createServer } from 'http';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect-listener.js","sourceRoot":"","sources":["../../../../src/private/node/session/redirect-listener.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getFavicon,\n getStylesheet,\n getEmptyUrlHTML,\n getAuthErrorHTML,\n getMissingCodeHTML,\n getMissingStateHTML,\n getSuccessHTML,\n EmptyUrlString,\n MissingCodeString,\n MissingStateString,\n} from './post-auth.js'\nimport {Abort, Bug} from '../../../error.js'\nimport {content, info, token} from '../../../output.js'\nimport {createApp, IncomingMessage, ServerResponse} from 'h3'\nimport url from 'url'\nimport {createServer, Server} from 'http'\n\nconst ResponseTimeoutSeconds = 10\nconst ServerStopDelaySeconds = 0.5\n\n/**\n * It represents the result of a redirect.\n */\ntype RedirectCallback = (error: Error | undefined, state: string | undefined, code: string | undefined) => void\n\n/**\n * Defines the interface of the options that\n * are used to instantiate a redirect listener.\n */\ninterface RedirectListenerOptions {\n host: string\n port: number\n callback: RedirectCallback\n}\n/**\n * When the authentication completes, Identity redirects\n * the user to a URL. In the case of the CLI, the redirect\n * is to localhost passing some parameters that are necessary\n * to continue the authentication. Because of that, we need\n * an HTTP server that runs and listens to the request.\n */\nexport class RedirectListener {\n private static createServer(callback: RedirectCallback): Server {\n const app = createApp().use('*', async (request: IncomingMessage, response: ServerResponse) => {\n const requestUrl = request.url\n if (requestUrl?.includes('favicon')) {\n const faviconFile = await getFavicon()\n response.setHeader('Content-Type', 'image/svg+xml')\n response.write(faviconFile)\n response.end()\n return {}\n } else if (requestUrl === '/style.css') {\n const stylesheetFile = await getStylesheet()\n response.setHeader('Content-Type', 'text/css')\n response.write(stylesheetFile)\n response.end()\n return {}\n }\n\n const respond = async (contents: string, error?: Error, state?: string, code?: string) => {\n response.setHeader('Content-Type', 'text/html')\n response.write(contents)\n response.end()\n callback(error, state, code)\n return {}\n }\n\n // If there was an empty/malformed URL sent back.\n if (!requestUrl) {\n const file = await getEmptyUrlHTML()\n const err = new Bug(EmptyUrlString)\n return respond(file, err, undefined, undefined)\n }\n\n // If an error was returned by the Identity server.\n const queryObject = url.parse(requestUrl, true).query\n if (queryObject.error && queryObject.error_description) {\n const file = await getAuthErrorHTML()\n const err = new Abort(`${queryObject.error_description}`)\n return respond(file, err, undefined, undefined)\n }\n\n // If the code isn't present in the URL.\n if (!queryObject.code) {\n const file = await getMissingCodeHTML()\n const err = new Bug(MissingCodeString)\n return respond(file, err, undefined, undefined)\n }\n\n // If the state isn't present in the URL.\n if (!queryObject.state) {\n const file = await getMissingStateHTML()\n const err = new Bug(MissingStateString)\n return respond(file, err, undefined, undefined)\n }\n\n const file = await getSuccessHTML()\n return respond(file, undefined, `${queryObject.code}`, `${queryObject.state}`)\n })\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n return createServer(app)\n }\n\n port: number\n host: string\n server: ReturnType<typeof RedirectListener.createServer>\n\n constructor(options: RedirectListenerOptions) {\n this.port = options.port\n this.host = options.host\n this.server = RedirectListener.createServer(options.callback)\n }\n\n start(): void {\n this.server.listen({port: this.port, host: this.host}, () => {})\n }\n\n async stop(): Promise<void> {\n await this.server.close()\n }\n}\n\nexport async function listenRedirect(host: string, port: number, url: string): Promise<{code: string; state: string}> {\n const result = await new Promise<{code: string; state: string}>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const message = '\\nAuto-open timed out. Open the login page: '\n info(content`${message}${token.link('Log in to Shopify Partners', url)}\\n`)\n }, ResponseTimeoutSeconds * 1000)\n\n const callback: RedirectCallback = (error, code, state) => {\n clearTimeout(timeout)\n setTimeout(() => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n redirectListener.stop()\n if (error) reject(error)\n else resolve({code: code as string, state: state as string})\n }, ServerStopDelaySeconds * 1000)\n }\n\n const redirectListener = new RedirectListener({host, port, callback})\n redirectListener.start()\n })\n return result\n}\n"]}