@shopify/ui-extensions-server-kit 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (367) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/README.md +74 -0
  3. package/dist/ExtensionServerClient/ExtensionServerClient.cjs.js +1 -0
  4. package/dist/ExtensionServerClient/ExtensionServerClient.d.ts +28 -0
  5. package/dist/ExtensionServerClient/ExtensionServerClient.es.js +133 -0
  6. package/dist/ExtensionServerClient/ExtensionServerClient.test.d.ts +1 -0
  7. package/dist/ExtensionServerClient/index.d.ts +2 -0
  8. package/dist/ExtensionServerClient/types.cjs.js +1 -0
  9. package/dist/ExtensionServerClient/types.d.ts +124 -0
  10. package/dist/ExtensionServerClient/types.es.js +4 -0
  11. package/dist/context/ExtensionServerProvider.cjs.js +1 -0
  12. package/dist/context/ExtensionServerProvider.d.ts +2 -0
  13. package/dist/context/ExtensionServerProvider.es.js +29 -0
  14. package/dist/context/ExtensionServerProvider.test.d.ts +1 -0
  15. package/dist/context/constants.cjs.js +1 -0
  16. package/dist/context/constants.d.ts +3 -0
  17. package/dist/context/constants.es.js +14 -0
  18. package/dist/context/index.d.ts +3 -0
  19. package/dist/context/types.d.ts +11 -0
  20. package/dist/hooks/index.d.ts +5 -0
  21. package/dist/hooks/useExtensionClient.cjs.js +1 -0
  22. package/dist/hooks/useExtensionClient.d.ts +1 -0
  23. package/dist/hooks/useExtensionClient.es.js +8 -0
  24. package/dist/hooks/useExtensionServerContext.cjs.js +1 -0
  25. package/dist/hooks/useExtensionServerContext.d.ts +1 -0
  26. package/dist/hooks/useExtensionServerContext.es.js +6 -0
  27. package/dist/hooks/useExtensionServerEvent.cjs.js +1 -0
  28. package/dist/hooks/useExtensionServerEvent.d.ts +1 -0
  29. package/dist/hooks/useExtensionServerEvent.es.js +9 -0
  30. package/dist/hooks/useExtensionServerState.cjs.js +1 -0
  31. package/dist/hooks/useExtensionServerState.d.ts +1 -0
  32. package/dist/hooks/useExtensionServerState.es.js +9 -0
  33. package/dist/hooks/useIsomorphicLayoutEffect.cjs.js +1 -0
  34. package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -0
  35. package/dist/hooks/useIsomorphicLayoutEffect.es.js +5 -0
  36. package/dist/i18n.cjs.js +1 -0
  37. package/dist/i18n.d.ts +93 -0
  38. package/dist/i18n.es.js +61 -0
  39. package/dist/i18n.test.d.ts +1 -0
  40. package/dist/index.cjs.js +1 -0
  41. package/dist/index.cjs2.js +1 -0
  42. package/dist/index.d.ts +7 -0
  43. package/dist/index.es.js +54 -0
  44. package/dist/index.es2.js +8 -0
  45. package/dist/state/actions/actions.cjs.js +1 -0
  46. package/dist/state/actions/actions.d.ts +6 -0
  47. package/dist/state/actions/actions.es.js +37 -0
  48. package/dist/state/actions/index.d.ts +2 -0
  49. package/dist/state/actions/types.d.ts +21 -0
  50. package/dist/state/index.d.ts +2 -0
  51. package/dist/state/reducers/constants.cjs.js +1 -0
  52. package/dist/state/reducers/constants.d.ts +2 -0
  53. package/dist/state/reducers/constants.es.js +7 -0
  54. package/dist/state/reducers/extensionServerReducer.cjs.js +1 -0
  55. package/dist/state/reducers/extensionServerReducer.d.ts +3 -0
  56. package/dist/state/reducers/extensionServerReducer.es.js +57 -0
  57. package/dist/state/reducers/extensionServerReducer.test.d.ts +1 -0
  58. package/dist/state/reducers/index.d.ts +3 -0
  59. package/dist/state/reducers/types.d.ts +6 -0
  60. package/dist/testing/MockExtensionServerProvider.cjs.js +1 -0
  61. package/dist/testing/MockExtensionServerProvider.d.ts +7 -0
  62. package/dist/testing/MockExtensionServerProvider.es.js +24 -0
  63. package/dist/testing/app.cjs.js +1 -0
  64. package/dist/testing/app.d.ts +2 -0
  65. package/dist/testing/app.es.js +16 -0
  66. package/dist/testing/extensions.cjs.js +1 -0
  67. package/dist/testing/extensions.d.ts +6 -0
  68. package/dist/testing/extensions.es.js +65 -0
  69. package/dist/testing/index.d.ts +3 -0
  70. package/dist/types.cjs.js +1 -0
  71. package/dist/types.d.ts +169 -0
  72. package/dist/types.es.js +4 -0
  73. package/dist/utilities/assetToString.cjs.js +1 -0
  74. package/dist/utilities/assetToString.d.ts +2 -0
  75. package/dist/utilities/assetToString.es.js +7 -0
  76. package/dist/utilities/assetToString.test.d.ts +1 -0
  77. package/dist/utilities/groupByKey.cjs.js +1 -0
  78. package/dist/utilities/groupByKey.d.ts +3 -0
  79. package/dist/utilities/groupByKey.es.js +6 -0
  80. package/dist/utilities/index.d.ts +7 -0
  81. package/dist/utilities/isUIExtension.cjs.js +1 -0
  82. package/dist/utilities/isUIExtension.d.ts +1 -0
  83. package/dist/utilities/isUIExtension.es.js +6 -0
  84. package/dist/utilities/isValidSurface.cjs.js +1 -0
  85. package/dist/utilities/isValidSurface.d.ts +2 -0
  86. package/dist/utilities/isValidSurface.es.js +7 -0
  87. package/dist/utilities/noop.cjs.js +1 -0
  88. package/dist/utilities/noop.d.ts +1 -0
  89. package/dist/utilities/noop.es.js +5 -0
  90. package/dist/utilities/replaceUpdated.cjs.js +1 -0
  91. package/dist/utilities/replaceUpdated.d.ts +1 -0
  92. package/dist/utilities/replaceUpdated.es.js +14 -0
  93. package/dist/utilities/replaceUpdated.test.d.ts +1 -0
  94. package/dist/utilities/set.cjs.js +1 -0
  95. package/dist/utilities/set.d.ts +4 -0
  96. package/dist/utilities/set.es.js +18 -0
  97. package/dist/utilities/set.test.d.ts +1 -0
  98. package/index.d.ts +1 -0
  99. package/index.js +1 -0
  100. package/index.mjs +1 -0
  101. package/node_modules/@shopify/react-testing/LICENSE.md +21 -0
  102. package/node_modules/@shopify/react-testing/README.md +711 -0
  103. package/node_modules/@shopify/react-testing/build/cjs/TestWrapper.js +52 -0
  104. package/node_modules/@shopify/react-testing/build/cjs/_virtual/_rollupPluginBabelHelpers.js +47 -0
  105. package/node_modules/@shopify/react-testing/build/cjs/compat.js +14 -0
  106. package/node_modules/@shopify/react-testing/build/cjs/destroy.js +13 -0
  107. package/node_modules/@shopify/react-testing/build/cjs/element.js +225 -0
  108. package/node_modules/@shopify/react-testing/build/cjs/index.js +21 -0
  109. package/node_modules/@shopify/react-testing/build/cjs/matchers/components.js +46 -0
  110. package/node_modules/@shopify/react-testing/build/cjs/matchers/context.js +25 -0
  111. package/node_modules/@shopify/react-testing/build/cjs/matchers/index.js +16 -0
  112. package/node_modules/@shopify/react-testing/build/cjs/matchers/props.js +38 -0
  113. package/node_modules/@shopify/react-testing/build/cjs/matchers/strings.js +42 -0
  114. package/node_modules/@shopify/react-testing/build/cjs/matchers/utilities.js +110 -0
  115. package/node_modules/@shopify/react-testing/build/cjs/mount.js +76 -0
  116. package/node_modules/@shopify/react-testing/build/cjs/root.js +284 -0
  117. package/node_modules/@shopify/react-testing/build/cjs/toReactString.js +86 -0
  118. package/node_modules/@shopify/react-testing/build/cjs/types.js +28 -0
  119. package/node_modules/@shopify/react-testing/build/esm/TestWrapper.mjs +44 -0
  120. package/node_modules/@shopify/react-testing/build/esm/_virtual/_rollupPluginBabelHelpers.mjs +42 -0
  121. package/node_modules/@shopify/react-testing/build/esm/compat.mjs +10 -0
  122. package/node_modules/@shopify/react-testing/build/esm/destroy.mjs +9 -0
  123. package/node_modules/@shopify/react-testing/build/esm/element.mjs +221 -0
  124. package/node_modules/@shopify/react-testing/build/esm/index.mjs +5 -0
  125. package/node_modules/@shopify/react-testing/build/esm/matchers/components.mjs +41 -0
  126. package/node_modules/@shopify/react-testing/build/esm/matchers/context.mjs +21 -0
  127. package/node_modules/@shopify/react-testing/build/esm/matchers/index.mjs +14 -0
  128. package/node_modules/@shopify/react-testing/build/esm/matchers/props.mjs +33 -0
  129. package/node_modules/@shopify/react-testing/build/esm/matchers/strings.mjs +37 -0
  130. package/node_modules/@shopify/react-testing/build/esm/matchers/utilities.mjs +101 -0
  131. package/node_modules/@shopify/react-testing/build/esm/mount.mjs +70 -0
  132. package/node_modules/@shopify/react-testing/build/esm/root.mjs +275 -0
  133. package/node_modules/@shopify/react-testing/build/esm/toReactString.mjs +80 -0
  134. package/node_modules/@shopify/react-testing/build/esm/types.mjs +26 -0
  135. package/node_modules/@shopify/react-testing/build/esnext/TestWrapper.esnext +44 -0
  136. package/node_modules/@shopify/react-testing/build/esnext/compat.esnext +10 -0
  137. package/node_modules/@shopify/react-testing/build/esnext/destroy.esnext +9 -0
  138. package/node_modules/@shopify/react-testing/build/esnext/element.esnext +221 -0
  139. package/node_modules/@shopify/react-testing/build/esnext/index.esnext +5 -0
  140. package/node_modules/@shopify/react-testing/build/esnext/matchers/components.esnext +41 -0
  141. package/node_modules/@shopify/react-testing/build/esnext/matchers/context.esnext +21 -0
  142. package/node_modules/@shopify/react-testing/build/esnext/matchers/index.esnext +14 -0
  143. package/node_modules/@shopify/react-testing/build/esnext/matchers/props.esnext +33 -0
  144. package/node_modules/@shopify/react-testing/build/esnext/matchers/strings.esnext +37 -0
  145. package/node_modules/@shopify/react-testing/build/esnext/matchers/utilities.esnext +99 -0
  146. package/node_modules/@shopify/react-testing/build/esnext/mount.esnext +71 -0
  147. package/node_modules/@shopify/react-testing/build/esnext/root.esnext +275 -0
  148. package/node_modules/@shopify/react-testing/build/esnext/toReactString.esnext +80 -0
  149. package/node_modules/@shopify/react-testing/build/esnext/types.esnext +26 -0
  150. package/node_modules/@shopify/react-testing/build/ts/TestWrapper.d.ts +17 -0
  151. package/node_modules/@shopify/react-testing/build/ts/TestWrapper.d.ts.map +1 -0
  152. package/node_modules/@shopify/react-testing/build/ts/compat.d.ts +3 -0
  153. package/node_modules/@shopify/react-testing/build/ts/compat.d.ts.map +1 -0
  154. package/node_modules/@shopify/react-testing/build/ts/destroy.d.ts +2 -0
  155. package/node_modules/@shopify/react-testing/build/ts/destroy.d.ts.map +1 -0
  156. package/node_modules/@shopify/react-testing/build/ts/element.d.ts +42 -0
  157. package/node_modules/@shopify/react-testing/build/ts/element.d.ts.map +1 -0
  158. package/node_modules/@shopify/react-testing/build/ts/index.d.ts +7 -0
  159. package/node_modules/@shopify/react-testing/build/ts/index.d.ts.map +1 -0
  160. package/node_modules/@shopify/react-testing/build/ts/matchers/components.d.ts +12 -0
  161. package/node_modules/@shopify/react-testing/build/ts/matchers/components.d.ts.map +1 -0
  162. package/node_modules/@shopify/react-testing/build/ts/matchers/context.d.ts +8 -0
  163. package/node_modules/@shopify/react-testing/build/ts/matchers/context.d.ts.map +1 -0
  164. package/node_modules/@shopify/react-testing/build/ts/matchers/index.d.ts +20 -0
  165. package/node_modules/@shopify/react-testing/build/ts/matchers/index.d.ts.map +1 -0
  166. package/node_modules/@shopify/react-testing/build/ts/matchers/props.d.ts +10 -0
  167. package/node_modules/@shopify/react-testing/build/ts/matchers/props.d.ts.map +1 -0
  168. package/node_modules/@shopify/react-testing/build/ts/matchers/strings.d.ts +11 -0
  169. package/node_modules/@shopify/react-testing/build/ts/matchers/strings.d.ts.map +1 -0
  170. package/node_modules/@shopify/react-testing/build/ts/matchers/utilities.d.ts +17 -0
  171. package/node_modules/@shopify/react-testing/build/ts/matchers/utilities.d.ts.map +1 -0
  172. package/node_modules/@shopify/react-testing/build/ts/mount.d.ts +39 -0
  173. package/node_modules/@shopify/react-testing/build/ts/mount.d.ts.map +1 -0
  174. package/node_modules/@shopify/react-testing/build/ts/root.d.ts +55 -0
  175. package/node_modules/@shopify/react-testing/build/ts/root.d.ts.map +1 -0
  176. package/node_modules/@shopify/react-testing/build/ts/toReactString.d.ts +5 -0
  177. package/node_modules/@shopify/react-testing/build/ts/toReactString.d.ts.map +1 -0
  178. package/node_modules/@shopify/react-testing/build/ts/types.d.ts +89 -0
  179. package/node_modules/@shopify/react-testing/build/ts/types.d.ts.map +1 -0
  180. package/node_modules/@shopify/react-testing/index.esnext +1 -0
  181. package/node_modules/@shopify/react-testing/index.js +1 -0
  182. package/node_modules/@shopify/react-testing/index.mjs +1 -0
  183. package/node_modules/@shopify/react-testing/matchers.esnext +1 -0
  184. package/node_modules/@shopify/react-testing/matchers.js +1 -0
  185. package/node_modules/@shopify/react-testing/matchers.mjs +1 -0
  186. package/node_modules/@shopify/react-testing/package.json +69 -0
  187. package/node_modules/@shopify/ui-extensions-test-utils/CHANGELOG.md +66 -0
  188. package/node_modules/@shopify/ui-extensions-test-utils/dist/index.js +3 -0
  189. package/node_modules/@shopify/ui-extensions-test-utils/dist/render.js +5 -0
  190. package/node_modules/@shopify/ui-extensions-test-utils/dist/renderHook.js +20 -0
  191. package/node_modules/@shopify/ui-extensions-test-utils/dist/withProviders.js +6 -0
  192. package/node_modules/@shopify/ui-extensions-test-utils/package.json +41 -0
  193. package/node_modules/@shopify/ui-extensions-test-utils/project.json +39 -0
  194. package/node_modules/@types/node/LICENSE +21 -0
  195. package/node_modules/@types/node/README.md +15 -0
  196. package/node_modules/@types/node/assert/strict.d.ts +8 -0
  197. package/node_modules/@types/node/assert.d.ts +985 -0
  198. package/node_modules/@types/node/async_hooks.d.ts +522 -0
  199. package/node_modules/@types/node/buffer.d.ts +2321 -0
  200. package/node_modules/@types/node/child_process.d.ts +1544 -0
  201. package/node_modules/@types/node/cluster.d.ts +432 -0
  202. package/node_modules/@types/node/console.d.ts +412 -0
  203. package/node_modules/@types/node/constants.d.ts +19 -0
  204. package/node_modules/@types/node/crypto.d.ts +4451 -0
  205. package/node_modules/@types/node/dgram.d.ts +586 -0
  206. package/node_modules/@types/node/diagnostics_channel.d.ts +192 -0
  207. package/node_modules/@types/node/dns/promises.d.ts +381 -0
  208. package/node_modules/@types/node/dns.d.ts +809 -0
  209. package/node_modules/@types/node/dom-events.d.ts +122 -0
  210. package/node_modules/@types/node/domain.d.ts +170 -0
  211. package/node_modules/@types/node/events.d.ts +803 -0
  212. package/node_modules/@types/node/fs/promises.d.ts +1205 -0
  213. package/node_modules/@types/node/fs.d.ts +4211 -0
  214. package/node_modules/@types/node/globals.d.ts +377 -0
  215. package/node_modules/@types/node/globals.global.d.ts +1 -0
  216. package/node_modules/@types/node/http.d.ts +1801 -0
  217. package/node_modules/@types/node/http2.d.ts +2386 -0
  218. package/node_modules/@types/node/https.d.ts +544 -0
  219. package/node_modules/@types/node/index.d.ts +88 -0
  220. package/node_modules/@types/node/inspector.d.ts +2739 -0
  221. package/node_modules/@types/node/module.d.ts +298 -0
  222. package/node_modules/@types/node/net.d.ts +913 -0
  223. package/node_modules/@types/node/os.d.ts +473 -0
  224. package/node_modules/@types/node/package.json +235 -0
  225. package/node_modules/@types/node/path.d.ts +191 -0
  226. package/node_modules/@types/node/perf_hooks.d.ts +626 -0
  227. package/node_modules/@types/node/process.d.ts +1531 -0
  228. package/node_modules/@types/node/punycode.d.ts +117 -0
  229. package/node_modules/@types/node/querystring.d.ts +141 -0
  230. package/node_modules/@types/node/readline/promises.d.ts +143 -0
  231. package/node_modules/@types/node/readline.d.ts +666 -0
  232. package/node_modules/@types/node/repl.d.ts +430 -0
  233. package/node_modules/@types/node/stream/consumers.d.ts +12 -0
  234. package/node_modules/@types/node/stream/promises.d.ts +83 -0
  235. package/node_modules/@types/node/stream/web.d.ts +336 -0
  236. package/node_modules/@types/node/stream.d.ts +1731 -0
  237. package/node_modules/@types/node/string_decoder.d.ts +67 -0
  238. package/node_modules/@types/node/test.d.ts +1113 -0
  239. package/node_modules/@types/node/timers/promises.d.ts +93 -0
  240. package/node_modules/@types/node/timers.d.ts +126 -0
  241. package/node_modules/@types/node/tls.d.ts +1203 -0
  242. package/node_modules/@types/node/trace_events.d.ts +171 -0
  243. package/node_modules/@types/node/ts4.8/assert/strict.d.ts +8 -0
  244. package/node_modules/@types/node/ts4.8/assert.d.ts +985 -0
  245. package/node_modules/@types/node/ts4.8/async_hooks.d.ts +522 -0
  246. package/node_modules/@types/node/ts4.8/buffer.d.ts +2321 -0
  247. package/node_modules/@types/node/ts4.8/child_process.d.ts +1544 -0
  248. package/node_modules/@types/node/ts4.8/cluster.d.ts +432 -0
  249. package/node_modules/@types/node/ts4.8/console.d.ts +412 -0
  250. package/node_modules/@types/node/ts4.8/constants.d.ts +19 -0
  251. package/node_modules/@types/node/ts4.8/crypto.d.ts +4450 -0
  252. package/node_modules/@types/node/ts4.8/dgram.d.ts +586 -0
  253. package/node_modules/@types/node/ts4.8/diagnostics_channel.d.ts +192 -0
  254. package/node_modules/@types/node/ts4.8/dns/promises.d.ts +381 -0
  255. package/node_modules/@types/node/ts4.8/dns.d.ts +809 -0
  256. package/node_modules/@types/node/ts4.8/dom-events.d.ts +122 -0
  257. package/node_modules/@types/node/ts4.8/domain.d.ts +170 -0
  258. package/node_modules/@types/node/ts4.8/events.d.ts +754 -0
  259. package/node_modules/@types/node/ts4.8/fs/promises.d.ts +1205 -0
  260. package/node_modules/@types/node/ts4.8/fs.d.ts +4211 -0
  261. package/node_modules/@types/node/ts4.8/globals.d.ts +377 -0
  262. package/node_modules/@types/node/ts4.8/globals.global.d.ts +1 -0
  263. package/node_modules/@types/node/ts4.8/http.d.ts +1801 -0
  264. package/node_modules/@types/node/ts4.8/http2.d.ts +2386 -0
  265. package/node_modules/@types/node/ts4.8/https.d.ts +544 -0
  266. package/node_modules/@types/node/ts4.8/index.d.ts +88 -0
  267. package/node_modules/@types/node/ts4.8/inspector.d.ts +2739 -0
  268. package/node_modules/@types/node/ts4.8/module.d.ts +298 -0
  269. package/node_modules/@types/node/ts4.8/net.d.ts +913 -0
  270. package/node_modules/@types/node/ts4.8/os.d.ts +473 -0
  271. package/node_modules/@types/node/ts4.8/path.d.ts +191 -0
  272. package/node_modules/@types/node/ts4.8/perf_hooks.d.ts +626 -0
  273. package/node_modules/@types/node/ts4.8/process.d.ts +1531 -0
  274. package/node_modules/@types/node/ts4.8/punycode.d.ts +117 -0
  275. package/node_modules/@types/node/ts4.8/querystring.d.ts +141 -0
  276. package/node_modules/@types/node/ts4.8/readline/promises.d.ts +143 -0
  277. package/node_modules/@types/node/ts4.8/readline.d.ts +666 -0
  278. package/node_modules/@types/node/ts4.8/repl.d.ts +430 -0
  279. package/node_modules/@types/node/ts4.8/stream/consumers.d.ts +12 -0
  280. package/node_modules/@types/node/ts4.8/stream/promises.d.ts +83 -0
  281. package/node_modules/@types/node/ts4.8/stream/web.d.ts +336 -0
  282. package/node_modules/@types/node/ts4.8/stream.d.ts +1731 -0
  283. package/node_modules/@types/node/ts4.8/string_decoder.d.ts +67 -0
  284. package/node_modules/@types/node/ts4.8/test.d.ts +1113 -0
  285. package/node_modules/@types/node/ts4.8/timers/promises.d.ts +93 -0
  286. package/node_modules/@types/node/ts4.8/timers.d.ts +126 -0
  287. package/node_modules/@types/node/ts4.8/tls.d.ts +1203 -0
  288. package/node_modules/@types/node/ts4.8/trace_events.d.ts +171 -0
  289. package/node_modules/@types/node/ts4.8/tty.d.ts +206 -0
  290. package/node_modules/@types/node/ts4.8/url.d.ts +937 -0
  291. package/node_modules/@types/node/ts4.8/util.d.ts +2075 -0
  292. package/node_modules/@types/node/ts4.8/v8.d.ts +541 -0
  293. package/node_modules/@types/node/ts4.8/vm.d.ts +667 -0
  294. package/node_modules/@types/node/ts4.8/wasi.d.ts +158 -0
  295. package/node_modules/@types/node/ts4.8/worker_threads.d.ts +692 -0
  296. package/node_modules/@types/node/ts4.8/zlib.d.ts +517 -0
  297. package/node_modules/@types/node/tty.d.ts +206 -0
  298. package/node_modules/@types/node/url.d.ts +937 -0
  299. package/node_modules/@types/node/util.d.ts +2075 -0
  300. package/node_modules/@types/node/v8.d.ts +541 -0
  301. package/node_modules/@types/node/vm.d.ts +667 -0
  302. package/node_modules/@types/node/wasi.d.ts +158 -0
  303. package/node_modules/@types/node/worker_threads.d.ts +692 -0
  304. package/node_modules/@types/node/zlib.d.ts +517 -0
  305. package/node_modules/@types/react/LICENSE +21 -0
  306. package/node_modules/@types/react/README.md +16 -0
  307. package/node_modules/@types/react/experimental.d.ts +192 -0
  308. package/node_modules/@types/react/global.d.ts +151 -0
  309. package/node_modules/@types/react/index.d.ts +3175 -0
  310. package/node_modules/@types/react/jsx-dev-runtime.d.ts +2 -0
  311. package/node_modules/@types/react/jsx-runtime.d.ts +2 -0
  312. package/node_modules/@types/react/package.json +149 -0
  313. package/node_modules/@vitejs/plugin-react-refresh/LICENSE +21 -0
  314. package/node_modules/@vitejs/plugin-react-refresh/README.md +73 -0
  315. package/node_modules/@vitejs/plugin-react-refresh/index.d.ts +14 -0
  316. package/node_modules/@vitejs/plugin-react-refresh/index.js +239 -0
  317. package/node_modules/@vitejs/plugin-react-refresh/package.json +35 -0
  318. package/package.json +65 -0
  319. package/project.json +74 -0
  320. package/scripts/create-entry-files.ts +44 -0
  321. package/src/ExtensionServerClient/ExtensionServerClient.test.ts +730 -0
  322. package/src/ExtensionServerClient/ExtensionServerClient.ts +310 -0
  323. package/src/ExtensionServerClient/index.ts +2 -0
  324. package/src/ExtensionServerClient/types.ts +159 -0
  325. package/src/context/ExtensionServerProvider.test.tsx +173 -0
  326. package/src/context/ExtensionServerProvider.tsx +46 -0
  327. package/src/context/constants.ts +15 -0
  328. package/src/context/index.ts +3 -0
  329. package/src/context/types.ts +13 -0
  330. package/src/hooks/index.ts +5 -0
  331. package/src/hooks/useExtensionClient.ts +6 -0
  332. package/src/hooks/useExtensionServerContext.ts +4 -0
  333. package/src/hooks/useExtensionServerEvent.ts +11 -0
  334. package/src/hooks/useExtensionServerState.ts +6 -0
  335. package/src/hooks/useIsomorphicLayoutEffect.ts +6 -0
  336. package/src/i18n.test.ts +417 -0
  337. package/src/i18n.ts +208 -0
  338. package/src/index.ts +7 -0
  339. package/src/state/actions/actions.ts +36 -0
  340. package/src/state/actions/index.ts +2 -0
  341. package/src/state/actions/types.ts +26 -0
  342. package/src/state/index.ts +2 -0
  343. package/src/state/reducers/constants.ts +6 -0
  344. package/src/state/reducers/extensionServerReducer.test.ts +160 -0
  345. package/src/state/reducers/extensionServerReducer.ts +87 -0
  346. package/src/state/reducers/index.ts +3 -0
  347. package/src/state/reducers/types.ts +7 -0
  348. package/src/testing/MockExtensionServerProvider.tsx +36 -0
  349. package/src/testing/app.ts +15 -0
  350. package/src/testing/extensions.ts +70 -0
  351. package/src/testing/index.ts +3 -0
  352. package/src/types.ts +172 -0
  353. package/src/utilities/assetToString.test.ts +16 -0
  354. package/src/utilities/assetToString.ts +8 -0
  355. package/src/utilities/groupByKey.ts +3 -0
  356. package/src/utilities/index.ts +7 -0
  357. package/src/utilities/isUIExtension.ts +7 -0
  358. package/src/utilities/isValidSurface.ts +7 -0
  359. package/src/utilities/noop.ts +1 -0
  360. package/src/utilities/replaceUpdated.test.ts +26 -0
  361. package/src/utilities/replaceUpdated.ts +16 -0
  362. package/src/utilities/set.test.ts +19 -0
  363. package/src/utilities/set.ts +29 -0
  364. package/testing.d.ts +1 -0
  365. package/testing.js +1 -0
  366. package/testing.mjs +1 -0
  367. package/tests/setup.ts +6 -0
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from './context'
2
+ export * from './ExtensionServerClient'
3
+ export * from './hooks'
4
+ export * from './state'
5
+ export * from './types'
6
+ export * from './utilities'
7
+ export * from './i18n'
@@ -0,0 +1,36 @@
1
+ import type {ConnectedAction, UpdateAction, RefreshAction, FocusAction, UnfocusAction} from './types'
2
+
3
+ export function createConnectedAction(payload: ConnectedAction['payload']): ConnectedAction {
4
+ return {
5
+ type: 'connected',
6
+ payload,
7
+ }
8
+ }
9
+
10
+ export function createUpdateAction(payload: UpdateAction['payload']): UpdateAction {
11
+ return {
12
+ type: 'update',
13
+ payload,
14
+ }
15
+ }
16
+
17
+ export function createRefreshAction(payload: RefreshAction['payload']): RefreshAction {
18
+ return {
19
+ type: 'refresh',
20
+ payload,
21
+ }
22
+ }
23
+
24
+ export function createFocusAction(payload: FocusAction['payload']): FocusAction {
25
+ return {
26
+ type: 'focus',
27
+ payload,
28
+ }
29
+ }
30
+
31
+ export function createUnfocusAction(payload: UnfocusAction['payload']): UnfocusAction {
32
+ return {
33
+ type: 'unfocus',
34
+ payload,
35
+ }
36
+ }
@@ -0,0 +1,2 @@
1
+ export * from './actions'
2
+ export * from './types'
@@ -0,0 +1,26 @@
1
+ export interface ConnectedAction {
2
+ type: 'connected'
3
+ payload: ExtensionServer.InboundEvents['connected']
4
+ }
5
+
6
+ export interface UpdateAction {
7
+ type: 'update'
8
+ payload: ExtensionServer.InboundEvents['update']
9
+ }
10
+
11
+ export interface RefreshAction {
12
+ type: 'refresh'
13
+ payload: ExtensionServer.InboundEvents['refresh']
14
+ }
15
+
16
+ export interface FocusAction {
17
+ type: 'focus'
18
+ payload: ExtensionServer.InboundEvents['focus']
19
+ }
20
+
21
+ export interface UnfocusAction {
22
+ type: 'unfocus'
23
+ payload: ExtensionServer.InboundEvents['unfocus']
24
+ }
25
+
26
+ export type ExtensionServerActions = ConnectedAction | UpdateAction | RefreshAction | FocusAction | UnfocusAction
@@ -0,0 +1,2 @@
1
+ export * from './actions'
2
+ export * from './reducers'
@@ -0,0 +1,6 @@
1
+ import type {ExtensionServerState} from './types'
2
+
3
+ export const INITIAL_STATE: ExtensionServerState = {
4
+ extensions: [],
5
+ store: '',
6
+ }
@@ -0,0 +1,160 @@
1
+ import {extensionServerReducer} from './extensionServerReducer'
2
+ import {INITIAL_STATE} from './constants'
3
+ import {mockExtension, mockApp} from '../../testing'
4
+ import {
5
+ createConnectedAction,
6
+ createUpdateAction,
7
+ createRefreshAction,
8
+ createFocusAction,
9
+ createUnfocusAction,
10
+ } from '../actions'
11
+
12
+ import type {ExtensionServerState} from './types'
13
+
14
+ describe('extensionServerReducer()', () => {
15
+ test('connects to server', () => {
16
+ const app = mockApp()
17
+ const extension = mockExtension()
18
+ const action = createConnectedAction({app, extensions: [extension], store: 'test-store.com'})
19
+ const state = extensionServerReducer(INITIAL_STATE, action)
20
+
21
+ expect(state).toStrictEqual({
22
+ app,
23
+ extensions: [extension],
24
+ store: 'test-store.com',
25
+ })
26
+ })
27
+
28
+ test('replaces existing app and extensions when connecting twice', () => {
29
+ const app = mockApp()
30
+ const extension = mockExtension()
31
+ const action1 = createConnectedAction({app, extensions: [extension], store: 'test-store.com'})
32
+ const initialState = extensionServerReducer(INITIAL_STATE, action1)
33
+
34
+ expect(initialState).toStrictEqual({
35
+ app,
36
+ extensions: [extension],
37
+ store: 'test-store.com',
38
+ })
39
+
40
+ const currentExtension = initialState.extensions[0]
41
+ const newExtension = {...currentExtension, uuid: 'new-uuid'}
42
+ const newApp = {...app, id: 'new-id'}
43
+ const action2 = createConnectedAction({app: newApp, extensions: [newExtension], store: 'test-store.com'})
44
+ const secondState = extensionServerReducer(initialState, action2)
45
+
46
+ expect(secondState).toStrictEqual({
47
+ app: newApp,
48
+ extensions: [newExtension],
49
+ store: 'test-store.com',
50
+ })
51
+ })
52
+
53
+ test('receives updates from the server', () => {
54
+ const extension1 = mockExtension()
55
+ const extension2 = mockExtension()
56
+ const previousState: ExtensionServerState = {
57
+ store: 'test-store.com',
58
+ extensions: [extension1, extension2],
59
+ }
60
+
61
+ const app = mockApp()
62
+ const updated1 = {...extension1, version: 'v2'}
63
+ const action = createUpdateAction({app, extensions: [updated1]})
64
+
65
+ const state = extensionServerReducer(previousState, action)
66
+
67
+ expect(state).toStrictEqual({
68
+ app,
69
+ extensions: [updated1, extension2],
70
+ store: 'test-store.com',
71
+ })
72
+ })
73
+
74
+ test('maintains extension order after update', () => {
75
+ const extension1 = mockExtension()
76
+ const extension2 = mockExtension()
77
+ const previousState: ExtensionServerState = {
78
+ store: 'test-store.com',
79
+ extensions: [extension1, extension2],
80
+ }
81
+
82
+ const app = mockApp()
83
+ const updated2 = {...extension2, version: 'v2'}
84
+ const action = createUpdateAction({app, extensions: [updated2]})
85
+
86
+ const state = extensionServerReducer(previousState, action)
87
+
88
+ expect(state).toStrictEqual({
89
+ app,
90
+ extensions: [extension1, updated2],
91
+ store: 'test-store.com',
92
+ })
93
+ })
94
+
95
+ // eslint-disable-next-line vitest/no-disabled-tests
96
+ test.skip('refreshes extension url', async () => {
97
+ const extension = mockExtension()
98
+ const previousState: ExtensionServerState = {
99
+ store: 'test-store.com',
100
+ extensions: [extension],
101
+ }
102
+
103
+ const action = createRefreshAction([{uuid: extension.uuid}])
104
+
105
+ const state1 = extensionServerReducer(previousState, action)
106
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins
107
+ const url1 = new URL(state1.extensions[0].assets.main.url)
108
+ const timestamp1 = url1.searchParams.get('lastUpdated') || ''
109
+
110
+ expect(timestamp1.length).toBeGreaterThan(0)
111
+
112
+ // sleep 1ms to guarantee new timestamp
113
+ await new Promise((resolve) => setTimeout(resolve, 1))
114
+
115
+ const state2 = extensionServerReducer(state1, action)
116
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins
117
+ const url2 = new URL(state2.extensions[0].assets.main.url)
118
+ const timestamp2 = url2.searchParams.get('lastUpdated') || ''
119
+
120
+ expect(timestamp2.length).toBeGreaterThan(0)
121
+ expect(timestamp1).not.toStrictEqual(timestamp2)
122
+ })
123
+
124
+ describe('focus', () => {
125
+ test('focuses only one extension', () => {
126
+ const extension1 = mockExtension()
127
+ const extension2 = mockExtension()
128
+
129
+ const previousState: ExtensionServerState = {
130
+ store: 'test-store.com',
131
+ extensions: [extension1, extension2],
132
+ }
133
+
134
+ const action1 = createFocusAction([{uuid: extension1.uuid}])
135
+ const state1 = extensionServerReducer(previousState, action1)
136
+
137
+ expect(state1.extensions[0].development.focused).toBe(true)
138
+
139
+ const action2 = createFocusAction([{uuid: extension2.uuid}])
140
+ const state2 = extensionServerReducer(state1, action2)
141
+
142
+ expect(state2.extensions[0].development.focused).toBe(false)
143
+ expect(state2.extensions[1].development.focused).toBe(true)
144
+ })
145
+
146
+ test('unfocuses extension', () => {
147
+ const extension = mockExtension({development: {focused: true}})
148
+
149
+ const previousState: ExtensionServerState = {
150
+ store: 'test-store.com',
151
+ extensions: [extension],
152
+ }
153
+
154
+ const action = createUnfocusAction()
155
+ const state = extensionServerReducer(previousState, action)
156
+
157
+ expect(state.extensions[0].development.focused).toBe(false)
158
+ })
159
+ })
160
+ })
@@ -0,0 +1,87 @@
1
+ import {set, replaceUpdated, assetToString} from '../../utilities'
2
+ import type {ExtensionServerActions} from '../actions'
3
+ import type {ExtensionPayload} from '../../types'
4
+
5
+ import type {ExtensionServerState} from './types'
6
+
7
+ export function extensionServerReducer(state: ExtensionServerState, action: ExtensionServerActions) {
8
+ switch (action.type) {
9
+ case 'connected': {
10
+ const extensions = (action.payload.extensions ?? []).map((extension) => {
11
+ Object.keys(extension.assets).forEach(
12
+ (asset) => (extension.assets[asset].url = assetToString(extension.assets[asset])),
13
+ )
14
+ return extension
15
+ })
16
+ return {
17
+ ...state,
18
+ store: action.payload.store,
19
+ app: action.payload.app,
20
+ extensions,
21
+ } as ExtensionServerState
22
+ }
23
+
24
+ case 'update': {
25
+ const extensions = (action.payload.extensions ?? []).map((extension) => {
26
+ Object.keys(extension.assets).forEach(
27
+ (asset) => (extension.assets[asset].url = assetToString(extension.assets[asset])),
28
+ )
29
+ return extension
30
+ })
31
+ return {
32
+ ...state,
33
+ app: {...(state.app ?? {}), ...(action.payload.app ?? {})},
34
+ extensions: replaceUpdated(state.extensions, extensions, ({uuid}) => uuid),
35
+ } as ExtensionServerState
36
+ }
37
+
38
+ case 'refresh': {
39
+ return {
40
+ ...state,
41
+ extensions: state.extensions.map((extension) => {
42
+ if (action.payload.some(({uuid}) => extension.uuid === uuid)) {
43
+ const assets: ExtensionPayload['assets'] = {}
44
+ Object.keys(extension.assets).forEach((asset) => {
45
+ const resourceURL = {...extension.assets[asset]}
46
+ resourceURL.lastUpdated = Date.now()
47
+ resourceURL.url = assetToString(resourceURL)
48
+
49
+ assets[asset] = resourceURL
50
+ })
51
+ return set(extension, (ext) => ext.assets, assets)
52
+ }
53
+ return extension
54
+ }),
55
+ }
56
+ }
57
+
58
+ case 'focus': {
59
+ return {
60
+ ...state,
61
+ extensions: state.extensions.map((extension) => {
62
+ if (action.payload.some(({uuid}) => extension.uuid === uuid)) {
63
+ return set(extension, (ext) => ext.development.focused, true)
64
+ } else if (extension.development.focused) {
65
+ return set(extension, (ext) => ext.development.focused, false)
66
+ }
67
+ return extension
68
+ }),
69
+ }
70
+ }
71
+
72
+ case 'unfocus': {
73
+ return {
74
+ ...state,
75
+ extensions: state.extensions.map((extension) => {
76
+ if (extension.development.focused) {
77
+ return set(extension, (ext) => ext.development.focused, false)
78
+ }
79
+ return extension
80
+ }),
81
+ }
82
+ }
83
+
84
+ default:
85
+ return state
86
+ }
87
+ }
@@ -0,0 +1,3 @@
1
+ export * from './constants'
2
+ export * from './extensionServerReducer'
3
+ export * from './types'
@@ -0,0 +1,7 @@
1
+ import type {App, ExtensionPayload} from '../../types'
2
+
3
+ export interface ExtensionServerState {
4
+ app?: App
5
+ extensions: ExtensionPayload[]
6
+ store: string
7
+ }
@@ -0,0 +1,36 @@
1
+ import {ExtensionServerProvider, extensionServerContext} from '../context'
2
+ import {useExtensionServerContext} from '../hooks'
3
+ import React, {useMemo} from 'react'
4
+ import type {ExtensionServerProviderProps, ExtensionServerContext} from '../context'
5
+
6
+ interface InternalProviderProps extends Partial<ExtensionServerContext> {
7
+ children?: ExtensionServerProviderProps['children']
8
+ }
9
+
10
+ function InternalProvider({children, ...mocks}: InternalProviderProps) {
11
+ const actual = useExtensionServerContext()
12
+
13
+ const context = useMemo(
14
+ () => ({
15
+ ...actual,
16
+ ...mocks,
17
+ }),
18
+ [actual, mocks],
19
+ )
20
+
21
+ return <extensionServerContext.Provider value={context}>{children}</extensionServerContext.Provider>
22
+ }
23
+
24
+ type MockExtensionServerProviderProps = Partial<ExtensionServerProviderProps> & InternalProviderProps
25
+
26
+ export function MockExtensionServerProvider({
27
+ children,
28
+ options = {connection: {}},
29
+ ...props
30
+ }: MockExtensionServerProviderProps) {
31
+ return (
32
+ <ExtensionServerProvider options={options}>
33
+ <InternalProvider {...props}>{children}</InternalProvider>
34
+ </ExtensionServerProvider>
35
+ )
36
+ }
@@ -0,0 +1,15 @@
1
+ import {App} from '../types'
2
+
3
+ export function mockApp(): App {
4
+ return {
5
+ id: 'id-1',
6
+ apiKey: '12345',
7
+ applicationUrl: 'www.applicationUrl.com',
8
+ title: 'App title',
9
+ url: 'mock url',
10
+ mobileUrl: 'mock mobile url',
11
+ icon: {
12
+ transformedSrc: 'www.transformed-src.com',
13
+ },
14
+ }
15
+ }
@@ -0,0 +1,70 @@
1
+ import {ExtensionPayload, Status} from '../types'
2
+
3
+ type DeepPartial<T> = {
4
+ [P in keyof T]?: DeepPartial<T[P]>
5
+ }
6
+
7
+ let id = 0
8
+
9
+ function pad(num: number) {
10
+ return `00000000000${num}`.slice(-12)
11
+ }
12
+
13
+ export function mockExtension(obj: DeepPartial<ExtensionPayload> = {}): ExtensionPayload {
14
+ const uuid = `00000000-0000-0000-0000-${pad(id++)}`
15
+ const lastUpdated = Date.now()
16
+ return {
17
+ handle: 'my-extension',
18
+ name: 'My extension',
19
+ description: 'My extension description',
20
+ surface: 'admin',
21
+ type: 'purchase_option',
22
+ externalType: 'external_type',
23
+ uuid,
24
+ version: 'extension version',
25
+ ...obj,
26
+ assets: {
27
+ main: {
28
+ name: 'main',
29
+ url: `https://secure-link.com/extensions/${uuid}/assets/handle.js?lastUpdated=${lastUpdated}`,
30
+ lastUpdated,
31
+ },
32
+ ...((obj.assets || {}) as any),
33
+ },
34
+ development: {
35
+ hidden: false,
36
+ status: Status.Success,
37
+ resource: {
38
+ url: 'resourceUrl',
39
+ },
40
+ root: {
41
+ url: `https://secure-link.com/extensions/${uuid}`,
42
+ },
43
+ renderer: {
44
+ name: 'render name',
45
+ version: '1.0.0',
46
+ },
47
+ ...((obj.development || {}) as any),
48
+ },
49
+ // this is due to the naive DeepPartial but also more complex ones
50
+ // [see stackoverflow](https://stackoverflow.com/a/68699273) assume that
51
+ // `DeepPartial<Array<T>> === Array<T | undefined>` while we are looking for
52
+ // `DeepPartial<Array<T>> === Array<T> | undefined`.
53
+ // This is the case for extension points and seems hard to fix
54
+ // in a generalized, non-surprising way
55
+ extensionPoints: obj.extensionPoints as any,
56
+ capabilities: obj.capabilities as any,
57
+ localization: obj.localization as any,
58
+ authenticatedRedirectStartUrl: obj.authenticatedRedirectStartUrl as any,
59
+ authenticatedRedirectRedirectUrls: obj.authenticatedRedirectRedirectUrls as any,
60
+ settings: {
61
+ fields: [
62
+ {
63
+ key: 'sample-key',
64
+ name: 'sample_name',
65
+ type: 'sample_type',
66
+ },
67
+ ],
68
+ },
69
+ }
70
+ }
@@ -0,0 +1,3 @@
1
+ export * from './MockExtensionServerProvider'
2
+ export * from './app'
3
+ export * from './extensions'
package/src/types.ts ADDED
@@ -0,0 +1,172 @@
1
+ /* eslint-disable @shopify/strict-component-boundaries */
2
+ import {FlattenedLocalization, Localization} from './i18n'
3
+ import './ExtensionServerClient/types'
4
+ import type {Surface} from './ExtensionServerClient/types'
5
+
6
+ declare global {
7
+ namespace ExtensionServer {
8
+ type ServerEvents =
9
+ | {
10
+ event: 'dispatch'
11
+ data: InboundEvents['dispatch']
12
+ }
13
+ | {
14
+ event: 'connected'
15
+ data: InboundEvents['connected']
16
+ }
17
+ | {
18
+ event: 'update'
19
+ data: InboundEvents['update']
20
+ }
21
+
22
+ interface InboundEvents extends DispatchEvents {
23
+ dispatch: {type: keyof DispatchEvents; payload: DispatchEvents[keyof DispatchEvents]}
24
+ connected: {extensions: ExtensionPayload[]; app?: App; store: string}
25
+ update: {extensions?: ExtensionPayload[]; app?: App}
26
+ }
27
+
28
+ interface OutboundPersistEvents {
29
+ update: {
30
+ extensions?: ({uuid: string} & DeepPartial<ExtensionPayload>)[]
31
+ app?: DeepPartial<App>
32
+ }
33
+ }
34
+
35
+ interface DispatchEvents {
36
+ refresh: {uuid: string}[]
37
+ focus: {uuid: string}[]
38
+ unfocus: void
39
+ navigate: {url: string}
40
+ }
41
+
42
+ // API responses
43
+ namespace API {
44
+ interface BaseResponse {
45
+ app: App
46
+ root: ResourceURL
47
+ socket: ResourceURL
48
+ devConsole: ResourceURL
49
+ store: string
50
+ version: string
51
+ }
52
+
53
+ interface ExtensionsResponse extends BaseResponse {
54
+ extensions: ExtensionPayload[]
55
+ }
56
+
57
+ interface ExtensionResponse extends BaseResponse {
58
+ extension: ExtensionPayload
59
+ }
60
+ }
61
+
62
+ interface UIExtension extends ExtensionPayload {
63
+ extensionPoints: ExtensionPoint[]
64
+ apiVersion: string
65
+ }
66
+ }
67
+ }
68
+
69
+ export type DeepPartial<T> = {
70
+ [P in keyof T]?: DeepPartial<T[P]>
71
+ }
72
+
73
+ export interface ResourceURL {
74
+ url: string
75
+ }
76
+
77
+ export interface Asset extends ResourceURL {
78
+ name: string
79
+ lastUpdated: number
80
+ }
81
+
82
+ export interface Metafield {
83
+ namespace: string
84
+ key: string
85
+ }
86
+
87
+ export interface ExtensionPoint {
88
+ target: string
89
+ surface: Surface
90
+ metafields?: Metafield[]
91
+ resource: ResourceURL
92
+ root: ResourceURL
93
+ localization?: FlattenedLocalization | Localization | null
94
+ name: string
95
+ description?: string
96
+ }
97
+
98
+ export type ExtensionPoints = string[] | ExtensionPoint[] | null
99
+
100
+ interface CollectBuyerConsentCapabilities {
101
+ smsMarketing: boolean
102
+ customerPrivacy: boolean
103
+ }
104
+
105
+ interface Capabilities {
106
+ apiAccess: boolean
107
+ blockProgress: boolean
108
+ networkAccess: boolean
109
+ collectBuyerConsent: CollectBuyerConsentCapabilities
110
+ }
111
+
112
+ export interface ExtensionPayload {
113
+ type: string
114
+ externalType: string
115
+ assets: {[name: string]: Asset}
116
+ development: {
117
+ hidden: boolean
118
+ status: Status
119
+ focused?: boolean
120
+ resource: ResourceURL
121
+ root: ResourceURL
122
+ renderer: {
123
+ name: string
124
+ version: string
125
+ }
126
+ }
127
+ uuid: string
128
+ version: string
129
+ surface: Surface
130
+ name: string
131
+ description?: string
132
+ handle: string
133
+ extensionPoints: ExtensionPoints
134
+ capabilities?: Capabilities
135
+ authenticatedRedirectStartUrl?: string
136
+ authenticatedRedirectRedirectUrls?: string[]
137
+ localization?: FlattenedLocalization | Localization | null
138
+ settings?: {
139
+ fields?: {
140
+ type: string
141
+ key?: string
142
+ name?: string
143
+ description?: string
144
+ required?: boolean
145
+ validations?: any[]
146
+ }[]
147
+ }
148
+ }
149
+
150
+ export enum Status {
151
+ Error = 'error',
152
+ Success = 'success',
153
+ }
154
+
155
+ export interface App {
156
+ id: string
157
+ apiKey: string
158
+ url: string
159
+ mobileUrl: string
160
+ applicationUrl: string
161
+ handle?: string | null
162
+ title: string
163
+ developerName?: string
164
+ icon: {
165
+ transformedSrc: string
166
+ }
167
+ installation?: {
168
+ launchUrl: string
169
+ }
170
+ supportEmail?: string
171
+ supportLocales?: string[]
172
+ }
@@ -0,0 +1,16 @@
1
+ import {assetToString} from './assetToString'
2
+ import type {Asset} from '../types'
3
+
4
+ describe('assetToString tests', () => {
5
+ test('creates a URL string from an asset', () => {
6
+ const asset: Asset = {
7
+ name: 'main',
8
+ url: 'http://localhost:8000/extensions/00000000/assets/handle.js',
9
+ lastUpdated: 1637004124,
10
+ }
11
+
12
+ const url = assetToString(asset)
13
+
14
+ expect(url).toBe(`${asset.url}?lastUpdated=${asset.lastUpdated}`)
15
+ })
16
+ })
@@ -0,0 +1,8 @@
1
+ import type {Asset} from '../types'
2
+
3
+ export function assetToString(asset: Asset) {
4
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins
5
+ const url = new URL(asset.url)
6
+ url.searchParams.set('lastUpdated', String(asset.lastUpdated))
7
+ return url.toString()
8
+ }
@@ -0,0 +1,3 @@
1
+ export function groupByKey<T extends {[key: string]: unknown}>(key: keyof T, items: T[]): Map<T[keyof T], T> {
2
+ return new Map(items.map((item) => [item[key], item]))
3
+ }
@@ -0,0 +1,7 @@
1
+ export * from './groupByKey'
2
+ export * from './noop'
3
+ export * from './replaceUpdated'
4
+ export * from './set'
5
+ export * from './assetToString'
6
+ export * from './isValidSurface'
7
+ export * from './isUIExtension'