@shopify/cli-kit 3.0.23 → 3.0.26

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 (287) hide show
  1. package/CHANGELOG.md +28 -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 +11 -0
  12. package/dist/analytics.js +96 -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/functions/app_function_set.d.ts +43 -0
  54. package/dist/api/graphql/functions/app_function_set.js +52 -0
  55. package/dist/api/graphql/functions/app_function_set.js.map +1 -0
  56. package/dist/api/graphql/functions/compile_module.d.ts +15 -0
  57. package/dist/api/graphql/functions/compile_module.js +13 -0
  58. package/dist/api/graphql/functions/compile_module.js.map +1 -0
  59. package/dist/api/graphql/functions/function_service_proxy.d.ts +4 -0
  60. package/dist/api/graphql/functions/function_service_proxy.js +7 -0
  61. package/dist/api/graphql/functions/function_service_proxy.js.map +1 -0
  62. package/dist/api/graphql/functions/get_app_functions.d.ts +1 -0
  63. package/dist/api/graphql/functions/get_app_functions.js +10 -0
  64. package/dist/api/graphql/functions/get_app_functions.js.map +1 -0
  65. package/dist/api/graphql/functions/module_compilation_status.d.ts +15 -0
  66. package/dist/api/graphql/functions/module_compilation_status.js +13 -0
  67. package/dist/api/graphql/functions/module_compilation_status.js.map +1 -0
  68. package/dist/api/graphql/functions/module_upload_url_generate.d.ts +18 -0
  69. package/dist/api/graphql/functions/module_upload_url_generate.js +17 -0
  70. package/dist/api/graphql/functions/module_upload_url_generate.js.map +1 -0
  71. package/dist/api/graphql/generate_signed_upload_url.d.ts +15 -0
  72. package/dist/api/graphql/generate_signed_upload_url.js +15 -0
  73. package/dist/api/graphql/generate_signed_upload_url.js.map +1 -0
  74. package/dist/api/graphql/get_variant_id.d.ts +17 -0
  75. package/dist/api/graphql/get_variant_id.js +20 -0
  76. package/dist/api/graphql/get_variant_id.js.map +1 -0
  77. package/dist/api/graphql/index.d.ts +21 -0
  78. package/dist/api/graphql/index.js +22 -0
  79. package/dist/api/graphql/index.js.map +1 -0
  80. package/dist/api/graphql/update_draft.d.ts +33 -0
  81. package/dist/api/graphql/update_draft.js +24 -0
  82. package/dist/api/graphql/update_draft.js.map +1 -0
  83. package/dist/api/graphql/update_urls.d.ts +14 -0
  84. package/dist/api/graphql/update_urls.js +12 -0
  85. package/dist/api/graphql/update_urls.js.map +1 -0
  86. package/dist/api/identity.d.ts +1 -0
  87. package/dist/api/identity.js +29 -0
  88. package/dist/api/identity.js.map +1 -0
  89. package/dist/api/partners.d.ts +25 -0
  90. package/dist/api/partners.js +100 -0
  91. package/dist/api/partners.js.map +1 -0
  92. package/dist/api.d.ts +5 -0
  93. package/dist/api.js +6 -0
  94. package/dist/api.js.map +1 -0
  95. package/dist/checksum.d.ts +15 -0
  96. package/dist/checksum.js +27 -0
  97. package/dist/checksum.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/colors.d.ts +1 -0
  102. package/dist/colors.js +8 -0
  103. package/dist/colors.js.map +1 -0
  104. package/dist/constants.d.ts +43 -0
  105. package/dist/constants.js +63 -0
  106. package/dist/constants.js.map +1 -0
  107. package/dist/dependency.d.ts +128 -0
  108. package/dist/dependency.js +302 -0
  109. package/dist/dependency.js.map +1 -0
  110. package/dist/dot-env.d.ts +28 -0
  111. package/dist/dot-env.js +31 -0
  112. package/dist/dot-env.js.map +1 -0
  113. package/dist/environment/fqdn.d.ts +23 -0
  114. package/dist/environment/fqdn.js +61 -0
  115. package/dist/environment/fqdn.js.map +1 -0
  116. package/dist/environment/local.d.ts +48 -0
  117. package/dist/environment/local.js +82 -0
  118. package/dist/environment/local.js.map +1 -0
  119. package/dist/environment/service.d.ts +17 -0
  120. package/dist/environment/service.js +41 -0
  121. package/dist/environment/service.js.map +1 -0
  122. package/dist/environment/spin.d.ts +47 -0
  123. package/dist/environment/spin.js +83 -0
  124. package/dist/environment/spin.js.map +1 -0
  125. package/dist/environment/utilities.d.ts +6 -0
  126. package/dist/environment/utilities.js +12 -0
  127. package/dist/environment/utilities.js.map +1 -0
  128. package/dist/environment.d.ts +5 -0
  129. package/dist/environment.js +6 -0
  130. package/dist/environment.js.map +1 -0
  131. package/dist/error.d.ts +44 -0
  132. package/dist/error.js +91 -0
  133. package/dist/error.js.map +1 -0
  134. package/dist/file.d.ts +67 -0
  135. package/dist/file.js +165 -0
  136. package/dist/file.js.map +1 -0
  137. package/dist/git.d.ts +15 -0
  138. package/dist/git.js +48 -0
  139. package/dist/git.js.map +1 -0
  140. package/dist/github.d.ts +33 -0
  141. package/dist/github.js +56 -0
  142. package/dist/github.js.map +1 -0
  143. package/dist/haiku.d.ts +1 -0
  144. package/dist/haiku.js +8 -0
  145. package/dist/haiku.js.map +1 -0
  146. package/dist/http/fetch.d.ts +16 -0
  147. package/dist/http/fetch.js +18 -0
  148. package/dist/http/fetch.js.map +1 -0
  149. package/dist/http/formdata.d.ts +3 -0
  150. package/dist/http/formdata.js +6 -0
  151. package/dist/http/formdata.js.map +1 -0
  152. package/dist/http.d.ts +2 -0
  153. package/dist/http.js +3 -0
  154. package/dist/http.js.map +1 -0
  155. package/dist/id.d.ts +6 -0
  156. package/dist/id.js +18 -0
  157. package/dist/id.js.map +1 -0
  158. package/dist/index.d.ts +37 -2115
  159. package/dist/index.js +38 -46
  160. package/dist/index.js.map +1 -1
  161. package/dist/network/api.d.ts +2 -0
  162. package/dist/network/api.js +2 -0
  163. package/dist/network/api.js.map +1 -0
  164. package/dist/network/service.d.ts +16 -0
  165. package/dist/network/service.js +12 -0
  166. package/dist/network/service.js.map +1 -0
  167. package/dist/node/archiver.d.ts +6 -0
  168. package/dist/node/archiver.js +24 -0
  169. package/dist/node/archiver.js.map +1 -0
  170. package/dist/node/cli.d.ts +18 -0
  171. package/dist/node/cli.js +91 -0
  172. package/dist/node/cli.js.map +1 -0
  173. package/dist/npm.d.ts +27 -0
  174. package/dist/npm.js +20 -0
  175. package/dist/npm.js.map +1 -0
  176. package/dist/os.d.ts +10 -0
  177. package/dist/os.js +70 -0
  178. package/dist/os.js.map +1 -0
  179. package/dist/output.d.ts +142 -0
  180. package/dist/output.js +505 -0
  181. package/dist/output.js.map +1 -0
  182. package/dist/path.d.ts +22 -0
  183. package/dist/path.js +43 -0
  184. package/dist/path.js.map +1 -0
  185. package/dist/plugins.d.ts +9 -0
  186. package/dist/plugins.js +12 -0
  187. package/dist/plugins.js.map +1 -0
  188. package/dist/port.d.ts +5 -0
  189. package/dist/port.js +13 -0
  190. package/dist/port.js.map +1 -0
  191. package/dist/ruby.d.ts +21 -0
  192. package/dist/ruby.js +192 -0
  193. package/dist/ruby.js.map +1 -0
  194. package/dist/schema.d.ts +1 -0
  195. package/dist/schema.js +2 -0
  196. package/dist/schema.js.map +1 -0
  197. package/dist/secure-store.d.ts +19 -0
  198. package/dist/secure-store.js +63 -0
  199. package/dist/secure-store.js.map +1 -0
  200. package/dist/semver.d.ts +3 -0
  201. package/dist/semver.js +6 -0
  202. package/dist/semver.js.map +1 -0
  203. package/dist/session/authorize.d.ts +7 -0
  204. package/dist/session/authorize.js +40 -0
  205. package/dist/session/authorize.js.map +1 -0
  206. package/dist/session/exchange.d.ts +42 -0
  207. package/dist/session/exchange.js +144 -0
  208. package/dist/session/exchange.js.map +1 -0
  209. package/dist/session/identity.d.ts +3 -0
  210. package/dist/session/identity.js +58 -0
  211. package/dist/session/identity.js.map +1 -0
  212. package/dist/session/post-auth.d.ts +13 -0
  213. package/dist/session/post-auth.js +56 -0
  214. package/dist/session/post-auth.js.map +1 -0
  215. package/dist/session/redirect-listener.d.ts +34 -0
  216. package/dist/session/redirect-listener.js +97 -0
  217. package/dist/session/redirect-listener.js.map +1 -0
  218. package/dist/session/schema.d.ts +174 -0
  219. package/dist/session/schema.js +59 -0
  220. package/dist/session/schema.js.map +1 -0
  221. package/dist/session/scopes.d.ts +16 -0
  222. package/dist/session/scopes.js +53 -0
  223. package/dist/session/scopes.js.map +1 -0
  224. package/dist/session/store.d.ts +24 -0
  225. package/dist/session/store.js +88 -0
  226. package/dist/session/store.js.map +1 -0
  227. package/dist/session/token.d.ts +40 -0
  228. package/dist/session/token.js +22 -0
  229. package/dist/session/token.js.map +1 -0
  230. package/dist/session/validate.d.ts +17 -0
  231. package/dist/session/validate.js +75 -0
  232. package/dist/session/validate.js.map +1 -0
  233. package/dist/session.d.ts +88 -0
  234. package/dist/session.js +251 -0
  235. package/dist/session.js.map +1 -0
  236. package/dist/store/schema.d.ts +3 -0
  237. package/dist/store/schema.js +27 -0
  238. package/dist/store/schema.js.map +1 -0
  239. package/dist/store.d.ts +32 -0
  240. package/dist/store.js +102 -0
  241. package/dist/store.js.map +1 -0
  242. package/dist/string.d.ts +22 -0
  243. package/dist/string.js +38 -0
  244. package/dist/string.js.map +1 -0
  245. package/dist/system.d.ts +53 -0
  246. package/dist/system.js +109 -0
  247. package/dist/system.js.map +1 -0
  248. package/dist/template.d.ts +11 -0
  249. package/dist/template.js +50 -0
  250. package/dist/template.js.map +1 -0
  251. package/dist/testing/output.d.ts +9 -0
  252. package/dist/testing/output.js +15 -0
  253. package/dist/testing/output.js.map +1 -0
  254. package/dist/testing/store.d.ts +7 -0
  255. package/dist/testing/store.js +26 -0
  256. package/dist/testing/store.js.map +1 -0
  257. package/dist/toml.d.ts +3 -0
  258. package/dist/toml.js +8 -0
  259. package/dist/toml.js.map +1 -0
  260. package/dist/tsconfig.tsbuildinfo +1 -0
  261. package/dist/ui/autocomplete.d.ts +7 -0
  262. package/dist/ui/autocomplete.js +43 -0
  263. package/dist/ui/autocomplete.js.map +1 -0
  264. package/dist/ui/input.d.ts +7 -0
  265. package/dist/ui/input.js +48 -0
  266. package/dist/ui/input.js.map +1 -0
  267. package/dist/ui/select.d.ts +6 -0
  268. package/dist/ui/select.js +30 -0
  269. package/dist/ui/select.js.map +1 -0
  270. package/dist/ui.d.ts +36 -0
  271. package/dist/ui.js +124 -0
  272. package/dist/ui.js.map +1 -0
  273. package/dist/version.d.ts +19 -0
  274. package/dist/version.js +34 -0
  275. package/dist/version.js.map +1 -0
  276. package/dist/vscode.d.ts +8 -0
  277. package/dist/vscode.js +36 -0
  278. package/dist/vscode.js.map +1 -0
  279. package/dist/yaml.d.ts +2 -0
  280. package/dist/yaml.js +8 -0
  281. package/dist/yaml.js.map +1 -0
  282. package/package.json +32 -21
  283. package/dist/index-160b2bd2.js +0 -175294
  284. package/dist/index-160b2bd2.js.map +0 -1
  285. package/dist/index.d.ts.map +0 -1
  286. package/dist/multipart-parser-7ce1f707.js +0 -477
  287. package/dist/multipart-parser-7ce1f707.js.map +0 -1
