@shopify/cli-kit 3.0.25 → 3.1.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 (289) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/assets/auth-error.html +2 -4
  3. package/assets/empty-url.html +2 -4
  4. package/assets/missing-code.html +2 -4
  5. package/assets/missing-state.html +2 -4
  6. package/assets/style.css +5 -8
  7. package/assets/success.html +1 -1
  8. package/dist/abort.d.ts +1 -0
  9. package/dist/abort.js +2 -0
  10. package/dist/abort.js.map +1 -0
  11. package/dist/analytics.d.ts +13 -0
  12. package/dist/analytics.js +111 -0
  13. package/dist/analytics.js.map +1 -0
  14. package/dist/api/admin.d.ts +3 -0
  15. package/dist/api/admin.js +80 -0
  16. package/dist/api/admin.js.map +1 -0
  17. package/dist/api/common.d.ts +11 -0
  18. package/dist/api/common.js +40 -0
  19. package/dist/api/common.js.map +1 -0
  20. package/dist/api/graphql/all_app_extension_registrations.d.ts +14 -0
  21. package/dist/api/graphql/all_app_extension_registrations.js +14 -0
  22. package/dist/api/graphql/all_app_extension_registrations.js.map +1 -0
  23. package/dist/api/graphql/all_orgs.d.ts +12 -0
  24. package/dist/api/graphql/all_orgs.js +14 -0
  25. package/dist/api/graphql/all_orgs.js.map +1 -0
  26. package/dist/api/graphql/all_stores_by_org.d.ts +18 -0
  27. package/dist/api/graphql/all_stores_by_org.js +21 -0
  28. package/dist/api/graphql/all_stores_by_org.js.map +1 -0
  29. package/dist/api/graphql/convert_dev_to_test_store.d.ts +16 -0
  30. package/dist/api/graphql/convert_dev_to_test_store.js +13 -0
  31. package/dist/api/graphql/convert_dev_to_test_store.js.map +1 -0
  32. package/dist/api/graphql/create_app.d.ts +28 -0
  33. package/dist/api/graphql/create_app.js +32 -0
  34. package/dist/api/graphql/create_app.js.map +1 -0
  35. package/dist/api/graphql/create_deployment.d.ts +33 -0
  36. package/dist/api/graphql/create_deployment.js +25 -0
  37. package/dist/api/graphql/create_deployment.js.map +1 -0
  38. package/dist/api/graphql/extension_create.d.ts +30 -0
  39. package/dist/api/graphql/extension_create.js +26 -0
  40. package/dist/api/graphql/extension_create.js.map +1 -0
  41. package/dist/api/graphql/extension_specifications.d.ts +18 -0
  42. package/dist/api/graphql/extension_specifications.js +18 -0
  43. package/dist/api/graphql/extension_specifications.js.map +1 -0
  44. package/dist/api/graphql/find_app.d.ts +13 -0
  45. package/dist/api/graphql/find_app.js +16 -0
  46. package/dist/api/graphql/find_app.js.map +1 -0
  47. package/dist/api/graphql/find_org.d.ts +23 -0
  48. package/dist/api/graphql/find_org.js +26 -0
  49. package/dist/api/graphql/find_org.js.map +1 -0
  50. package/dist/api/graphql/find_org_basic.d.ts +11 -0
  51. package/dist/api/graphql/find_org_basic.js +14 -0
  52. package/dist/api/graphql/find_org_basic.js.map +1 -0
  53. package/dist/api/graphql/find_store_by_domain.d.ts +21 -0
  54. package/dist/api/graphql/find_store_by_domain.js +24 -0
  55. package/dist/api/graphql/find_store_by_domain.js.map +1 -0
  56. package/dist/api/graphql/functions/app_function_set.d.ts +43 -0
  57. package/dist/api/graphql/functions/app_function_set.js +52 -0
  58. package/dist/api/graphql/functions/app_function_set.js.map +1 -0
  59. package/dist/api/graphql/functions/compile_module.d.ts +15 -0
  60. package/dist/api/graphql/functions/compile_module.js +13 -0
  61. package/dist/api/graphql/functions/compile_module.js.map +1 -0
  62. package/dist/api/graphql/functions/function_service_proxy.d.ts +4 -0
  63. package/dist/api/graphql/functions/function_service_proxy.js +7 -0
  64. package/dist/api/graphql/functions/function_service_proxy.js.map +1 -0
  65. package/dist/api/graphql/functions/get_app_functions.d.ts +1 -0
  66. package/dist/api/graphql/functions/get_app_functions.js +10 -0
  67. package/dist/api/graphql/functions/get_app_functions.js.map +1 -0
  68. package/dist/api/graphql/functions/module_compilation_status.d.ts +15 -0
  69. package/dist/api/graphql/functions/module_compilation_status.js +13 -0
  70. package/dist/api/graphql/functions/module_compilation_status.js.map +1 -0
  71. package/dist/api/graphql/functions/module_upload_url_generate.d.ts +18 -0
  72. package/dist/api/graphql/functions/module_upload_url_generate.js +17 -0
  73. package/dist/api/graphql/functions/module_upload_url_generate.js.map +1 -0
  74. package/dist/api/graphql/generate_signed_upload_url.d.ts +15 -0
  75. package/dist/api/graphql/generate_signed_upload_url.js +15 -0
  76. package/dist/api/graphql/generate_signed_upload_url.js.map +1 -0
  77. package/dist/api/graphql/get_variant_id.d.ts +17 -0
  78. package/dist/api/graphql/get_variant_id.js +20 -0
  79. package/dist/api/graphql/get_variant_id.js.map +1 -0
  80. package/dist/api/graphql/index.d.ts +22 -0
  81. package/dist/api/graphql/index.js +23 -0
  82. package/dist/api/graphql/index.js.map +1 -0
  83. package/dist/api/graphql/update_draft.d.ts +33 -0
  84. package/dist/api/graphql/update_draft.js +24 -0
  85. package/dist/api/graphql/update_draft.js.map +1 -0
  86. package/dist/api/graphql/update_urls.d.ts +14 -0
  87. package/dist/api/graphql/update_urls.js +12 -0
  88. package/dist/api/graphql/update_urls.js.map +1 -0
  89. package/dist/api/identity.d.ts +1 -0
  90. package/dist/api/identity.js +32 -0
  91. package/dist/api/identity.js.map +1 -0
  92. package/dist/api/partners.d.ts +25 -0
  93. package/dist/api/partners.js +100 -0
  94. package/dist/api/partners.js.map +1 -0
  95. package/dist/api.d.ts +5 -0
  96. package/dist/api.js +6 -0
  97. package/dist/api.js.map +1 -0
  98. package/dist/cli.d.ts +7 -0
  99. package/dist/cli.js +13 -0
  100. package/dist/cli.js.map +1 -0
  101. package/dist/constants.d.ts +43 -0
  102. package/dist/constants.js +63 -0
  103. package/dist/constants.js.map +1 -0
  104. package/dist/environment/fqdn.d.ts +23 -0
  105. package/dist/environment/fqdn.js +61 -0
  106. package/dist/environment/fqdn.js.map +1 -0
  107. package/dist/environment/local.d.ts +48 -0
  108. package/dist/environment/local.js +82 -0
  109. package/dist/environment/local.js.map +1 -0
  110. package/dist/environment/service.d.ts +17 -0
  111. package/dist/environment/service.js +41 -0
  112. package/dist/environment/service.js.map +1 -0
  113. package/dist/environment/spin.d.ts +47 -0
  114. package/dist/environment/spin.js +83 -0
  115. package/dist/environment/spin.js.map +1 -0
  116. package/dist/environment/utilities.d.ts +6 -0
  117. package/dist/environment/utilities.js +12 -0
  118. package/dist/environment/utilities.js.map +1 -0
  119. package/dist/environment.d.ts +5 -0
  120. package/dist/environment.js +6 -0
  121. package/dist/environment.js.map +1 -0
  122. package/dist/error.d.ts +44 -0
  123. package/dist/error.js +91 -0
  124. package/dist/error.js.map +1 -0
  125. package/dist/file.d.ts +67 -0
  126. package/dist/file.js +165 -0
  127. package/dist/file.js.map +1 -0
  128. package/dist/git.d.ts +15 -0
  129. package/dist/git.js +48 -0
  130. package/dist/git.js.map +1 -0
  131. package/dist/github.d.ts +33 -0
  132. package/dist/github.js +56 -0
  133. package/dist/github.js.map +1 -0
  134. package/dist/haiku.d.ts +1 -0
  135. package/dist/haiku.js +8 -0
  136. package/dist/haiku.js.map +1 -0
  137. package/dist/http/fetch.d.ts +16 -0
  138. package/dist/http/fetch.js +18 -0
  139. package/dist/http/fetch.js.map +1 -0
  140. package/dist/http/formdata.d.ts +3 -0
  141. package/dist/http/formdata.js +6 -0
  142. package/dist/http/formdata.js.map +1 -0
  143. package/dist/http.d.ts +2 -0
  144. package/dist/http.js +3 -0
  145. package/dist/http.js.map +1 -0
  146. package/dist/id.d.ts +6 -0
  147. package/dist/id.js +18 -0
  148. package/dist/id.js.map +1 -0
  149. package/dist/index.d.ts +33 -2179
  150. package/dist/index.js +34 -3264
  151. package/dist/index.js.map +1 -1
  152. package/dist/network/api.d.ts +2 -0
  153. package/dist/network/api.js +2 -0
  154. package/dist/network/api.js.map +1 -0
  155. package/dist/network/service.d.ts +16 -0
  156. package/dist/network/service.js +12 -0
  157. package/dist/network/service.js.map +1 -0
  158. package/dist/{archiver.d.ts → node/archiver.d.ts} +1 -4
  159. package/dist/node/archiver.js +22 -42
  160. package/dist/node/archiver.js.map +1 -1
  161. package/dist/node/checksum.d.ts +20 -0
  162. package/dist/node/checksum.js +32 -0
  163. package/dist/node/checksum.js.map +1 -0
  164. package/dist/node/cli.d.ts +18 -0
  165. package/dist/node/cli.js +96 -0
  166. package/dist/node/cli.js.map +1 -0
  167. package/dist/node/colors.d.ts +1 -0
  168. package/dist/node/colors.js +8 -0
  169. package/dist/node/colors.js.map +1 -0
  170. package/dist/node/dot-env.d.ts +33 -0
  171. package/dist/node/dot-env.js +36 -0
  172. package/dist/node/dot-env.js.map +1 -0
  173. package/dist/node/node-package-manager.d.ts +197 -0
  174. package/dist/node/node-package-manager.js +309 -0
  175. package/dist/node/node-package-manager.js.map +1 -0
  176. package/dist/node/ruby.d.ts +30 -0
  177. package/dist/node/ruby.js +197 -0
  178. package/dist/node/ruby.js.map +1 -0
  179. package/dist/npm.d.ts +27 -0
  180. package/dist/npm.js +20 -0
  181. package/dist/npm.js.map +1 -0
  182. package/dist/os.d.ts +10 -0
  183. package/dist/os.js +70 -0
  184. package/dist/os.js.map +1 -0
  185. package/dist/output.d.ts +149 -0
  186. package/dist/output.js +515 -0
  187. package/dist/output.js.map +1 -0
  188. package/dist/path.d.ts +22 -0
  189. package/dist/path.js +43 -0
  190. package/dist/path.js.map +1 -0
  191. package/dist/plugins.d.ts +9 -0
  192. package/dist/plugins.js +12 -0
  193. package/dist/plugins.js.map +1 -0
  194. package/dist/port.d.ts +5 -0
  195. package/dist/port.js +35 -0
  196. package/dist/port.js.map +1 -0
  197. package/dist/schema.d.ts +1 -0
  198. package/dist/schema.js +2 -0
  199. package/dist/schema.js.map +1 -0
  200. package/dist/secure-store.d.ts +19 -0
  201. package/dist/secure-store.js +63 -0
  202. package/dist/secure-store.js.map +1 -0
  203. package/dist/semver.d.ts +3 -0
  204. package/dist/semver.js +6 -0
  205. package/dist/semver.js.map +1 -0
  206. package/dist/session/authorize.d.ts +7 -0
  207. package/dist/session/authorize.js +40 -0
  208. package/dist/session/authorize.js.map +1 -0
  209. package/dist/session/exchange.d.ts +42 -0
  210. package/dist/session/exchange.js +144 -0
  211. package/dist/session/exchange.js.map +1 -0
  212. package/dist/session/identity.d.ts +3 -0
  213. package/dist/session/identity.js +58 -0
  214. package/dist/session/identity.js.map +1 -0
  215. package/dist/session/post-auth.d.ts +13 -0
  216. package/dist/session/post-auth.js +56 -0
  217. package/dist/session/post-auth.js.map +1 -0
  218. package/dist/session/redirect-listener.d.ts +34 -0
  219. package/dist/session/redirect-listener.js +97 -0
  220. package/dist/session/redirect-listener.js.map +1 -0
  221. package/dist/session/schema.d.ts +174 -0
  222. package/dist/session/schema.js +59 -0
  223. package/dist/session/schema.js.map +1 -0
  224. package/dist/session/scopes.d.ts +16 -0
  225. package/dist/session/scopes.js +53 -0
  226. package/dist/session/scopes.js.map +1 -0
  227. package/dist/session/store.d.ts +24 -0
  228. package/dist/session/store.js +88 -0
  229. package/dist/session/store.js.map +1 -0
  230. package/dist/session/token.d.ts +40 -0
  231. package/dist/session/token.js +22 -0
  232. package/dist/session/token.js.map +1 -0
  233. package/dist/session/validate.d.ts +17 -0
  234. package/dist/session/validate.js +75 -0
  235. package/dist/session/validate.js.map +1 -0
  236. package/dist/session.d.ts +88 -0
  237. package/dist/session.js +251 -0
  238. package/dist/session.js.map +1 -0
  239. package/dist/store/schema.d.ts +3 -0
  240. package/dist/store/schema.js +27 -0
  241. package/dist/store/schema.js.map +1 -0
  242. package/dist/store.d.ts +32 -0
  243. package/dist/store.js +102 -0
  244. package/dist/store.js.map +1 -0
  245. package/dist/string.d.ts +22 -0
  246. package/dist/string.js +38 -0
  247. package/dist/string.js.map +1 -0
  248. package/dist/system.d.ts +53 -0
  249. package/dist/system.js +109 -0
  250. package/dist/system.js.map +1 -0
  251. package/dist/template.d.ts +11 -0
  252. package/dist/template.js +50 -0
  253. package/dist/template.js.map +1 -0
  254. package/dist/testing/output.d.ts +9 -0
  255. package/dist/testing/output.js +15 -0
  256. package/dist/testing/output.js.map +1 -0
  257. package/dist/testing/store.d.ts +7 -0
  258. package/dist/testing/store.js +26 -0
  259. package/dist/testing/store.js.map +1 -0
  260. package/dist/toml.d.ts +3 -0
  261. package/dist/toml.js +8 -0
  262. package/dist/toml.js.map +1 -0
  263. package/dist/tsconfig.tsbuildinfo +1 -0
  264. package/dist/ui/autocomplete.d.ts +7 -0
  265. package/dist/ui/autocomplete.js +43 -0
  266. package/dist/ui/autocomplete.js.map +1 -0
  267. package/dist/ui/input.d.ts +7 -0
  268. package/dist/ui/input.js +48 -0
  269. package/dist/ui/input.js.map +1 -0
  270. package/dist/ui/select.d.ts +6 -0
  271. package/dist/ui/select.js +30 -0
  272. package/dist/ui/select.js.map +1 -0
  273. package/dist/ui.d.ts +36 -0
  274. package/dist/ui.js +124 -0
  275. package/dist/ui.js.map +1 -0
  276. package/dist/version.d.ts +19 -0
  277. package/dist/version.js +34 -0
  278. package/dist/version.js.map +1 -0
  279. package/dist/vscode.d.ts +8 -0
  280. package/dist/vscode.js +36 -0
  281. package/dist/vscode.js.map +1 -0
  282. package/dist/yaml.d.ts +2 -0
  283. package/dist/yaml.js +8 -0
  284. package/dist/yaml.js.map +1 -0
  285. package/package.json +19 -8
  286. package/dist/archiver.d.ts.map +0 -1
  287. package/dist/index.d.ts.map +0 -1
  288. package/dist/local-d0094ffe.js +0 -1344
  289. package/dist/local-d0094ffe.js.map +0 -1