@@ -0,0 +1,59 @@
1
+ import { define } from '../schema.js';
2
+ const DateSchema = define.preprocess((arg) => {
3
+ if (typeof arg === 'string' || arg instanceof Date)
4
+ return new Date(arg);
5
+ return null;
6
+ }, define.date());
7
+ /**
8
+ * The schema represents an Identity token.
9
+ */
10
+ const IdentityTokenSchema = define.object({
11
+ accessToken: define.string(),
12
+ refreshToken: define.string(),
13
+ expiresAt: DateSchema,
14
+ scopes: define.array(define.string()),
15
+ });
16
+ /**
17
+ * The schema represents an application token.
18
+ */
19
+ const ApplicationTokenSchema = define.object({
20
+ accessToken: define.string(),
21
+ expiresAt: DateSchema,
22
+ scopes: define.array(define.string()),
23
+ });
24
+ /**
25
+ * This schema represents the format of the session
26
+ * that we cache in the system to avoid unnecessary
27
+ * token exchanges.
28
+ *
29
+ * @example
30
+ * {
31
+ * "accounts.shopify.com": {
32
+ * "identity": {...} // IdentityTokenSchema
33
+ * "applications": {
34
+ * "${domain}-application-id": { // Admin APIs includes domain in the key
35
+ * "accessToken": "...",
36
+ * },
37
+ * "$application-id": { // ApplicationTokenSchema
38
+ * "accessToken": "...",
39
+ * },
40
+ * }
41
+ * },
42
+ * "identity.spin.com": {...}
43
+ *}
44
+ *
45
+ */
46
+ export const SessionSchema = define.object({}).catchall(define.object({
47
+ /**
48
+ * It contains the identity token. Before usint it, we exchange it
49
+ * to get a token that we can use with different applications. The exchanged
50
+ * tokens for the applications are stored under applications.
51
+ */
52
+ identity: IdentityTokenSchema,
53
+ /**
54
+ * It contains exchanged tokens for the applications the CLI
55
+ * authenticates with. Tokens are scoped under the fqdn of the applications.
56
+ */
57
+ applications: define.object({}).catchall(ApplicationTokenSchema),
58
+ }));
59
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/session/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAA;AAEnC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,YAAY,IAAI;QAAE,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAA;IACxE,OAAO,IAAI,CAAA;AACb,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;AAEjB;;GAEG;AACH,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC;IACxC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;IAC5B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;IAC7B,SAAS,EAAE,UAAU;IACrB,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;CACtC,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;IAC5B,SAAS,EAAE,UAAU;IACrB,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;CACtC,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,CACrD,MAAM,CAAC,MAAM,CAAC;IACZ;;;;OAIG;IACH,QAAQ,EAAE,mBAAmB;IAC7B;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC;CACjE,CAAC,CACH,CAAA","sourcesContent":["import {define} from '../schema.js'\n\nconst DateSchema = define.preprocess((arg) => {\n if (typeof arg === 'string' || arg instanceof Date) return new Date(arg)\n return null\n}, define.date())\n\n/**\n * The schema represents an Identity token.\n */\nconst IdentityTokenSchema = define.object({\n accessToken: define.string(),\n refreshToken: define.string(),\n expiresAt: DateSchema,\n scopes: define.array(define.string()),\n})\n\n/**\n * The schema represents an application token.\n */\nconst ApplicationTokenSchema = define.object({\n accessToken: define.string(),\n expiresAt: DateSchema,\n scopes: define.array(define.string()),\n})\n\n/**\n * This schema represents the format of the session\n * that we cache in the system to avoid unnecessary\n * token exchanges.\n *\n * @example\n * {\n * \"accounts.shopify.com\": {\n * \"identity\": {...} // IdentityTokenSchema\n * \"applications\": {\n * \"${domain}-application-id\": { // Admin APIs includes domain in the key\n * \"accessToken\": \"...\",\n * },\n * \"$application-id\": { // ApplicationTokenSchema\n * \"accessToken\": \"...\",\n * },\n * }\n * },\n * \"identity.spin.com\": {...}\n *}\n *\n */\nexport const SessionSchema = define.object({}).catchall(\n define.object({\n /**\n * It contains the identity token. Before usint it, we exchange it\n * to get a token that we can use with different applications. The exchanged\n * tokens for the applications are stored under applications.\n */\n identity: IdentityTokenSchema,\n /**\n * It contains exchanged tokens for the applications the CLI\n * authenticates with. Tokens are scoped under the fqdn of the applications.\n */\n applications: define.object({}).catchall(ApplicationTokenSchema),\n }),\n)\n\nexport type Session = define.infer<typeof SessionSchema>\nexport type IdentityToken = define.infer<typeof IdentityTokenSchema>\nexport type ApplicationToken = define.infer<typeof ApplicationTokenSchema>\n"]}
@@ -0,0 +1,16 @@
1
+ import { API } from '../network/api.js';
2
+ /**
3
+ * Generate a flat array with all the default scopes for all the APIs plus
4
+ * any custom scope defined by the user.
5
+ * @param extraScopes custom user-defined scopes
6
+ * @returns Array of scopes
7
+ */
8
+ export declare function allDefaultScopes(extraScopes?: string[]): string[];
9
+ /**
10
+ * Generate a flat array with the default scopes for the given API plus
11
+ * any custom scope defined by the user
12
+ * @param api API to get the scopes for
13
+ * @param extraScopes custom user-defined scopes
14
+ * @returns Array of scopes
15
+ */
16
+ export declare function apiScopes(api: API, extraScopes?: string[]): string[];
@@ -0,0 +1,53 @@
1
+ import { Bug } from '../error.js';
2
+ import { allAPIs } from '../network/api.js';
3
+ /**
4
+ * Generate a flat array with all the default scopes for all the APIs plus
5
+ * any custom scope defined by the user.
6
+ * @param extraScopes custom user-defined scopes
7
+ * @returns Array of scopes
8
+ */
9
+ export function allDefaultScopes(extraScopes = []) {
10
+ let scopes = allAPIs.map(defaultApiScopes).flat();
11
+ scopes = ['openid', ...scopes, ...extraScopes].map(scopeTransform);
12
+ return Array.from(new Set(scopes));
13
+ }
14
+ /**
15
+ * Generate a flat array with the default scopes for the given API plus
16
+ * any custom scope defined by the user
17
+ * @param api API to get the scopes for
18
+ * @param extraScopes custom user-defined scopes
19
+ * @returns Array of scopes
20
+ */
21
+ export function apiScopes(api, extraScopes = []) {
22
+ const scopes = ['openid', ...defaultApiScopes(api), ...extraScopes.map(scopeTransform)].map(scopeTransform);
23
+ return Array.from(new Set(scopes));
24
+ }
25
+ function defaultApiScopes(api) {
26
+ switch (api) {
27
+ case 'admin':
28
+ return ['graphql', 'themes', 'collaborator'];
29
+ case 'storefront-renderer':
30
+ return ['devtools'];
31
+ case 'partners':
32
+ return ['cli'];
33
+ default:
34
+ throw new Bug(`Unknown API: ${api}`);
35
+ }
36
+ }
37
+ function scopeTransform(scope) {
38
+ switch (scope) {
39
+ case 'graphql':
40
+ return 'https://api.shopify.com/auth/shop.admin.graphql';
41
+ case 'themes':
42
+ return 'https://api.shopify.com/auth/shop.admin.themes';
43
+ case 'collaborator':
44
+ return 'https://api.shopify.com/auth/partners.collaborator-relationships.readonly';
45
+ case 'cli':
46
+ return 'https://api.shopify.com/auth/partners.app.cli.access';
47
+ case 'devtools':
48
+ return 'https://api.shopify.com/auth/shop.storefront-renderer.devtools';
49
+ default:
50
+ return scope;
51
+ }
52
+ }
53
+ //# sourceMappingURL=scopes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/session/scopes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,aAAa,CAAA;AAC/B,OAAO,EAAC,OAAO,EAAM,MAAM,mBAAmB,CAAA;AAE9C;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,cAAwB,EAAE;IACzD,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,CAAA;IACjD,MAAM,GAAG,CAAC,QAAQ,EAAE,GAAG,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IAClE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,GAAQ,EAAE,cAAwB,EAAE;IAC5D,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IAC3G,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;AACpC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAQ;IAChC,QAAQ,GAAG,EAAE;QACX,KAAK,OAAO;YACV,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAA;QAC9C,KAAK,qBAAqB;YACxB,OAAO,CAAC,UAAU,CAAC,CAAA;QACrB,KAAK,UAAU;YACb,OAAO,CAAC,KAAK,CAAC,CAAA;QAChB;YACE,MAAM,IAAI,GAAG,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAA;KACvC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,QAAQ,KAAK,EAAE;QACb,KAAK,SAAS;YACZ,OAAO,iDAAiD,CAAA;QAC1D,KAAK,QAAQ;YACX,OAAO,gDAAgD,CAAA;QACzD,KAAK,cAAc;YACjB,OAAO,2EAA2E,CAAA;QACpF,KAAK,KAAK;YACR,OAAO,sDAAsD,CAAA;QAC/D,KAAK,UAAU;YACb,OAAO,gEAAgE,CAAA;QACzE;YACE,OAAO,KAAK,CAAA;KACf;AACH,CAAC","sourcesContent":["import {Bug} from '../error.js'\nimport {allAPIs, API} from '../network/api.js'\n\n/**\n * Generate a flat array with all the default scopes for all the APIs plus\n * any custom scope defined by the user.\n * @param extraScopes custom user-defined scopes\n * @returns Array of scopes\n */\nexport function allDefaultScopes(extraScopes: string[] = []): string[] {\n let scopes = allAPIs.map(defaultApiScopes).flat()\n scopes = ['openid', ...scopes, ...extraScopes].map(scopeTransform)\n return Array.from(new Set(scopes))\n}\n\n/**\n * Generate a flat array with the default scopes for the given API plus\n * any custom scope defined by the user\n * @param api API to get the scopes for\n * @param extraScopes custom user-defined scopes\n * @returns Array of scopes\n */\nexport function apiScopes(api: API, extraScopes: string[] = []): string[] {\n const scopes = ['openid', ...defaultApiScopes(api), ...extraScopes.map(scopeTransform)].map(scopeTransform)\n return Array.from(new Set(scopes))\n}\n\nfunction defaultApiScopes(api: API): string[] {\n switch (api) {\n case 'admin':\n return ['graphql', 'themes', 'collaborator']\n case 'storefront-renderer':\n return ['devtools']\n case 'partners':\n return ['cli']\n default:\n throw new Bug(`Unknown API: ${api}`)\n }\n}\n\nfunction scopeTransform(scope: string): string {\n switch (scope) {\n case 'graphql':\n return 'https://api.shopify.com/auth/shop.admin.graphql'\n case 'themes':\n return 'https://api.shopify.com/auth/shop.admin.themes'\n case 'collaborator':\n return 'https://api.shopify.com/auth/partners.collaborator-relationships.readonly'\n case 'cli':\n return 'https://api.shopify.com/auth/partners.app.cli.access'\n case 'devtools':\n return 'https://api.shopify.com/auth/shop.storefront-renderer.devtools'\n default:\n return scope\n }\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import type { Session } from './schema.js';
2
+ /**
3
+ * The identifier of the session in the secure store.
4
+ */
5
+ export declare const identifier = "session";
6
+ /**
7
+ * Serializes the session as a JSON and stores it securely in the system.
8
+ * If the secure store is not available, the session is stored in the local config.
9
+ * @param session {Session} the session to store.
10
+ */
11
+ export declare function store(session: Session): Promise<void>;
12
+ /**
13
+ * Fetches the session from the secure store and returns it.
14
+ * If the secure store is not available, the session is fetched from the local config.
15
+ * If the format of the session is invalid, the method will discard it.
16
+ * In the future might add some logic for supporting migrating the schema
17
+ * of already-persisted sessions.
18
+ * @returns {Promise<Session\undefined>} Returns a promise that resolves with the session if it exists and is valid.
19
+ */
20
+ export declare function fetch(): Promise<Session | undefined>;
21
+ /**
22
+ * Removes a session from the system.
23
+ */
24
+ export declare function remove(): Promise<void>;
@@ -0,0 +1,88 @@
1
+ import { SessionSchema } from './schema.js';
2
+ import constants from '../constants.js';
3
+ import { platformAndArch } from '../os.js';
4
+ import { store as secureStore, fetch as secureFetch, remove as secureRemove } from '../secure-store.js';
5
+ import { cliKitStore } from '../store.js';
6
+ import { content, debug } from '../output.js';
7
+ /**
8
+ * The identifier of the session in the secure store.
9
+ */
10
+ export const identifier = 'session';
11
+ /**
12
+ * Serializes the session as a JSON and stores it securely in the system.
13
+ * If the secure store is not available, the session is stored in the local config.
14
+ * @param session {Session} the session to store.
15
+ */
16
+ export async function store(session) {
17
+ const jsonSession = JSON.stringify(session);
18
+ if (await secureStoreAvailable()) {
19
+ await secureStore(identifier, jsonSession);
20
+ }
21
+ else {
22
+ await cliKitStore().setSession(jsonSession);
23
+ }
24
+ }
25
+ /**
26
+ * Fetches the session from the secure store and returns it.
27
+ * If the secure store is not available, the session is fetched from the local config.
28
+ * If the format of the session is invalid, the method will discard it.
29
+ * In the future might add some logic for supporting migrating the schema
30
+ * of already-persisted sessions.
31
+ * @returns {Promise<Session\undefined>} Returns a promise that resolves with the session if it exists and is valid.
32
+ */
33
+ export async function fetch() {
34
+ let content;
35
+ if (await secureStoreAvailable()) {
36
+ content = await secureFetch(identifier);
37
+ }
38
+ else {
39
+ content = cliKitStore().getSession();
40
+ }
41
+ if (!content) {
42
+ return undefined;
43
+ }
44
+ const contentJson = JSON.parse(content);
45
+ const parsedSession = await SessionSchema.safeParseAsync(contentJson);
46
+ if (parsedSession.success) {
47
+ return parsedSession.data;
48
+ }
49
+ else {
50
+ await remove();
51
+ return undefined;
52
+ }
53
+ }
54
+ /**
55
+ * Removes a session from the system.
56
+ */
57
+ export async function remove() {
58
+ if (await secureStoreAvailable()) {
59
+ await secureRemove(identifier);
60
+ }
61
+ else {
62
+ cliKitStore().removeSession();
63
+ }
64
+ }
65
+ /**
66
+ * Returns true if the secure store is available on the system.
67
+ * Keytar it's not supported on some Linux environments or Windows.
68
+ * More details: https://github.com/Shopify/shopify-cli-planning/issues/261
69
+ * @returns a boolean indicating if the secure store is available.
70
+ */
71
+ async function secureStoreAvailable() {
72
+ try {
73
+ if (platformAndArch().platform === 'windows') {
74
+ debug(content `Secure store not supported on Windows`);
75
+ return false;
76
+ }
77
+ const keytar = await import('keytar');
78
+ await keytar.default.findCredentials(constants.keychain.service);
79
+ debug(content `Secure store is available`);
80
+ return true;
81
+ // eslint-disable-next-line no-catch-all/no-catch-all
82
+ }
83
+ catch (_error) {
84
+ debug(content `Failed to load secure store`);
85
+ return false;
86
+ }
87
+ }
88
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/session/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAA;AACzC,OAAO,SAAS,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,UAAU,CAAA;AACxC,OAAO,EAAC,KAAK,IAAI,WAAW,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,IAAI,YAAY,EAAC,MAAM,oBAAoB,CAAA;AACrG,OAAO,EAAC,WAAW,EAAC,MAAM,aAAa,CAAA;AACvC,OAAO,EAAC,OAAO,EAAE,KAAK,EAAC,MAAM,cAAc,CAAA;AAG3C;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAA;AAEnC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,OAAgB;IAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;KAC3C;SAAM;QACL,MAAM,WAAW,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;KAC5C;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,IAAI,OAAO,CAAA;IACX,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,OAAO,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAA;KACxC;SAAM;QACL,OAAO,GAAG,WAAW,EAAE,CAAC,UAAU,EAAE,CAAA;KACrC;IAED,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,SAAS,CAAA;KACjB;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACvC,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;IACrE,IAAI,aAAa,CAAC,OAAO,EAAE;QACzB,OAAO,aAAa,CAAC,IAAI,CAAA;KAC1B;SAAM;QACL,MAAM,MAAM,EAAE,CAAA;QACd,OAAO,SAAS,CAAA;KACjB;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,YAAY,CAAC,UAAU,CAAC,CAAA;KAC/B;SAAM;QACL,WAAW,EAAE,CAAC,aAAa,EAAE,CAAA;KAC9B;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,oBAAoB;IACjC,IAAI;QACF,IAAI,eAAe,EAAE,CAAC,QAAQ,KAAK,SAAS,EAAE;YAC5C,KAAK,CAAC,OAAO,CAAA,uCAAuC,CAAC,CAAA;YACrD,OAAO,KAAK,CAAA;SACb;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrC,MAAM,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAChE,KAAK,CAAC,OAAO,CAAA,2BAA2B,CAAC,CAAA;QACzC,OAAO,IAAI,CAAA;QACX,qDAAqD;KACtD;IAAC,OAAO,MAAM,EAAE;QACf,KAAK,CAAC,OAAO,CAAA,6BAA6B,CAAC,CAAA;QAC3C,OAAO,KAAK,CAAA;KACb;AACH,CAAC","sourcesContent":["import {SessionSchema} from './schema.js'\nimport constants from '../constants.js'\nimport {platformAndArch} from '../os.js'\nimport {store as secureStore, fetch as secureFetch, remove as secureRemove} from '../secure-store.js'\nimport {cliKitStore} from '../store.js'\nimport {content, debug} from '../output.js'\nimport type {Session} from './schema.js'\n\n/**\n * The identifier of the session in the secure store.\n */\nexport const identifier = 'session'\n\n/**\n * Serializes the session as a JSON and stores it securely in the system.\n * If the secure store is not available, the session is stored in the local config.\n * @param session {Session} the session to store.\n */\nexport async function store(session: Session) {\n const jsonSession = JSON.stringify(session)\n if (await secureStoreAvailable()) {\n await secureStore(identifier, jsonSession)\n } else {\n await cliKitStore().setSession(jsonSession)\n }\n}\n\n/**\n * Fetches the session from the secure store and returns it.\n * If the secure store is not available, the session is fetched from the local config.\n * If the format of the session is invalid, the method will discard it.\n * In the future might add some logic for supporting migrating the schema\n * of already-persisted sessions.\n * @returns {Promise<Session\\undefined>} Returns a promise that resolves with the session if it exists and is valid.\n */\nexport async function fetch(): Promise<Session | undefined> {\n let content\n if (await secureStoreAvailable()) {\n content = await secureFetch(identifier)\n } else {\n content = cliKitStore().getSession()\n }\n\n if (!content) {\n return undefined\n }\n const contentJson = JSON.parse(content)\n const parsedSession = await SessionSchema.safeParseAsync(contentJson)\n if (parsedSession.success) {\n return parsedSession.data\n } else {\n await remove()\n return undefined\n }\n}\n\n/**\n * Removes a session from the system.\n */\nexport async function remove() {\n if (await secureStoreAvailable()) {\n await secureRemove(identifier)\n } else {\n cliKitStore().removeSession()\n }\n}\n\n/**\n * Returns true if the secure store is available on the system.\n * Keytar it's not supported on some Linux environments or Windows.\n * More details: https://github.com/Shopify/shopify-cli-planning/issues/261\n * @returns a boolean indicating if the secure store is available.\n */\nasync function secureStoreAvailable(): Promise<boolean> {\n try {\n if (platformAndArch().platform === 'windows') {\n debug(content`Secure store not supported on Windows`)\n return false\n }\n const keytar = await import('keytar')\n await keytar.default.findCredentials(constants.keychain.service)\n debug(content`Secure store is available`)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (_error) {\n debug(content`Failed to load secure store`)\n return false\n }\n}\n"]}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * It represents a temporary token that can be
3
+ * used to send authenticated HTTP requests.
4
+ */
5
+ declare class Token {
6
+ /**
7
+ * A fully-qualified domain name of the service
8
+ * this token is for.
9
+ */
10
+ fqdn: string;
11
+ /**
12
+ * Access token
13
+ */
14
+ accessToken: string;
15
+ /**
16
+ * Token to refresh the access token if it has expired.
17
+ */
18
+ refreshToken?: string;
19
+ /**
20
+ * The expiration date of the session
21
+ */
22
+ expiresAt: Date;
23
+ /**
24
+ * The list of scopes the token has access to.
25
+ */
26
+ scopes: string[];
27
+ constructor(options: {
28
+ fqdn: string;
29
+ accessToken: string;
30
+ refreshToken?: string;
31
+ expiresAt: Date;
32
+ scopes: string[];
33
+ });
34
+ /**
35
+ * Returns true if the session is expired.
36
+ * @returns {boolean} True if the session is expired.
37
+ */
38
+ get isExpired(): boolean;
39
+ }
40
+ export default Token;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * It represents a temporary token that can be
3
+ * used to send authenticated HTTP requests.
4
+ */
5
+ class Token {
6
+ constructor(options) {
7
+ this.fqdn = options.fqdn;
8
+ this.accessToken = options.accessToken;
9
+ this.refreshToken = options.refreshToken;
10
+ this.expiresAt = options.expiresAt;
11
+ this.scopes = options.scopes;
12
+ }
13
+ /**
14
+ * Returns true if the session is expired.
15
+ * @returns {boolean} True if the session is expired.
16
+ */
17
+ get isExpired() {
18
+ return new Date() > this.expiresAt;
19
+ }
20
+ }
21
+ export default Token;
22
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/session/token.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,KAAK;IA2BT,YAAY,OAAsG;QAChH,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;QACxB,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAA;QACtC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAA;QACxC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;QAClC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC9B,CAAC;IAED;;;OAGG;IACH,IAAI,SAAS;QACX,OAAO,IAAI,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAA;IACpC,CAAC;CACF;AAED,eAAe,KAAK,CAAA","sourcesContent":["/**\n * It represents a temporary token that can be\n * used to send authenticated HTTP requests.\n */\nclass Token {\n /**\n * A fully-qualified domain name of the service\n * this token is for.\n */\n fqdn: string\n\n /**\n * Access token\n */\n accessToken: string\n\n /**\n * Token to refresh the access token if it has expired.\n */\n refreshToken?: string\n\n /**\n * The expiration date of the session\n */\n expiresAt: Date\n\n /**\n * The list of scopes the token has access to.\n */\n scopes: string[]\n\n constructor(options: {fqdn: string; accessToken: string; refreshToken?: string; expiresAt: Date; scopes: string[]}) {\n this.fqdn = options.fqdn\n this.accessToken = options.accessToken\n this.refreshToken = options.refreshToken\n this.expiresAt = options.expiresAt\n this.scopes = options.scopes\n }\n\n /**\n * Returns true if the session is expired.\n * @returns {boolean} True if the session is expired.\n */\n get isExpired(): boolean {\n return new Date() > this.expiresAt\n }\n}\n\nexport default Token\n"]}
@@ -0,0 +1,17 @@
1
+ import { ApplicationToken, IdentityToken } from './schema.js';
2
+ import { OAuthApplications } from '../session.js';
3
+ declare type ValidationResult = 'needs_refresh' | 'needs_full_auth' | 'ok';
4
+ /**
5
+ * Validate if the current session is valid or we need to refresh/re-authenticate
6
+ * @param scopes {string[]} requested scopes to validate
7
+ * @param applications {OAuthApplications} requested applications
8
+ * @param session current session with identity and application tokens
9
+ * @returns {ValidationResult} 'ok' if the session is valid, 'needs_full_auth' if we need to re-authenticate, 'needs_refresh' if we need to refresh the session
10
+ */
11
+ export declare function validateSession(scopes: string[], applications: OAuthApplications, session: {
12
+ identity: IdentityToken;
13
+ applications: {
14
+ [x: string]: ApplicationToken;
15
+ };
16
+ }): Promise<ValidationResult>;
17
+ export {};
@@ -0,0 +1,75 @@
1
+ import { applicationId } from './identity.js';
2
+ import constants from '../constants.js';
3
+ import { identity, partners } from '../api.js';
4
+ import { debug } from '../output.js';
5
+ /**
6
+ * Validate if an identity token is valid for the requested scopes
7
+ * @param requestedScopes scopes
8
+ * @param identity
9
+ * @returns
10
+ */
11
+ function validateScopes(requestedScopes, identity) {
12
+ const currentScopes = identity.scopes;
13
+ return requestedScopes.every((scope) => currentScopes.includes(scope));
14
+ }
15
+ /**
16
+ * Validate if the current session is valid or we need to refresh/re-authenticate
17
+ * @param scopes {string[]} requested scopes to validate
18
+ * @param applications {OAuthApplications} requested applications
19
+ * @param session current session with identity and application tokens
20
+ * @returns {ValidationResult} 'ok' if the session is valid, 'needs_full_auth' if we need to re-authenticate, 'needs_refresh' if we need to refresh the session
21
+ */
22
+ export async function validateSession(scopes, applications, session) {
23
+ if (!session)
24
+ return 'needs_full_auth';
25
+ const scopesAreValid = validateScopes(scopes, session.identity);
26
+ const identityIsValid = await identity.validateIdentityToken(session.identity.accessToken);
27
+ if (!scopesAreValid)
28
+ return 'needs_full_auth';
29
+ let tokensAreExpired = isTokenExpired(session.identity);
30
+ let tokensAreRevoked = false;
31
+ if (applications.partnersApi) {
32
+ const appId = applicationId('partners');
33
+ const token = session.applications[appId];
34
+ tokensAreRevoked = tokensAreRevoked || (await isPartnersTokenRevoked(token));
35
+ tokensAreExpired = tokensAreExpired || isTokenExpired(token);
36
+ }
37
+ if (applications.storefrontRendererApi) {
38
+ const appId = applicationId('storefront-renderer');
39
+ const token = session.applications[appId];
40
+ tokensAreExpired = tokensAreExpired || isTokenExpired(token);
41
+ }
42
+ if (applications.adminApi) {
43
+ const appId = applicationId('admin');
44
+ const realAppId = `${applications.adminApi.storeFqdn}-${appId}`;
45
+ const token = session.applications[realAppId];
46
+ tokensAreExpired = tokensAreExpired || isTokenExpired(token);
47
+ }
48
+ debug(`
49
+ The validation of the token for application/identity completed with the following results:
50
+ - It's expired: ${tokensAreExpired}
51
+ - It's been revoked: ${tokensAreRevoked}
52
+ - It's invalid in identity: ${!identityIsValid}
53
+ `);
54
+ if (tokensAreExpired)
55
+ return 'needs_refresh';
56
+ if (tokensAreRevoked)
57
+ return 'needs_full_auth';
58
+ if (!identityIsValid)
59
+ return 'needs_full_auth';
60
+ return 'ok';
61
+ }
62
+ function isTokenExpired(token) {
63
+ if (!token)
64
+ return true;
65
+ return token.expiresAt < expireThreshold();
66
+ }
67
+ async function isPartnersTokenRevoked(token) {
68
+ if (!token)
69
+ return false;
70
+ return partners.checkIfTokenIsRevoked(token.accessToken);
71
+ }
72
+ function expireThreshold() {
73
+ return new Date(Date.now() + constants.session.expirationTimeMarginInMinutes * 60 * 1000);
74
+ }
75
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/session/validate.ts"],"names":[],"mappings":"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","sourcesContent":["import {applicationId} from './identity.js'\nimport {ApplicationToken, IdentityToken} from './schema.js'\nimport constants from '../constants.js'\nimport {OAuthApplications} from '../session.js'\nimport {identity, partners} from '../api.js'\nimport {debug} from '../output.js'\n\ntype ValidationResult = 'needs_refresh' | 'needs_full_auth' | 'ok'\n\n/**\n * Validate if an identity token is valid for the requested scopes\n * @param requestedScopes scopes\n * @param identity\n * @returns\n */\nfunction validateScopes(requestedScopes: string[], identity: IdentityToken) {\n const currentScopes = identity.scopes\n return requestedScopes.every((scope) => currentScopes.includes(scope))\n}\n\n/**\n * Validate if the current session is valid or we need to refresh/re-authenticate\n * @param scopes {string[]} requested scopes to validate\n * @param applications {OAuthApplications} requested applications\n * @param session current session with identity and application tokens\n * @returns {ValidationResult} 'ok' if the session is valid, 'needs_full_auth' if we need to re-authenticate, 'needs_refresh' if we need to refresh the session\n */\nexport async function validateSession(\n scopes: string[],\n applications: OAuthApplications,\n session: {\n identity: IdentityToken\n applications: {[x: string]: ApplicationToken}\n },\n): Promise<ValidationResult> {\n if (!session) return 'needs_full_auth'\n const scopesAreValid = validateScopes(scopes, session.identity)\n const identityIsValid = await identity.validateIdentityToken(session.identity.accessToken)\n if (!scopesAreValid) return 'needs_full_auth'\n let tokensAreExpired = isTokenExpired(session.identity)\n let tokensAreRevoked = false\n\n if (applications.partnersApi) {\n const appId = applicationId('partners')\n const token = session.applications[appId]\n tokensAreRevoked = tokensAreRevoked || (await isPartnersTokenRevoked(token))\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n if (applications.storefrontRendererApi) {\n const appId = applicationId('storefront-renderer')\n const token = session.applications[appId]\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n if (applications.adminApi) {\n const appId = applicationId('admin')\n const realAppId = `${applications.adminApi.storeFqdn}-${appId}`\n const token = session.applications[realAppId]\n tokensAreExpired = tokensAreExpired || isTokenExpired(token)\n }\n\n debug(`\nThe validation of the token for application/identity completed with the following results:\n- It's expired: ${tokensAreExpired}\n- It's been revoked: ${tokensAreRevoked}\n- It's invalid in identity: ${!identityIsValid}\n `)\n\n if (tokensAreExpired) return 'needs_refresh'\n if (tokensAreRevoked) return 'needs_full_auth'\n if (!identityIsValid) return 'needs_full_auth'\n return 'ok'\n}\n\nfunction isTokenExpired(token: ApplicationToken): boolean {\n if (!token) return true\n return token.expiresAt < expireThreshold()\n}\n\nasync function isPartnersTokenRevoked(token: ApplicationToken) {\n if (!token) return false\n return partners.checkIfTokenIsRevoked(token.accessToken)\n}\n\nfunction expireThreshold(): Date {\n return new Date(Date.now() + constants.session.expirationTimeMarginInMinutes * 60 * 1000)\n}\n"]}
@@ -0,0 +1,88 @@
1
+ /// <reference types="node" />
2
+ import { Abort } from './error.js';
3
+ /**
4
+ * A scope supported by the Shopify Admin API.
5
+ */
6
+ declare type AdminAPIScope = 'graphql' | 'themes' | 'collaborator' | string;
7
+ /**
8
+ * It represents the options to authenticate against the Shopify Admin API.
9
+ */
10
+ interface AdminAPIOAuthOptions {
11
+ /** Store to request permissions for */
12
+ storeFqdn: string;
13
+ /** List of scopes to request permissions for */
14
+ scopes: AdminAPIScope[];
15
+ }
16
+ /**
17
+ * A scope supported by the Partners API.
18
+ */
19
+ declare type PartnersAPIScope = 'cli' | string;
20
+ interface PartnersAPIOAuthOptions {
21
+ /** List of scopes to request permissions for */
22
+ scopes: PartnersAPIScope[];
23
+ }
24
+ /**
25
+ * A scope supported by the Storefront Renderer API.
26
+ */
27
+ declare type StorefrontRendererScope = 'devtools' | string;
28
+ interface StorefrontRendererAPIOAuthOptions {
29
+ /** List of scopes to request permissions for */
30
+ scopes: StorefrontRendererScope[];
31
+ }
32
+ /**
33
+ * It represents the authentication requirements and
34
+ * is the input necessary to trigger the authentication
35
+ * flow.
36
+ */
37
+ export interface OAuthApplications {
38
+ adminApi?: AdminAPIOAuthOptions;
39
+ storefrontRendererApi?: StorefrontRendererAPIOAuthOptions;
40
+ partnersApi?: PartnersAPIOAuthOptions;
41
+ }
42
+ export interface AdminSession {
43
+ token: string;
44
+ storeFqdn: string;
45
+ }
46
+ export interface OAuthSession {
47
+ admin?: AdminSession;
48
+ partners?: string;
49
+ storefront?: string;
50
+ }
51
+ export declare const PartnerOrganizationNotFoundError: () => Abort;
52
+ /**
53
+ * Ensure that we have a valid session to access the Partners API.
54
+ * If SHOPIFY_CLI_PARTNERS_TOKEN exists, that token will be used to obtain a valid Partners Token
55
+ * If SHOPIFY_CLI_PARTNERS_TOKEN exists, scopes will be ignored
56
+ * @param scopes {string[]} Optional array of extra scopes to authenticate with.
57
+ * @returns {Promise<string>} The access token for the Partners API.
58
+ */
59
+ export declare function ensureAuthenticatedPartners(scopes?: string[], env?: NodeJS.ProcessEnv): Promise<string>;
60
+ /**
61
+ * Ensure that we have a valid session to access the Storefront API.
62
+ * @param scopes {string[]} Optional array of extra scopes to authenticate with.
63
+ * @returns {Promise<string>} The access token for the Storefront API.
64
+ */
65
+ export declare function ensureAuthenticatedStorefront(scopes?: string[]): Promise<string>;
66
+ /**
67
+ * Ensure that we have a valid Admin session for the given store.
68
+ * @param store {string} Store fqdn to request auth for
69
+ * @param scopes {string[]} Optional array of extra scopes to authenticate with.
70
+ * @returns {Promise<string>} The access token for the Admin API
71
+ */
72
+ export declare function ensureAuthenticatedAdmin(store: string, scopes?: string[]): Promise<AdminSession>;
73
+ /**
74
+ * This method ensures that we have a valid session to authenticate against the given applications using the provided scopes.
75
+ * @param applications {OAuthApplications} An object containing the applications we need to be authenticated with.
76
+ * @returns {OAuthSession} An instance with the access tokens organized by application.
77
+ */
78
+ export declare function ensureAuthenticated(applications: OAuthApplications, env?: NodeJS.ProcessEnv): Promise<OAuthSession>;
79
+ export declare function hasPartnerAccount(partnersToken: string): Promise<boolean>;
80
+ /**
81
+ * If the user creates an account from the Identity website, the created
82
+ * account won't get a Partner organization created. We need to detect that
83
+ * and take the user to create a partner organization.
84
+ * @param partnersToken {string} Partners token
85
+ */
86
+ export declare function ensureUserHasPartnerAccount(partnersToken: string): Promise<void>;
87
+ export declare function logout(): Promise<void>;
88
+ export {};