@@ -0,0 +1,9 @@
1
+ import { Plugin } from '@oclif/core/lib/interfaces';
2
+ interface TunnelPlugin {
3
+ start: (options: TunnelStartOptions) => Promise<string>;
4
+ }
5
+ interface TunnelStartOptions {
6
+ port: number;
7
+ }
8
+ export declare function lookupTunnelPlugin(plugins: Plugin[]): Promise<TunnelPlugin | undefined>;
9
+ export {};
@@ -0,0 +1,12 @@
1
+ import { join, pathToFileURL } from './path.js';
2
+ import { debug, content } from './output.js';
3
+ const TUNNEL_PLUGINS = ['@shopify/plugin-ngrok'];
4
+ export async function lookupTunnelPlugin(plugins) {
5
+ debug(content `Looking up the Ngrok tunnel plugin...`);
6
+ const tunnelPlugin = plugins.find((plugin) => TUNNEL_PLUGINS.includes(plugin.name));
7
+ if (!tunnelPlugin)
8
+ return undefined;
9
+ const tunnelPath = pathToFileURL(join(tunnelPlugin.root, 'dist/tunnel.js')).toString();
10
+ return import(tunnelPath).catch(() => undefined);
11
+ }
12
+ //# sourceMappingURL=plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.js","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,aAAa,EAAC,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAC,KAAK,EAAE,OAAO,EAAC,MAAM,aAAa,CAAA;AAG1C,MAAM,cAAc,GAAG,CAAC,uBAAuB,CAAC,CAAA;AAUhD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAiB;IACxD,KAAK,CAAC,OAAO,CAAA,uCAAuC,CAAC,CAAA;IACrD,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IACnF,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAA;IACnC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;IACtF,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;AAClD,CAAC","sourcesContent":["import {join, pathToFileURL} from './path.js'\nimport {debug, content} from './output.js'\nimport {Plugin} from '@oclif/core/lib/interfaces'\n\nconst TUNNEL_PLUGINS = ['@shopify/plugin-ngrok']\n\ninterface TunnelPlugin {\n start: (options: TunnelStartOptions) => Promise<string>\n}\n\ninterface TunnelStartOptions {\n port: number\n}\n\nexport async function lookupTunnelPlugin(plugins: Plugin[]): Promise<TunnelPlugin | undefined> {\n debug(content`Looking up the Ngrok tunnel plugin...`)\n const tunnelPlugin = plugins.find((plugin) => TUNNEL_PLUGINS.includes(plugin.name))\n if (!tunnelPlugin) return undefined\n const tunnelPath = pathToFileURL(join(tunnelPlugin.root, 'dist/tunnel.js')).toString()\n return import(tunnelPath).catch(() => undefined)\n}\n"]}
package/dist/port.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Returns an available port in the current environment.
3
+ * @returns {Promise<number>} A promise that resolves with an availabe port.
4
+ */
5
+ export declare function getRandomPort(): Promise<number>;
package/dist/port.js ADDED
@@ -0,0 +1,35 @@
1
+ import { debug, content, token } from './output.js';
2
+ import { Abort } from './error.js';
3
+ import { sleep } from './system.js';
4
+ import * as port from 'get-port-please';
5
+ /**
6
+ * Returns an available port in the current environment.
7
+ * @returns {Promise<number>} A promise that resolves with an availabe port.
8
+ */
9
+ export async function getRandomPort() {
10
+ debug(content `Getting a random port...`);
11
+ const randomPort = retryOnError(() => port.getRandomPort());
12
+ debug(content `Random port obtained: ${token.raw(`${randomPort}`)}`);
13
+ return randomPort;
14
+ }
15
+ async function retryOnError(execute, maxTries = 5, waitTimeInSeconds = 1) {
16
+ let retryCount = 1;
17
+ while (true) {
18
+ try {
19
+ // eslint-disable-next-line no-await-in-loop
20
+ return await execute();
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ }
23
+ catch (error) {
24
+ if (retryCount++ < maxTries) {
25
+ debug(content `Unknown problem getting a random port: ${error.message}`);
26
+ // eslint-disable-next-line no-await-in-loop
27
+ await sleep(waitTimeInSeconds);
28
+ }
29
+ else {
30
+ throw new Abort(error.message);
31
+ }
32
+ }
33
+ }
34
+ }
35
+ //# sourceMappingURL=port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port.js","sourceRoot":"","sources":["../src/port.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AACjD,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAA;AAChC,OAAO,EAAC,KAAK,EAAC,MAAM,aAAa,CAAA;AACjC,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAA;AAEvC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,KAAK,CAAC,OAAO,CAAA,0BAA0B,CAAC,CAAA;IACxC,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAA;IAC3D,KAAK,CAAC,OAAO,CAAA,yBAAyB,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,CAAC,CAAA;IACnE,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,KAAK,UAAU,YAAY,CAAI,OAAgB,EAAE,QAAQ,GAAG,CAAC,EAAE,iBAAiB,GAAG,CAAC;IAClF,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,OAAO,IAAI,EAAE;QACX,IAAI;YACF,4CAA4C;YAC5C,OAAO,MAAM,OAAO,EAAE,CAAA;YACtB,8DAA8D;SAC/D;QAAC,OAAO,KAAU,EAAE;YACnB,IAAI,UAAU,EAAE,GAAG,QAAQ,EAAE;gBAC3B,KAAK,CAAC,OAAO,CAAA,0CAA0C,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;gBACvE,4CAA4C;gBAC5C,MAAM,KAAK,CAAC,iBAAiB,CAAC,CAAA;aAC/B;iBAAM;gBACL,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;aAC/B;SACF;KACF;AACH,CAAC","sourcesContent":["import {debug, content, token} from './output.js'\nimport {Abort} from './error.js'\nimport {sleep} from './system.js'\nimport * as port from 'get-port-please'\n\n/**\n * Returns an available port in the current environment.\n * @returns {Promise<number>} A promise that resolves with an availabe port.\n */\nexport async function getRandomPort(): Promise<number> {\n debug(content`Getting a random port...`)\n const randomPort = retryOnError(() => port.getRandomPort())\n debug(content`Random port obtained: ${token.raw(`${randomPort}`)}`)\n return randomPort\n}\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 debug(content`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 Abort(error.message)\n }\n }\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ export { z as define } from 'zod';
package/dist/schema.js ADDED
@@ -0,0 +1,2 @@
1
+ export { z as define } from 'zod';
2
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,IAAI,MAAM,EAAC,MAAM,KAAK,CAAA","sourcesContent":["export {z as define} from 'zod'\n"]}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Fetches secured content from the system's keychain.
3
+ * @param identifier {string} Identifier to identify the content.
4
+ * @returns A promise that resolves with the content or null if it doesn't exist.
5
+ */
6
+ export declare function fetch(identifier: string): Promise<string | null>;
7
+ /**
8
+ * Securely stores the content under the given key.
9
+ * @param identifier {string} Identifier to identify the content.
10
+ * @param content {string} The content to be stored.
11
+ * @returns A promise that resolves when the storing completes.
12
+ */
13
+ export declare function store(identifier: string, content: string): Promise<void>;
14
+ /**
15
+ * Removes the content with the given identifier.
16
+ * @param identifier {string} Identifier to identify the content.
17
+ * @returns A promise that resolves with true if the content was deleted.
18
+ */
19
+ export declare function remove(identifier: string): Promise<boolean>;
@@ -0,0 +1,63 @@
1
+ import constants from './constants.js';
2
+ import { content as outputContent, debug } from './output.js';
3
+ import { Abort } from './error.js';
4
+ /**
5
+ * Fetches secured content from the system's keychain.
6
+ * @param identifier {string} Identifier to identify the content.
7
+ * @returns A promise that resolves with the content or null if it doesn't exist.
8
+ */
9
+ export async function fetch(identifier) {
10
+ debug(outputContent `Reading ${identifier} from the secure store...`);
11
+ try {
12
+ const keytar = await import('keytar');
13
+ const content = await keytar.getPassword(constants.keychain.service, identifier);
14
+ return content;
15
+ }
16
+ catch (error) {
17
+ throw createAbort(error, 'Unable to read from the secure store');
18
+ }
19
+ }
20
+ /**
21
+ * Securely stores the content under the given key.
22
+ * @param identifier {string} Identifier to identify the content.
23
+ * @param content {string} The content to be stored.
24
+ * @returns A promise that resolves when the storing completes.
25
+ */
26
+ export async function store(identifier, content) {
27
+ debug(outputContent `Updating ${identifier} in the secure store with new content...`);
28
+ try {
29
+ const keytar = await import('keytar');
30
+ await keytar.default.setPassword(constants.keychain.service, identifier, content);
31
+ }
32
+ catch (error) {
33
+ throw createAbort(error, 'Unable to update the secure store');
34
+ }
35
+ }
36
+ /**
37
+ * Removes the content with the given identifier.
38
+ * @param identifier {string} Identifier to identify the content.
39
+ * @returns A promise that resolves with true if the content was deleted.
40
+ */
41
+ export async function remove(identifier) {
42
+ debug(outputContent `Removing ${identifier} from the secure store...`);
43
+ try {
44
+ const keytar = await import('keytar');
45
+ const result = await keytar.default.deletePassword(constants.keychain.service, identifier);
46
+ return result;
47
+ }
48
+ catch (error) {
49
+ throw createAbort(error, 'Unable to remove from the secure store');
50
+ }
51
+ }
52
+ function createAbort(error, message) {
53
+ let newMessage = message;
54
+ let stack = '';
55
+ if (error instanceof Error) {
56
+ newMessage = message.concat(`: ${error.message}`);
57
+ stack = error.stack;
58
+ }
59
+ const abort = new Abort(newMessage);
60
+ abort.stack = stack;
61
+ return abort;
62
+ }
63
+ //# sourceMappingURL=secure-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-store.js","sourceRoot":"","sources":["../src/secure-store.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAC,OAAO,IAAI,aAAa,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAA;AAEhC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,UAAkB;IAC5C,KAAK,CAAC,aAAa,CAAA,WAAW,UAAU,2BAA2B,CAAC,CAAA;IACpE,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAChF,OAAO,OAAO,CAAA;KACf;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,WAAW,CAAC,KAAK,EAAE,sCAAsC,CAAC,CAAA;KACjE;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,UAAkB,EAAE,OAAe;IAC7D,KAAK,CAAC,aAAa,CAAA,YAAY,UAAU,0CAA0C,CAAC,CAAA;IACpF,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrC,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;KAClF;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,WAAW,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAA;KAC9D;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,UAAkB;IAC7C,KAAK,CAAC,aAAa,CAAA,YAAY,UAAU,2BAA2B,CAAC,CAAA;IACrE,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC1F,OAAO,MAAM,CAAA;KACd;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,WAAW,CAAC,KAAK,EAAE,wCAAwC,CAAC,CAAA;KACnE;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAc,EAAE,OAAe;IAClD,IAAI,UAAU,GAAG,OAAO,CAAA;IACxB,IAAI,KAAK,GAAuB,EAAE,CAAA;IAClC,IAAI,KAAK,YAAY,KAAK,EAAE;QAC1B,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QACjD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;KACpB;IACD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,UAAU,CAAC,CAAA;IACnC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAA;IACnB,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["import constants from './constants.js'\nimport {content as outputContent, debug} from './output.js'\nimport {Abort} from './error.js'\n\n/**\n * Fetches secured content from the system's keychain.\n * @param identifier {string} Identifier to identify the content.\n * @returns A promise that resolves with the content or null if it doesn't exist.\n */\nexport async function fetch(identifier: string): Promise<string | null> {\n debug(outputContent`Reading ${identifier} from the secure store...`)\n try {\n const keytar = await import('keytar')\n const content = await keytar.getPassword(constants.keychain.service, identifier)\n return content\n } catch (error) {\n throw createAbort(error, 'Unable to read from the secure store')\n }\n}\n\n/**\n * Securely stores the content under the given key.\n * @param identifier {string} Identifier to identify the content.\n * @param content {string} The content to be stored.\n * @returns A promise that resolves when the storing completes.\n */\nexport async function store(identifier: string, content: string): Promise<void> {\n debug(outputContent`Updating ${identifier} in the secure store with new content...`)\n try {\n const keytar = await import('keytar')\n await keytar.default.setPassword(constants.keychain.service, identifier, content)\n } catch (error) {\n throw createAbort(error, 'Unable to update the secure store')\n }\n}\n\n/**\n * Removes the content with the given identifier.\n * @param identifier {string} Identifier to identify the content.\n * @returns A promise that resolves with true if the content was deleted.\n */\nexport async function remove(identifier: string): Promise<boolean> {\n debug(outputContent`Removing ${identifier} from the secure store...`)\n try {\n const keytar = await import('keytar')\n const result = await keytar.default.deletePassword(constants.keychain.service, identifier)\n return result\n } catch (error) {\n throw createAbort(error, 'Unable to remove from the secure store')\n }\n}\n\nfunction createAbort(error: unknown, message: string) {\n let newMessage = message\n let stack: string | undefined = ''\n if (error instanceof Error) {\n newMessage = message.concat(`: ${error.message}`)\n stack = error.stack\n }\n const abort = new Abort(newMessage)\n abort.stack = stack\n return abort\n}\n"]}
@@ -0,0 +1,3 @@
1
+ declare const coerce: any, SemVer: any;
2
+ export { SemVer as Version };
3
+ export { coerce };
package/dist/semver.js ADDED
@@ -0,0 +1,6 @@
1
+ import { createRequire } from 'module';
2
+ const require = createRequire(import.meta.url);
3
+ const { coerce, SemVer } = require('semver');
4
+ export { SemVer as Version };
5
+ export { coerce };
6
+ //# sourceMappingURL=semver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.js","sourceRoot":"","sources":["../src/semver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,QAAQ,CAAA;AAEpC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC9C,MAAM,EAAC,MAAM,EAAE,MAAM,EAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;AAE1C,OAAO,EAAC,MAAM,IAAI,OAAO,EAAC,CAAA;AAC1B,OAAO,EAAC,MAAM,EAAC,CAAA","sourcesContent":["import {createRequire} from 'module'\n\nconst require = createRequire(import.meta.url)\nconst {coerce, SemVer} = require('semver')\n\nexport {SemVer as Version}\nexport {coerce}\n"]}
@@ -0,0 +1,7 @@
1
+ import { Abort } from '../error.js';
2
+ export declare const MismatchStateError: Abort;
3
+ export interface CodeAuthResult {
4
+ code: string;
5
+ codeVerifier: string;
6
+ }
7
+ export declare function authorize(scopes: string[], state?: string): Promise<CodeAuthResult>;
@@ -0,0 +1,40 @@
1
+ import { listenRedirect } from './redirect-listener.js';
2
+ import { clientId } from './identity.js';
3
+ import { generateRandomChallengePair, randomHex } from '../string.js';
4
+ import { open } from '../system.js';
5
+ import { Abort } from '../error.js';
6
+ import { identity as identityFqdn } from '../environment/fqdn.js';
7
+ import * as output from '../output.js';
8
+ import { keypress } from '../ui.js';
9
+ export const MismatchStateError = new Abort("The state received from the authentication doesn't match the one that initiated the authentication process.");
10
+ export async function authorize(scopes, state = randomHex(30)) {
11
+ const port = 3456;
12
+ const host = '127.0.0.1';
13
+ const redirectUri = `http://${host}:${port}`;
14
+ const fqdn = await identityFqdn();
15
+ const identityClientId = await clientId();
16
+ let url = `http://${fqdn}/oauth/authorize`;
17
+ const { codeVerifier, codeChallenge } = generateRandomChallengePair();
18
+ /* eslint-disable @typescript-eslint/naming-convention */
19
+ const params = {
20
+ client_id: identityClientId,
21
+ scope: scopes.join(' '),
22
+ redirect_uri: redirectUri,
23
+ state,
24
+ response_type: 'code',
25
+ code_challenge_method: 'S256',
26
+ code_challenge: codeChallenge,
27
+ };
28
+ /* eslint-enable @typescript-eslint/naming-convention */
29
+ output.info('\nTo run this command, log in to Shopify Partners.');
30
+ output.info('👉 Press any key to open the login page on your browser');
31
+ await keypress();
32
+ url = `${url}?${new URLSearchParams(params).toString()}`;
33
+ open(url);
34
+ const result = await listenRedirect(host, port, url);
35
+ if (result.state !== state) {
36
+ throw MismatchStateError;
37
+ }
38
+ return { code: result.code, codeVerifier };
39
+ }
40
+ //# sourceMappingURL=authorize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/session/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AACtC,OAAO,EAAC,2BAA2B,EAAE,SAAS,EAAC,MAAM,cAAc,CAAA;AACnE,OAAO,EAAC,IAAI,EAAC,MAAM,cAAc,CAAA;AACjC,OAAO,EAAC,KAAK,EAAC,MAAM,aAAa,CAAA;AACjC,OAAO,EAAC,QAAQ,IAAI,YAAY,EAAC,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AACtC,OAAO,EAAC,QAAQ,EAAC,MAAM,UAAU,CAAA;AAEjC,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,KAAK,CACzC,6GAA6G,CAC9G,CAAA;AAOD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAgB,EAAE,QAAgB,SAAS,CAAC,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAA;IACjB,MAAM,IAAI,GAAG,WAAW,CAAA;IACxB,MAAM,WAAW,GAAG,UAAU,IAAI,IAAI,IAAI,EAAE,CAAA;IAC5C,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAA;IACjC,MAAM,gBAAgB,GAAG,MAAM,QAAQ,EAAE,CAAA;IAEzC,IAAI,GAAG,GAAG,UAAU,IAAI,kBAAkB,CAAA;IAE1C,MAAM,EAAC,YAAY,EAAE,aAAa,EAAC,GAAG,2BAA2B,EAAE,CAAA;IAEnE,yDAAyD;IACzD,MAAM,MAAM,GAAG;QACb,SAAS,EAAE,gBAAgB;QAC3B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QACvB,YAAY,EAAE,WAAW;QACzB,KAAK;QACL,aAAa,EAAE,MAAM;QACrB,qBAAqB,EAAE,MAAM;QAC7B,cAAc,EAAE,aAAa;KAC9B,CAAA;IACD,wDAAwD;IAExD,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;IACjE,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAA;IACtE,MAAM,QAAQ,EAAE,CAAA;IAEhB,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAA;IACxD,IAAI,CAAC,GAAG,CAAC,CAAA;IAET,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;IAEpD,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,EAAE;QAC1B,MAAM,kBAAkB,CAAA;KACzB;IAED,OAAO,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,EAAC,CAAA;AAC1C,CAAC","sourcesContent":["import {listenRedirect} from './redirect-listener.js'\nimport {clientId} from './identity.js'\nimport {generateRandomChallengePair, randomHex} from '../string.js'\nimport {open} from '../system.js'\nimport {Abort} from '../error.js'\nimport {identity as identityFqdn} from '../environment/fqdn.js'\nimport * as output from '../output.js'\nimport {keypress} from '../ui.js'\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 = await clientId()\n\n let url = `http://${fqdn}/oauth/authorize`\n\n const {codeVerifier, codeChallenge} = generateRandomChallengePair()\n\n /* eslint-disable @typescript-eslint/naming-convention */\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 /* eslint-enable @typescript-eslint/naming-convention */\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 open(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"]}
@@ -0,0 +1,42 @@
1
+ import { ApplicationToken, IdentityToken } from './schema.js';
2
+ import { CodeAuthResult } from './authorize.js';
3
+ export declare class InvalidGrantError extends Error {
4
+ }
5
+ export interface ExchangeScopes {
6
+ admin: string[];
7
+ partners: string[];
8
+ storefront: string[];
9
+ }
10
+ /**
11
+ * Given a valid authorization code, request an identity access token.
12
+ * This token can then be used to get API specific tokens.
13
+ * @param codeData code and codeVerifier from the authorize endpoint
14
+ * @param clientId
15
+ * @param identityFqdn
16
+ * @returns {Promise<IdentityToken>} An instance with the identity access tokens.
17
+ */
18
+ export declare function exchangeCodeForAccessToken(codeData: CodeAuthResult): Promise<IdentityToken>;
19
+ /**
20
+ * Given an identity token, request an application token.
21
+ * @param token access token obtained in a previous step
22
+ * @param store the store to use, only needed for admin API
23
+ * @param clientId
24
+ * @param identityFqdn
25
+ * @returns {Promise<ApplicationSchema>} An array with the application access tokens.
26
+ */
27
+ export declare function exchangeAccessForApplicationTokens(identityToken: IdentityToken, scopes: ExchangeScopes, store?: string): Promise<{
28
+ [x: string]: ApplicationToken;
29
+ }>;
30
+ /**
31
+ * Given an expired access token, refresh it to get a new one.
32
+ * @param currentToken
33
+ * @returns
34
+ */
35
+ export declare function refreshAccessToken(currentToken: IdentityToken): Promise<IdentityToken>;
36
+ /**
37
+ * Given a custom CLI token passed as ENV variable, request a valid partners API token
38
+ * This token does not accept extra scopes, just the cli one.
39
+ * @param token {string} The CLI token passed as ENV variable
40
+ * @returns {Promise<ApplicationToken>} An instance with the application access tokens.
41
+ */
42
+ export declare function exchangeCustomPartnerToken(token: string): Promise<ApplicationToken>;
@@ -0,0 +1,144 @@
1
+ import { applicationId, clientId as getIdentityClientId } from './identity.js';
2
+ import * as secureStore from './store.js';
3
+ import { Abort } from '../error.js';
4
+ import { fetch } from '../http.js';
5
+ import { identity as identityFqdn } from '../environment/fqdn.js';
6
+ export class InvalidGrantError extends Error {
7
+ }
8
+ const InvalidIdentityError = new Abort('\nError validating auth session', "We've cleared the current session, please try again");
9
+ /**
10
+ * Given a valid authorization code, request an identity access token.
11
+ * This token can then be used to get API specific tokens.
12
+ * @param codeData code and codeVerifier from the authorize endpoint
13
+ * @param clientId
14
+ * @param identityFqdn
15
+ * @returns {Promise<IdentityToken>} An instance with the identity access tokens.
16
+ */
17
+ export async function exchangeCodeForAccessToken(codeData) {
18
+ const clientId = await getIdentityClientId();
19
+ /* eslint-disable @typescript-eslint/naming-convention */
20
+ const params = {
21
+ grant_type: 'authorization_code',
22
+ code: codeData.code,
23
+ redirect_uri: 'http://127.0.0.1:3456',
24
+ client_id: clientId,
25
+ code_verifier: codeData.codeVerifier,
26
+ };
27
+ /* eslint-enable @typescript-eslint/naming-convention */
28
+ return tokenRequest(params).then(buildIdentityToken);
29
+ }
30
+ /**
31
+ * Given an identity token, request an application token.
32
+ * @param token access token obtained in a previous step
33
+ * @param store the store to use, only needed for admin API
34
+ * @param clientId
35
+ * @param identityFqdn
36
+ * @returns {Promise<ApplicationSchema>} An array with the application access tokens.
37
+ */
38
+ export async function exchangeAccessForApplicationTokens(identityToken, scopes, store) {
39
+ const token = identityToken.accessToken;
40
+ const partners = await requestAppToken('partners', token, scopes.partners);
41
+ const storefront = await requestAppToken('storefront-renderer', token, scopes.storefront);
42
+ const result = {
43
+ ...partners,
44
+ ...storefront,
45
+ };
46
+ if (store) {
47
+ const admin = await requestAppToken('admin', token, scopes.admin, store);
48
+ Object.assign(result, admin);
49
+ }
50
+ return result;
51
+ }
52
+ /**
53
+ * Given an expired access token, refresh it to get a new one.
54
+ * @param currentToken
55
+ * @returns
56
+ */
57
+ export async function refreshAccessToken(currentToken) {
58
+ const clientId = await getIdentityClientId();
59
+ /* eslint-disable @typescript-eslint/naming-convention */
60
+ const params = {
61
+ grant_type: 'refresh_token',
62
+ access_token: currentToken.accessToken,
63
+ refresh_token: currentToken.refreshToken,
64
+ client_id: clientId,
65
+ };
66
+ /* eslint-enable @typescript-eslint/naming-convention */
67
+ return tokenRequest(params).then(buildIdentityToken);
68
+ }
69
+ /**
70
+ * Given a custom CLI token passed as ENV variable, request a valid partners API token
71
+ * This token does not accept extra scopes, just the cli one.
72
+ * @param token {string} The CLI token passed as ENV variable
73
+ * @returns {Promise<ApplicationToken>} An instance with the application access tokens.
74
+ */
75
+ export async function exchangeCustomPartnerToken(token) {
76
+ const appId = applicationId('partners');
77
+ const newToken = await requestAppToken('partners', token, ['https://api.shopify.com/auth/partners.app.cli.access']);
78
+ return newToken[appId];
79
+ }
80
+ async function requestAppToken(api, token, scopes = [], store) {
81
+ const appId = applicationId(api);
82
+ const clientId = await getIdentityClientId();
83
+ /* eslint-disable @typescript-eslint/naming-convention */
84
+ const params = {
85
+ grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',
86
+ requested_token_type: 'urn:ietf:params:oauth:token-type:access_token',
87
+ subject_token_type: 'urn:ietf:params:oauth:token-type:access_token',
88
+ client_id: clientId,
89
+ audience: appId,
90
+ scope: scopes.join(' '),
91
+ subject_token: token,
92
+ ...(api === 'admin' && { destination: `https://${store}/admin` }),
93
+ };
94
+ /* eslint-enable @typescript-eslint/naming-convention */
95
+ let identifier = appId;
96
+ if (api === 'admin' && store) {
97
+ identifier = `${store}-${appId}`;
98
+ }
99
+ const appToken = await tokenRequest(params).then(buildApplicationToken);
100
+ return { [identifier]: appToken };
101
+ }
102
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
103
+ async function tokenRequest(params) {
104
+ const fqdn = await identityFqdn();
105
+ const url = new URL(`https://${fqdn}/oauth/token`);
106
+ url.search = new URLSearchParams(Object.entries(params)).toString();
107
+ const res = await fetch(url.href, { method: 'POST' });
108
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
109
+ const payload = await res.json();
110
+ if (!res.ok) {
111
+ if (payload.error === 'invalid_grant') {
112
+ // There's an scenario when Identity returns "invalid_grant" when trying to refresh the token
113
+ // using a valid refresh token. When that happens, we take the user through the authentication flow.
114
+ throw new InvalidGrantError(payload.error_description);
115
+ }
116
+ else if (payload.error === 'invalid_request') {
117
+ // There's an scenario when Identity returns "invalid_request" when exchanging an identity token.
118
+ // This means the token is invalid. We clear the session and throw an error to let the caller know.
119
+ secureStore.remove();
120
+ throw InvalidIdentityError;
121
+ }
122
+ else {
123
+ throw new Abort(payload.error_description);
124
+ }
125
+ }
126
+ return payload;
127
+ }
128
+ function buildIdentityToken(result) {
129
+ return {
130
+ accessToken: result.access_token,
131
+ refreshToken: result.refresh_token,
132
+ expiresAt: new Date(Date.now() + result.expires_in * 1000),
133
+ scopes: result.scope.split(' '),
134
+ };
135
+ }
136
+ // eslint-disable-next-line @typescript-eslint/naming-convention
137
+ function buildApplicationToken(result) {
138
+ return {
139
+ accessToken: result.access_token,
140
+ expiresAt: new Date(Date.now() + result.expires_in * 1000),
141
+ scopes: result.scope.split(' '),
142
+ };
143
+ }
144
+ //# sourceMappingURL=exchange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/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 * as secureStore from './store.js'\nimport {Abort} from '../error.js'\nimport {API} from '../network/api.js'\nimport {fetch} from '../http.js'\nimport {identity as identityFqdn} from '../environment/fqdn.js'\n\nexport class InvalidGrantError extends Error {}\n\nconst InvalidIdentityError = new Abort(\n '\\nError validating auth session',\n \"We've cleared the current session, please try again\",\n)\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 * @param clientId\n * @param identityFqdn\n * @returns {Promise<IdentityToken>} An instance with the identity access tokens.\n */\nexport async function exchangeCodeForAccessToken(codeData: CodeAuthResult): Promise<IdentityToken> {\n const clientId = await getIdentityClientId()\n /* eslint-disable @typescript-eslint/naming-convention */\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 /* eslint-enable @typescript-eslint/naming-convention */\n\n return tokenRequest(params).then(buildIdentityToken)\n}\n\n/**\n * Given an identity token, request an application token.\n * @param token access token obtained in a previous step\n * @param store the store to use, only needed for admin API\n * @param clientId\n * @param identityFqdn\n * @returns {Promise<ApplicationSchema>} 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 = await requestAppToken('partners', token, scopes.partners)\n const storefront = await requestAppToken('storefront-renderer', token, scopes.storefront)\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 * @param currentToken\n * @returns\n */\nexport async function refreshAccessToken(currentToken: IdentityToken): Promise<IdentityToken> {\n const clientId = await getIdentityClientId()\n /* eslint-disable @typescript-eslint/naming-convention */\n const params = {\n grant_type: 'refresh_token',\n access_token: currentToken.accessToken,\n refresh_token: currentToken.refreshToken,\n client_id: clientId,\n }\n /* eslint-enable @typescript-eslint/naming-convention */\n return tokenRequest(params).then(buildIdentityToken)\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 {string} The CLI token passed as ENV variable\n * @returns {Promise<ApplicationToken>} 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\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 /* eslint-disable @typescript-eslint/naming-convention */\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 /* eslint-enable @typescript-eslint/naming-convention */\n\n let identifier = appId\n if (api === 'admin' && store) {\n identifier = `${store}-${appId}`\n }\n const appToken = await tokenRequest(params).then(buildApplicationToken)\n return {[identifier]: appToken}\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function tokenRequest(params: {[key: string]: string}): Promise<any> {\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 fetch(url.href, {method: 'POST'})\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const payload: any = await res.json()\n if (!res.ok) {\n if (payload.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 throw new InvalidGrantError(payload.error_description)\n } else if (payload.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 secureStore.remove()\n throw InvalidIdentityError\n } else {\n throw new Abort(payload.error_description)\n }\n }\n return payload\n}\n\nfunction buildIdentityToken(result: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n access_token: string\n // eslint-disable-next-line @typescript-eslint/naming-convention\n refresh_token: string\n // eslint-disable-next-line @typescript-eslint/naming-convention\n expires_in: number\n scope: string\n}): 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\n// eslint-disable-next-line @typescript-eslint/naming-convention\nfunction buildApplicationToken(result: {access_token: string; expires_in: number; scope: string}): 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"]}
@@ -0,0 +1,3 @@
1
+ import { API } from '../network/api.js';
2
+ export declare function clientId(): string;
3
+ export declare function applicationId(api: API): string;
@@ -0,0 +1,58 @@
1
+ import { Bug } from '../error.js';
2
+ import { shopify as shopifyEnvironment, partners as partnersEnvironment, identity as identityEnvironment, } from '../environment/service.js';
3
+ import { Environment } from '../network/service.js';
4
+ export function clientId() {
5
+ const environment = identityEnvironment();
6
+ if (environment === Environment.Local) {
7
+ return 'e5380e02-312a-7408-5718-e07017e9cf52';
8
+ }
9
+ else if (environment === Environment.Production) {
10
+ return 'fbdb2649-e327-4907-8f67-908d24cfd7e3';
11
+ }
12
+ else {
13
+ return 'e5380e02-312a-7408-5718-e07017e9cf52';
14
+ }
15
+ }
16
+ export function applicationId(api) {
17
+ switch (api) {
18
+ case 'admin': {
19
+ const environment = shopifyEnvironment();
20
+ if (environment === Environment.Local) {
21
+ return 'e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52';
22
+ }
23
+ else if (environment === Environment.Production) {
24
+ return '7ee65a63608843c577db8b23c4d7316ea0a01bd2f7594f8a9c06ea668c1b775c';
25
+ }
26
+ else {
27
+ return 'e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52';
28
+ }
29
+ }
30
+ case 'partners': {
31
+ const environment = partnersEnvironment();
32
+ if (environment === Environment.Local) {
33
+ return 'df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978';
34
+ }
35
+ else if (environment === Environment.Production) {
36
+ return '271e16d403dfa18082ffb3d197bd2b5f4479c3fc32736d69296829cbb28d41a6';
37
+ }
38
+ else {
39
+ return 'df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978';
40
+ }
41
+ }
42
+ case 'storefront-renderer': {
43
+ const environment = shopifyEnvironment();
44
+ if (environment === Environment.Local) {
45
+ return '46f603de-894f-488d-9471-5b721280ff49';
46
+ }
47
+ else if (environment === Environment.Production) {
48
+ return 'ee139b3d-5861-4d45-b387-1bc3ada7811c';
49
+ }
50
+ else {
51
+ return '46f603de-894f-488d-9471-5b721280ff49';
52
+ }
53
+ }
54
+ default:
55
+ throw new Bug(`Application id for API of type: ${api}`);
56
+ }
57
+ }
58
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/session/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,aAAa,CAAA;AAC/B,OAAO,EACL,OAAO,IAAI,kBAAkB,EAC7B,QAAQ,IAAI,mBAAmB,EAC/B,QAAQ,IAAI,mBAAmB,GAChC,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAGjD,MAAM,UAAU,QAAQ;IACtB,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAA;IACzC,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,mBAAmB,EAAE,CAAA;YACzC,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 {\n shopify as shopifyEnvironment,\n partners as partnersEnvironment,\n identity as identityEnvironment,\n} from '../environment/service.js'\nimport {Environment} from '../network/service.js'\nimport {API} from '../network/api.js'\n\nexport function clientId(): string {\n const environment = identityEnvironment()\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 = shopifyEnvironment()\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 = partnersEnvironment()\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 = shopifyEnvironment()\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"]}
@@ -0,0 +1,13 @@
1
+ import { Bug } from '../error.js';
2
+ export declare const getEmptyUrlHTML: () => Promise<string>;
3
+ export declare const getAuthErrorHTML: () => Promise<string>;
4
+ export declare const getMissingCodeHTML: () => Promise<string>;
5
+ export declare const getMissingStateHTML: () => Promise<string>;
6
+ export declare const getSuccessHTML: () => Promise<string>;
7
+ export declare const getStylesheet: () => Promise<string>;
8
+ export declare const getFavicon: () => Promise<string>;
9
+ export declare const EmptyUrlString = "We received the authentication redirect but the URL is empty.";
10
+ export declare const AuthErrorString = "There was an issue while trying to authenticate.";
11
+ export declare const MissingCodeString = "The authentication can't continue because the redirect doesn't include the code.";
12
+ export declare const MissingStateString = "The authentication can't continue because the redirect doesn't include the state.";
13
+ export declare const RedirectPageAssetNotFoundError: () => Bug;
@@ -0,0 +1,56 @@
1
+ import { findUp, moduleDirectory } from '../path.js';
2
+ import { read } from '../file.js';
3
+ import { Bug } from '../error.js';
4
+ const HTMLFileNames = ['empty-url.html', 'auth-error.html', 'missing-code.html', 'missing-state.html', 'success.html'];
5
+ const StylesheetFilename = 'style.css';
6
+ const FaviconFileName = 'favicon.svg';
7
+ /**
8
+ * Finds the full path of the given file-name from the assets folder.
9
+ *
10
+ * @param {string} fileName The name of the file to look for.
11
+ * @returns {string | null} The full path of the file, or null if not found.
12
+ */
13
+ const getFilePath = async (fileName) => {
14
+ const filePath = await findUp(`assets/${fileName}`, {
15
+ type: 'file',
16
+ cwd: moduleDirectory(import.meta.url),
17
+ });
18
+ if (!filePath) {
19
+ throw RedirectPageAssetNotFoundError();
20
+ }
21
+ return filePath;
22
+ };
23
+ export const getEmptyUrlHTML = async () => {
24
+ const filePath = await getFilePath(HTMLFileNames[0]);
25
+ return read(filePath);
26
+ };
27
+ export const getAuthErrorHTML = async () => {
28
+ const filePath = await getFilePath(HTMLFileNames[1]);
29
+ return read(filePath);
30
+ };
31
+ export const getMissingCodeHTML = async () => {
32
+ const filePath = await getFilePath(HTMLFileNames[2]);
33
+ return read(filePath);
34
+ };
35
+ export const getMissingStateHTML = async () => {
36
+ const filePath = await getFilePath(HTMLFileNames[3]);
37
+ return read(filePath);
38
+ };
39
+ export const getSuccessHTML = async () => {
40
+ const filePath = await getFilePath(HTMLFileNames[4]);
41
+ return read(filePath);
42
+ };
43
+ export const getStylesheet = async () => {
44
+ const filePath = await getFilePath(StylesheetFilename);
45
+ return read(filePath);
46
+ };
47
+ export const getFavicon = async () => {
48
+ const filePath = await getFilePath(FaviconFileName);
49
+ return read(filePath);
50
+ };
51
+ export const EmptyUrlString = 'We received the authentication redirect but the URL is empty.';
52
+ export const AuthErrorString = 'There was an issue while trying to authenticate.';
53
+ export const MissingCodeString = "The authentication can't continue because the redirect doesn't include the code.";
54
+ export const MissingStateString = "The authentication can't continue because the redirect doesn't include the state.";
55
+ export const RedirectPageAssetNotFoundError = () => new Bug(`Redirect page asset not found`);
56
+ //# sourceMappingURL=post-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-auth.js","sourceRoot":"","sources":["../../src/session/post-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,eAAe,EAAC,MAAM,YAAY,CAAA;AAClD,OAAO,EAAC,IAAI,EAAC,MAAM,YAAY,CAAA;AAC/B,OAAO,EAAC,GAAG,EAAC,MAAM,aAAa,CAAA;AAE/B,MAAM,aAAa,GAAG,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,cAAc,CAAC,CAAA;AACtH,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,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,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,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,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,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,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,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,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,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,IAAqB,EAAE;IACvD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAA;IACtD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,IAAqB,EAAE;IACpD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,CAAA;IACnD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;AACvB,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 {read} from '../file.js'\nimport {Bug} from '../error.js'\n\nconst HTMLFileNames = ['empty-url.html', 'auth-error.html', 'missing-code.html', 'missing-state.html', 'success.html']\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 {string} fileName The name of the file to look for.\n * @returns {string | null} 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 read(filePath)\n}\n\nexport const getAuthErrorHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[1])\n return read(filePath)\n}\n\nexport const getMissingCodeHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[2])\n return read(filePath)\n}\n\nexport const getMissingStateHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[3])\n return read(filePath)\n}\n\nexport const getSuccessHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[4])\n return read(filePath)\n}\n\nexport const getStylesheet = async (): Promise<string> => {\n const filePath = await getFilePath(StylesheetFilename)\n return read(filePath)\n}\n\nexport const getFavicon = async (): Promise<string> => {\n const filePath = await getFilePath(FaviconFileName)\n return read(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"]}