utneque 1.0.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 (431) hide show
  1. package/.editorconfig +10 -0
  2. package/.eslintrc.isomorphic.js +26 -0
  3. package/.eslintrc.js +86 -0
  4. package/.gitattributes +1 -0
  5. package/.github/workflows/ci.yml +33 -0
  6. package/.github/workflows/deploy-browser-cdn-candidate.yml +51 -0
  7. package/.github/workflows/deploy-releases.yml +178 -0
  8. package/.nvmrc +1 -0
  9. package/.prettierrc +7 -0
  10. package/.vscode/extensions.json +3 -0
  11. package/.vscode/launch.json +81 -0
  12. package/.vscode/settings.json +41 -0
  13. package/.yarn/plugins/@yarnpkg/plugin-constraints.cjs +52 -0
  14. package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +546 -0
  15. package/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
  16. package/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs +28 -0
  17. package/.yarn/releases/yarn-3.4.1.cjs +873 -0
  18. package/.yarnrc.yml +15 -0
  19. package/jest.config.js +18 -0
  20. package/package.json +59 -0
  21. package/packages/browser/.eslintrc.js +9 -0
  22. package/packages/browser/.lintstagedrc.js +1 -0
  23. package/packages/browser/ARCHITECTURE.md +48 -0
  24. package/packages/browser/LICENSE.MD +45 -0
  25. package/packages/browser/Makefile +64 -0
  26. package/packages/browser/README.md +227 -0
  27. package/packages/browser/e2e-tests/local-server.ts +28 -0
  28. package/packages/browser/e2e-tests/performance/ajs-perf-browser.test.ts +75 -0
  29. package/packages/browser/jest.config.js +15 -0
  30. package/packages/browser/jest.setup.js +10 -0
  31. package/packages/browser/package.json +106 -0
  32. package/packages/browser/qa/README.md +41 -0
  33. package/packages/browser/qa/__fixtures__/snippets.ts +148 -0
  34. package/packages/browser/qa/__tests__/backwards-compatibility.test.ts +180 -0
  35. package/packages/browser/qa/__tests__/destinations.test.ts +101 -0
  36. package/packages/browser/qa/__tests__/smoke.test.ts +170 -0
  37. package/packages/browser/qa/lib/benchmark.ts +36 -0
  38. package/packages/browser/qa/lib/browser.ts +28 -0
  39. package/packages/browser/qa/lib/jest-reporter.js +57 -0
  40. package/packages/browser/qa/lib/runner.ts +142 -0
  41. package/packages/browser/qa/lib/schema.ts +59 -0
  42. package/packages/browser/qa/lib/server.ts +54 -0
  43. package/packages/browser/qa/lib/stats.ts +52 -0
  44. package/packages/browser/scripts/build-prep.sh +7 -0
  45. package/packages/browser/scripts/ci.sh +15 -0
  46. package/packages/browser/scripts/release.js +121 -0
  47. package/packages/browser/scripts/release.sh +9 -0
  48. package/packages/browser/scripts/run.sh +8 -0
  49. package/packages/browser/src/browser/__tests__/analytics-lazy-init.integration.test.ts +51 -0
  50. package/packages/browser/src/browser/__tests__/analytics-pre-init.integration.test.ts +440 -0
  51. package/packages/browser/src/browser/__tests__/anon-id-and-reset.integration.test.ts +73 -0
  52. package/packages/browser/src/browser/__tests__/cdn.test.ts +53 -0
  53. package/packages/browser/src/browser/__tests__/csp-detection.test.ts +140 -0
  54. package/packages/browser/src/browser/__tests__/inspector.integration.test.ts +121 -0
  55. package/packages/browser/src/browser/__tests__/integration.test.ts +1213 -0
  56. package/packages/browser/src/browser/__tests__/integrations.integration.test.ts +260 -0
  57. package/packages/browser/src/browser/__tests__/page-enrichment.integration.test.ts +216 -0
  58. package/packages/browser/src/browser/__tests__/query-string.integration.test.ts +116 -0
  59. package/packages/browser/src/browser/__tests__/standalone-analytics.test.ts +303 -0
  60. package/packages/browser/src/browser/__tests__/standalone-errors.test.ts +136 -0
  61. package/packages/browser/src/browser/__tests__/standalone.test.ts +97 -0
  62. package/packages/browser/src/browser/__tests__/typedef-tests/analytics-browser.ts +150 -0
  63. package/packages/browser/src/browser/__tests__/update-cdn-settings.test.ts +71 -0
  64. package/packages/browser/src/browser/browser-umd.ts +19 -0
  65. package/packages/browser/src/browser/index.ts +486 -0
  66. package/packages/browser/src/browser/standalone-analytics.ts +62 -0
  67. package/packages/browser/src/browser/standalone-interface.ts +11 -0
  68. package/packages/browser/src/browser/standalone.ts +92 -0
  69. package/packages/browser/src/core/__tests__/track-form.test.ts +193 -0
  70. package/packages/browser/src/core/__tests__/track-link.test.ts +252 -0
  71. package/packages/browser/src/core/analytics/__tests__/integration.test.ts +334 -0
  72. package/packages/browser/src/core/analytics/__tests__/test-plugins.ts +94 -0
  73. package/packages/browser/src/core/analytics/index.ts +672 -0
  74. package/packages/browser/src/core/analytics/interfaces.ts +100 -0
  75. package/packages/browser/src/core/arguments-resolver/__tests__/index.test.ts +524 -0
  76. package/packages/browser/src/core/arguments-resolver/index.ts +200 -0
  77. package/packages/browser/src/core/auto-track.ts +152 -0
  78. package/packages/browser/src/core/buffer/__tests__/index.test.ts +455 -0
  79. package/packages/browser/src/core/buffer/index.ts +371 -0
  80. package/packages/browser/src/core/callback/index.ts +1 -0
  81. package/packages/browser/src/core/connection/__tests__/index.test.ts +25 -0
  82. package/packages/browser/src/core/connection/index.ts +13 -0
  83. package/packages/browser/src/core/constants/index.ts +1 -0
  84. package/packages/browser/src/core/context/__tests__/index.test.ts +201 -0
  85. package/packages/browser/src/core/context/index.ts +21 -0
  86. package/packages/browser/src/core/environment/index.ts +7 -0
  87. package/packages/browser/src/core/events/__tests__/index.test.ts +450 -0
  88. package/packages/browser/src/core/events/index.ts +280 -0
  89. package/packages/browser/src/core/events/interfaces.ts +36 -0
  90. package/packages/browser/src/core/inspector/index.ts +14 -0
  91. package/packages/browser/src/core/page/__tests__/index.test.ts +130 -0
  92. package/packages/browser/src/core/page/add-page-context.ts +33 -0
  93. package/packages/browser/src/core/page/get-page-context.ts +140 -0
  94. package/packages/browser/src/core/page/index.ts +2 -0
  95. package/packages/browser/src/core/plugin/index.ts +12 -0
  96. package/packages/browser/src/core/query-string/__tests__/gracefulDecodeURIComponent.test.ts +17 -0
  97. package/packages/browser/src/core/query-string/__tests__/index.test.ts +149 -0
  98. package/packages/browser/src/core/query-string/__tests__/pickPrefix.test.ts +31 -0
  99. package/packages/browser/src/core/query-string/__tests__/useQueryString.test.ts +60 -0
  100. package/packages/browser/src/core/query-string/gracefulDecodeURIComponent.ts +16 -0
  101. package/packages/browser/src/core/query-string/index.ts +64 -0
  102. package/packages/browser/src/core/query-string/pickPrefix.ts +20 -0
  103. package/packages/browser/src/core/queue/__tests__/event-queue.test.ts +82 -0
  104. package/packages/browser/src/core/queue/event-queue.ts +22 -0
  105. package/packages/browser/src/core/session/__tests__/index.test.ts +41 -0
  106. package/packages/browser/src/core/session/index.ts +107 -0
  107. package/packages/browser/src/core/stats/__tests__/index.test.ts +15 -0
  108. package/packages/browser/src/core/stats/__tests__/remote-metrics.test.ts +189 -0
  109. package/packages/browser/src/core/stats/index.ts +15 -0
  110. package/packages/browser/src/core/stats/remote-metrics.ts +144 -0
  111. package/packages/browser/src/core/storage/__tests__/cookieStorage.test.ts +58 -0
  112. package/packages/browser/src/core/storage/__tests__/localStorage.test.ts +70 -0
  113. package/packages/browser/src/core/storage/__tests__/test-helpers.ts +26 -0
  114. package/packages/browser/src/core/storage/__tests__/universalStorage.test.ts +167 -0
  115. package/packages/browser/src/core/storage/cookieStorage.ts +80 -0
  116. package/packages/browser/src/core/storage/index.ts +64 -0
  117. package/packages/browser/src/core/storage/localStorage.ts +45 -0
  118. package/packages/browser/src/core/storage/memoryStorage.ts +22 -0
  119. package/packages/browser/src/core/storage/settings.ts +23 -0
  120. package/packages/browser/src/core/storage/types.ts +49 -0
  121. package/packages/browser/src/core/storage/universalStorage.ts +78 -0
  122. package/packages/browser/src/core/user/__tests__/index.test.ts +922 -0
  123. package/packages/browser/src/core/user/__tests__/migrate.test.ts +101 -0
  124. package/packages/browser/src/core/user/__tests__/session.test.ts +136 -0
  125. package/packages/browser/src/core/user/__tests__/tld.test.ts +36 -0
  126. package/packages/browser/src/core/user/index.ts +399 -0
  127. package/packages/browser/src/core/user/migrate.ts +126 -0
  128. package/packages/browser/src/core/user/tld.ts +65 -0
  129. package/packages/browser/src/core/user/vendor/crypto-es/LICENSE +53 -0
  130. package/packages/browser/src/core/user/vendor/crypto-es/lib/aes.ts +302 -0
  131. package/packages/browser/src/core/user/vendor/crypto-es/lib/cipher-core.ts +922 -0
  132. package/packages/browser/src/core/user/vendor/crypto-es/lib/core.ts +806 -0
  133. package/packages/browser/src/core/user/vendor/crypto-es/lib/enc-base64.ts +110 -0
  134. package/packages/browser/src/core/user/vendor/crypto-es/lib/evpkdf.ts +110 -0
  135. package/packages/browser/src/core/user/vendor/crypto-es/lib/md5.ts +238 -0
  136. package/packages/browser/src/core/user/vendor/readme.md +7 -0
  137. package/packages/browser/src/generated/__tests__/version.test.ts +18 -0
  138. package/packages/browser/src/generated/version.ts +2 -0
  139. package/packages/browser/src/index.ts +13 -0
  140. package/packages/browser/src/lib/__tests__/embedded-write-key.test.ts +15 -0
  141. package/packages/browser/src/lib/__tests__/fetch.test.ts +35 -0
  142. package/packages/browser/src/lib/__tests__/get-process-env.test.ts +5 -0
  143. package/packages/browser/src/lib/__tests__/group-by.test.ts +96 -0
  144. package/packages/browser/src/lib/__tests__/is-plan-event-enabled.test.ts +36 -0
  145. package/packages/browser/src/lib/__tests__/is-thenable.test.ts +39 -0
  146. package/packages/browser/src/lib/__tests__/merged-options.test.ts +123 -0
  147. package/packages/browser/src/lib/__tests__/on-page-change.test.ts +74 -0
  148. package/packages/browser/src/lib/__tests__/parse-cdn.test.ts +88 -0
  149. package/packages/browser/src/lib/__tests__/pick.test.ts +34 -0
  150. package/packages/browser/src/lib/__tests__/pick.typedef.ts +39 -0
  151. package/packages/browser/src/lib/bind-all.ts +19 -0
  152. package/packages/browser/src/lib/browser-polyfill.ts +23 -0
  153. package/packages/browser/src/lib/client-hints/__tests__/index.test.ts +66 -0
  154. package/packages/browser/src/lib/client-hints/index.ts +16 -0
  155. package/packages/browser/src/lib/client-hints/interfaces.ts +42 -0
  156. package/packages/browser/src/lib/create-deferred.ts +16 -0
  157. package/packages/browser/src/lib/csp-detection.ts +8 -0
  158. package/packages/browser/src/lib/embedded-write-key.ts +24 -0
  159. package/packages/browser/src/lib/fetch.ts +10 -0
  160. package/packages/browser/src/lib/get-global.ts +16 -0
  161. package/packages/browser/src/lib/get-process-env.ts +11 -0
  162. package/packages/browser/src/lib/global-analytics-helper.ts +31 -0
  163. package/packages/browser/src/lib/group-by.ts +30 -0
  164. package/packages/browser/src/lib/is-plan-event-enabled.ts +20 -0
  165. package/packages/browser/src/lib/is-thenable.ts +9 -0
  166. package/packages/browser/src/lib/load-script.ts +66 -0
  167. package/packages/browser/src/lib/merged-options.ts +46 -0
  168. package/packages/browser/src/lib/on-page-change.ts +29 -0
  169. package/packages/browser/src/lib/p-while.ts +12 -0
  170. package/packages/browser/src/lib/parse-cdn.ts +56 -0
  171. package/packages/browser/src/lib/pick.ts +28 -0
  172. package/packages/browser/src/lib/priority-queue/__tests__/backoff.test.ts +23 -0
  173. package/packages/browser/src/lib/priority-queue/__tests__/index.test.ts +158 -0
  174. package/packages/browser/src/lib/priority-queue/__tests__/persisted.test.ts +228 -0
  175. package/packages/browser/src/lib/priority-queue/backoff.ts +24 -0
  176. package/packages/browser/src/lib/priority-queue/index.ts +6 -0
  177. package/packages/browser/src/lib/priority-queue/persisted.ts +127 -0
  178. package/packages/browser/src/lib/sleep.ts +4 -0
  179. package/packages/browser/src/lib/to-facade.ts +53 -0
  180. package/packages/browser/src/lib/version-type.ts +10 -0
  181. package/packages/browser/src/node/__tests__/node-integration.test.ts +19 -0
  182. package/packages/browser/src/node/index.ts +36 -0
  183. package/packages/browser/src/node/node.browser.ts +7 -0
  184. package/packages/browser/src/plugins/ajs-destination/__tests__/index.test.ts +834 -0
  185. package/packages/browser/src/plugins/ajs-destination/index.ts +392 -0
  186. package/packages/browser/src/plugins/ajs-destination/loader.ts +129 -0
  187. package/packages/browser/src/plugins/ajs-destination/types.ts +44 -0
  188. package/packages/browser/src/plugins/ajs-destination/utils.ts +32 -0
  189. package/packages/browser/src/plugins/analytics-node/__tests__/index.test.ts +69 -0
  190. package/packages/browser/src/plugins/analytics-node/index.ts +67 -0
  191. package/packages/browser/src/plugins/env-enrichment/__tests__/index.test.ts +421 -0
  192. package/packages/browser/src/plugins/env-enrichment/index.ts +208 -0
  193. package/packages/browser/src/plugins/hightouchio/__tests__/batched-dispatcher.test.ts +299 -0
  194. package/packages/browser/src/plugins/hightouchio/__tests__/index.test.ts +317 -0
  195. package/packages/browser/src/plugins/hightouchio/__tests__/normalize.test.ts +181 -0
  196. package/packages/browser/src/plugins/hightouchio/__tests__/retries.test.ts +82 -0
  197. package/packages/browser/src/plugins/hightouchio/batched-dispatcher.ts +127 -0
  198. package/packages/browser/src/plugins/hightouchio/fetch-dispatcher.ts +27 -0
  199. package/packages/browser/src/plugins/hightouchio/index.ts +147 -0
  200. package/packages/browser/src/plugins/hightouchio/normalize.ts +71 -0
  201. package/packages/browser/src/plugins/hightouchio/schedule-flush.ts +58 -0
  202. package/packages/browser/src/plugins/legacy-video-plugins/__tests__/index.test.ts +48 -0
  203. package/packages/browser/src/plugins/legacy-video-plugins/index.ts +16 -0
  204. package/packages/browser/src/plugins/middleware/__tests__/index.test.ts +268 -0
  205. package/packages/browser/src/plugins/middleware/index.ts +131 -0
  206. package/packages/browser/src/plugins/remote-loader/__tests__/index.test.ts +943 -0
  207. package/packages/browser/src/plugins/remote-loader/index.ts +256 -0
  208. package/packages/browser/src/plugins/remote-middleware/__tests__/index.test.ts +116 -0
  209. package/packages/browser/src/plugins/remote-middleware/index.ts +44 -0
  210. package/packages/browser/src/plugins/routing-middleware/__tests__/index.test.ts +64 -0
  211. package/packages/browser/src/plugins/routing-middleware/index.ts +37 -0
  212. package/packages/browser/src/plugins/schema-filter/__tests__/index.test.ts +520 -0
  213. package/packages/browser/src/plugins/schema-filter/index.ts +90 -0
  214. package/packages/browser/src/plugins/validation/__tests__/index.test.ts +78 -0
  215. package/packages/browser/src/plugins/validation/index.ts +44 -0
  216. package/packages/browser/src/test-helpers/browser-storage.ts +75 -0
  217. package/packages/browser/src/test-helpers/factories.ts +18 -0
  218. package/packages/browser/src/test-helpers/fetch-parse.ts +8 -0
  219. package/packages/browser/src/test-helpers/fixtures/cdn-settings.ts +301 -0
  220. package/packages/browser/src/test-helpers/fixtures/classic-destination.ts +25 -0
  221. package/packages/browser/src/test-helpers/fixtures/client-hints.ts +28 -0
  222. package/packages/browser/src/test-helpers/fixtures/create-fetch-method.ts +30 -0
  223. package/packages/browser/src/test-helpers/fixtures/index.ts +4 -0
  224. package/packages/browser/src/test-helpers/fixtures/page-context.ts +11 -0
  225. package/packages/browser/src/test-helpers/test-writekeys.ts +5 -0
  226. package/packages/browser/src/test-helpers/type-assertions.ts +11 -0
  227. package/packages/browser/src/tester/__fixtures__/hightouch-snippet.ts +64 -0
  228. package/packages/browser/src/tester/__fixtures__/index.html +8 -0
  229. package/packages/browser/src/tester/ajs-perf.ts +30 -0
  230. package/packages/browser/src/tester/ajs-tester.ts +119 -0
  231. package/packages/browser/src/tester/server.js +16 -0
  232. package/packages/browser/tsconfig.build.json +9 -0
  233. package/packages/browser/tsconfig.json +13 -0
  234. package/packages/browser/webpack.config.js +106 -0
  235. package/packages/config/package.json +10 -0
  236. package/packages/config/src/index.js +4 -0
  237. package/packages/config/src/jest/config.js +50 -0
  238. package/packages/config/src/jest/get-module-map.js +34 -0
  239. package/packages/config/src/lint-staged/config.js +4 -0
  240. package/packages/config-webpack/package.json +20 -0
  241. package/packages/config-webpack/webpack.config.common.js +75 -0
  242. package/packages/consent/consent-tools/.eslintrc.js +7 -0
  243. package/packages/consent/consent-tools/.lintstagedrc.js +1 -0
  244. package/packages/consent/consent-tools/LICENSE +45 -0
  245. package/packages/consent/consent-tools/README.md +104 -0
  246. package/packages/consent/consent-tools/jest.config.js +6 -0
  247. package/packages/consent/consent-tools/jest.setup.js +4 -0
  248. package/packages/consent/consent-tools/package.json +48 -0
  249. package/packages/consent/consent-tools/src/domain/__tests__/assertions/integrations-assertions.ts +37 -0
  250. package/packages/consent/consent-tools/src/domain/__tests__/consent-stamping.test.ts +45 -0
  251. package/packages/consent/consent-tools/src/domain/__tests__/create-wrapper.test.ts +816 -0
  252. package/packages/consent/consent-tools/src/domain/__tests__/typedef-tests.ts +21 -0
  253. package/packages/consent/consent-tools/src/domain/consent-changed.ts +51 -0
  254. package/packages/consent/consent-tools/src/domain/consent-stamping.ts +19 -0
  255. package/packages/consent/consent-tools/src/domain/create-wrapper.ts +238 -0
  256. package/packages/consent/consent-tools/src/domain/get-initialized-analytics.ts +25 -0
  257. package/packages/consent/consent-tools/src/domain/load-cancellation.ts +31 -0
  258. package/packages/consent/consent-tools/src/domain/validation/__tests__/options-validators.test.ts +77 -0
  259. package/packages/consent/consent-tools/src/domain/validation/__tests__/validation-error.test.ts +15 -0
  260. package/packages/consent/consent-tools/src/domain/validation/common-validators.ts +19 -0
  261. package/packages/consent/consent-tools/src/domain/validation/index.ts +1 -0
  262. package/packages/consent/consent-tools/src/domain/validation/options-validators.ts +74 -0
  263. package/packages/consent/consent-tools/src/domain/validation/validation-error.ts +11 -0
  264. package/packages/consent/consent-tools/src/index.ts +16 -0
  265. package/packages/consent/consent-tools/src/types/errors.ts +14 -0
  266. package/packages/consent/consent-tools/src/types/index.ts +3 -0
  267. package/packages/consent/consent-tools/src/types/settings.ts +121 -0
  268. package/packages/consent/consent-tools/src/types/wrapper.ts +107 -0
  269. package/packages/consent/consent-tools/src/utils/index.ts +4 -0
  270. package/packages/consent/consent-tools/src/utils/pick.ts +18 -0
  271. package/packages/consent/consent-tools/src/utils/pipe.ts +14 -0
  272. package/packages/consent/consent-tools/src/utils/resolve-when.ts +32 -0
  273. package/packages/consent/consent-tools/src/utils/uniq.ts +4 -0
  274. package/packages/consent/consent-tools/tsconfig.build.json +9 -0
  275. package/packages/consent/consent-tools/tsconfig.json +12 -0
  276. package/packages/consent/consent-wrapper-onetrust/.eslintrc.js +7 -0
  277. package/packages/consent/consent-wrapper-onetrust/.lintstagedrc.js +1 -0
  278. package/packages/consent/consent-wrapper-onetrust/LICENSE +45 -0
  279. package/packages/consent/consent-wrapper-onetrust/README.md +125 -0
  280. package/packages/consent/consent-wrapper-onetrust/img/onetrust-cat-id.jpg +0 -0
  281. package/packages/consent/consent-wrapper-onetrust/img/onetrust-popup.jpg +0 -0
  282. package/packages/consent/consent-wrapper-onetrust/jest.config.js +6 -0
  283. package/packages/consent/consent-wrapper-onetrust/jest.setup.js +4 -0
  284. package/packages/consent/consent-wrapper-onetrust/package.json +60 -0
  285. package/packages/consent/consent-wrapper-onetrust/src/domain/__tests__/wrapper.test.ts +151 -0
  286. package/packages/consent/consent-wrapper-onetrust/src/domain/wrapper.ts +61 -0
  287. package/packages/consent/consent-wrapper-onetrust/src/index.ts +6 -0
  288. package/packages/consent/consent-wrapper-onetrust/src/index.umd.ts +11 -0
  289. package/packages/consent/consent-wrapper-onetrust/src/lib/__tests__/onetrust-api.test.ts +181 -0
  290. package/packages/consent/consent-wrapper-onetrust/src/lib/onetrust-api.ts +155 -0
  291. package/packages/consent/consent-wrapper-onetrust/src/lib/validation/index.ts +1 -0
  292. package/packages/consent/consent-wrapper-onetrust/src/lib/validation/onetrust-api-error.ts +11 -0
  293. package/packages/consent/consent-wrapper-onetrust/src/test-helpers/mocks.ts +23 -0
  294. package/packages/consent/consent-wrapper-onetrust/src/test-helpers/onetrust-globals.d.ts +11 -0
  295. package/packages/consent/consent-wrapper-onetrust/src/test-helpers/utils.ts +3 -0
  296. package/packages/consent/consent-wrapper-onetrust/tsconfig.build.json +9 -0
  297. package/packages/consent/consent-wrapper-onetrust/tsconfig.json +11 -0
  298. package/packages/consent/consent-wrapper-onetrust/webpack.config.js +25 -0
  299. package/packages/core/.eslintrc.js +4 -0
  300. package/packages/core/.lintstagedrc.js +1 -0
  301. package/packages/core/LICENSE.MD +45 -0
  302. package/packages/core/README.md +3 -0
  303. package/packages/core/jest.config.js +5 -0
  304. package/packages/core/jest.setup.js +10 -0
  305. package/packages/core/package.json +40 -0
  306. package/packages/core/src/analytics/__tests__/dispatch.test.ts +95 -0
  307. package/packages/core/src/analytics/dispatch.ts +58 -0
  308. package/packages/core/src/analytics/index.ts +11 -0
  309. package/packages/core/src/callback/__tests__/index.test.ts +85 -0
  310. package/packages/core/src/callback/index.ts +51 -0
  311. package/packages/core/src/context/index.ts +123 -0
  312. package/packages/core/src/emitter/__tests__/emitter.test.ts +74 -0
  313. package/packages/core/src/emitter/index.ts +65 -0
  314. package/packages/core/src/emitter/interface.ts +31 -0
  315. package/packages/core/src/events/__tests__/index.test.ts +394 -0
  316. package/packages/core/src/events/index.ts +280 -0
  317. package/packages/core/src/events/interfaces.ts +475 -0
  318. package/packages/core/src/index.ts +19 -0
  319. package/packages/core/src/logger/__tests__/index.test.ts +66 -0
  320. package/packages/core/src/logger/index.ts +74 -0
  321. package/packages/core/src/plugins/index.ts +43 -0
  322. package/packages/core/src/priority-queue/__tests__/backoff.test.ts +23 -0
  323. package/packages/core/src/priority-queue/__tests__/index.test.ts +158 -0
  324. package/packages/core/src/priority-queue/backoff.ts +24 -0
  325. package/packages/core/src/priority-queue/index.ts +103 -0
  326. package/packages/core/src/queue/__tests__/event-queue.test.ts +678 -0
  327. package/packages/core/src/queue/__tests__/extension-flushing.test.ts +416 -0
  328. package/packages/core/src/queue/delivery.ts +73 -0
  329. package/packages/core/src/queue/event-queue.ts +318 -0
  330. package/packages/core/src/stats/__tests__/index.test.ts +103 -0
  331. package/packages/core/src/stats/index.ts +88 -0
  332. package/packages/core/src/task/__tests__/task-group.test.ts +26 -0
  333. package/packages/core/src/task/task-group.ts +31 -0
  334. package/packages/core/src/user/index.ts +7 -0
  335. package/packages/core/src/utils/__tests__/group-by.test.ts +96 -0
  336. package/packages/core/src/utils/__tests__/is-plain-object.test.ts +27 -0
  337. package/packages/core/src/utils/__tests__/is-thenable.test.ts +39 -0
  338. package/packages/core/src/utils/bind-all.ts +19 -0
  339. package/packages/core/src/utils/get-global.ts +17 -0
  340. package/packages/core/src/utils/group-by.ts +30 -0
  341. package/packages/core/src/utils/has-properties.ts +7 -0
  342. package/packages/core/src/utils/is-plain-object.ts +26 -0
  343. package/packages/core/src/utils/is-thenable.ts +9 -0
  344. package/packages/core/src/utils/p-while.ts +12 -0
  345. package/packages/core/src/utils/pick.ts +8 -0
  346. package/packages/core/src/utils/ts-helpers.ts +13 -0
  347. package/packages/core/src/validation/__tests__/assertions.test.ts +155 -0
  348. package/packages/core/src/validation/assertions.ts +72 -0
  349. package/packages/core/src/validation/errors.ts +8 -0
  350. package/packages/core/src/validation/helpers.ts +23 -0
  351. package/packages/core/test-helpers/index.ts +2 -0
  352. package/packages/core/test-helpers/test-ctx.ts +7 -0
  353. package/packages/core/test-helpers/test-event-queue.ts +7 -0
  354. package/packages/core/tsconfig.build.json +9 -0
  355. package/packages/core/tsconfig.json +11 -0
  356. package/packages/node/.eslintrc.js +7 -0
  357. package/packages/node/.lintstagedrc.js +1 -0
  358. package/packages/node/LICENSE +45 -0
  359. package/packages/node/README.md +138 -0
  360. package/packages/node/jest.config.js +5 -0
  361. package/packages/node/jest.setup.js +4 -0
  362. package/packages/node/package.json +50 -0
  363. package/packages/node/scripts/version.sh +11 -0
  364. package/packages/node/src/__tests__/callback.test.ts +47 -0
  365. package/packages/node/src/__tests__/disable.integration.test.ts +42 -0
  366. package/packages/node/src/__tests__/emitter.integration.test.ts +45 -0
  367. package/packages/node/src/__tests__/graceful-shutdown-integration.test.ts +244 -0
  368. package/packages/node/src/__tests__/http-client.integration.test.ts +69 -0
  369. package/packages/node/src/__tests__/http-integration.test.ts +362 -0
  370. package/packages/node/src/__tests__/integration.test.ts +357 -0
  371. package/packages/node/src/__tests__/plugins.test.ts +16 -0
  372. package/packages/node/src/__tests__/settings.test.ts +9 -0
  373. package/packages/node/src/__tests__/test-helpers/assert-shape/http-request-event.ts +13 -0
  374. package/packages/node/src/__tests__/test-helpers/assert-shape/index.ts +2 -0
  375. package/packages/node/src/__tests__/test-helpers/assert-shape/segment-http-api.ts +43 -0
  376. package/packages/node/src/__tests__/test-helpers/create-test-analytics.ts +42 -0
  377. package/packages/node/src/__tests__/test-helpers/factories.ts +17 -0
  378. package/packages/node/src/__tests__/test-helpers/is-valid-date.ts +6 -0
  379. package/packages/node/src/__tests__/test-helpers/resolve-ctx.ts +19 -0
  380. package/packages/node/src/__tests__/test-helpers/resolve-emitter.ts +11 -0
  381. package/packages/node/src/__tests__/test-helpers/sleep.ts +3 -0
  382. package/packages/node/src/__tests__/test-helpers/test-plugin.ts +16 -0
  383. package/packages/node/src/__tests__/typedef-tests.ts +120 -0
  384. package/packages/node/src/app/analytics-node.ts +299 -0
  385. package/packages/node/src/app/context.ts +11 -0
  386. package/packages/node/src/app/dispatch-emit.ts +42 -0
  387. package/packages/node/src/app/emitter.ts +23 -0
  388. package/packages/node/src/app/event-factory.ts +20 -0
  389. package/packages/node/src/app/event-queue.ts +23 -0
  390. package/packages/node/src/app/settings.ts +49 -0
  391. package/packages/node/src/app/types/index.ts +3 -0
  392. package/packages/node/src/app/types/params.ts +76 -0
  393. package/packages/node/src/app/types/plugin.ts +5 -0
  394. package/packages/node/src/app/types/segment-event.ts +7 -0
  395. package/packages/node/src/generated/version.ts +2 -0
  396. package/packages/node/src/index.ts +26 -0
  397. package/packages/node/src/lib/__tests__/abort.test.ts +54 -0
  398. package/packages/node/src/lib/__tests__/create-url.test.ts +35 -0
  399. package/packages/node/src/lib/__tests__/env.test.ts +52 -0
  400. package/packages/node/src/lib/__tests__/get-message-id.test.ts +21 -0
  401. package/packages/node/src/lib/abort.ts +77 -0
  402. package/packages/node/src/lib/base-64-encode.ts +8 -0
  403. package/packages/node/src/lib/create-url.ts +11 -0
  404. package/packages/node/src/lib/env.ts +45 -0
  405. package/packages/node/src/lib/extract-promise-parts.ts +21 -0
  406. package/packages/node/src/lib/fetch.ts +16 -0
  407. package/packages/node/src/lib/get-message-id.ts +10 -0
  408. package/packages/node/src/lib/http-client.ts +95 -0
  409. package/packages/node/src/lib/uuid.ts +1 -0
  410. package/packages/node/src/plugins/segmentio/__tests__/methods.test.ts +223 -0
  411. package/packages/node/src/plugins/segmentio/__tests__/publisher.test.ts +411 -0
  412. package/packages/node/src/plugins/segmentio/context-batch.ts +71 -0
  413. package/packages/node/src/plugins/segmentio/index.ts +66 -0
  414. package/packages/node/src/plugins/segmentio/publisher.ts +265 -0
  415. package/packages/node/tsconfig.build.json +9 -0
  416. package/packages/node/tsconfig.json +10 -0
  417. package/packages/test-helpers/.eslintrc.js +7 -0
  418. package/packages/test-helpers/.lintstagedrc.js +1 -0
  419. package/packages/test-helpers/jest.config.js +3 -0
  420. package/packages/test-helpers/package.json +26 -0
  421. package/packages/test-helpers/src/analytics/cdn-settings-builder.ts +79 -0
  422. package/packages/test-helpers/src/analytics/index.ts +1 -0
  423. package/packages/test-helpers/src/index.ts +2 -0
  424. package/packages/test-helpers/src/utils/index.ts +1 -0
  425. package/packages/test-helpers/src/utils/sleep.ts +4 -0
  426. package/packages/test-helpers/tsconfig.build.json +9 -0
  427. package/packages/test-helpers/tsconfig.json +11 -0
  428. package/tsconfig.json +21 -0
  429. package/turbo.json +39 -0
  430. package/typings/get-monorepo-packages.d.ts +9 -0
  431. package/typings/spawn.d.ts +10 -0
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ./node_modules/.bin/ts-node --script-mode --transpile-only --files
2
+ /* eslint-disable no-undef */
3
+
4
+ const ex = require('execa')
5
+ const S3 = require('aws-sdk/clients/s3')
6
+ const fs = require('fs-extra')
7
+ const path = require('path')
8
+ const mime = require('mime')
9
+ const logUpdate = require('log-update')
10
+
11
+ const bucket =
12
+ process.env.NODE_ENV == 'production'
13
+ ? process.env.PROD_BUCKET
14
+ : process.env.STAGE_BUCKET
15
+ if (!bucket) throw new Error('Missing one of PROD_BUCKET or STAGE_BUCKET')
16
+
17
+ const accessKeyId = process.env.AWS_ACCESS_KEY_ID
18
+ if (!accessKeyId) throw new Error('Missing AWS_ACCESS_KEY_ID')
19
+ const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY
20
+ if (!secretAccessKey) throw new Error('Missing AWS_SECRET_ACCESS_KEY')
21
+ const sessionToken = process.env.AWS_SESSION_TOKEN
22
+ if (!sessionToken) throw new Error('Missing AWS_SESSION_TOKEN')
23
+
24
+ const pathPrefix = process.env.PATH_PREFIX ?? 'browser/candidate'
25
+ const pathVersion = process.env.PATH_VERSION
26
+ if (!pathVersion) throw new Error('Missing PATH_VERSION')
27
+
28
+ const getBranch = async () =>
29
+ (await ex('git', ['branch', '--show-current'])).stdout
30
+
31
+ const getSha = async () =>
32
+ (await ex('git', ['rev-parse', '--short', 'HEAD'])).stdout
33
+
34
+ async function getFiles(dir) {
35
+ const subdirs = await fs.readdir(dir)
36
+ const files = await Promise.all(
37
+ subdirs.map(async (subdir) => {
38
+ const res = path.resolve(dir, subdir)
39
+ return (await fs.stat(res)).isDirectory() ? getFiles(res) : [res]
40
+ })
41
+ )
42
+ return files.reduce((a, f) => a.concat(f, [])).map((f) => f.split(dir)[1])
43
+ }
44
+
45
+ async function upload() {
46
+ const s3 = new S3({
47
+ accessKeyId,
48
+ secretAccessKey,
49
+ sessionToken,
50
+ region: 'us-east-1',
51
+ })
52
+
53
+ const files = await getFiles(path.join(process.cwd(), './dist/umd'))
54
+ const total = files.length
55
+ let progress = 0
56
+
57
+ const uploads = files.map(async (f) => {
58
+ const filePath = path.join(process.cwd(), './dist/umd', f)
59
+
60
+ const options = {
61
+ Bucket: bucket,
62
+ Key: path.join(pathPrefix, pathVersion, f),
63
+ Body: await fs.readFile(filePath),
64
+ ContentType:
65
+ mime.getType(filePath.replace('.gz', '')) || 'application/javascript',
66
+ CacheControl: 'public,max-age=31536000,immutable',
67
+ }
68
+
69
+ if (filePath.includes('.gz')) {
70
+ options.ContentEncoding = 'gzip'
71
+ }
72
+
73
+ const output = await s3.putObject(options).promise()
74
+
75
+ if (pathPrefix === 'browser/release') {
76
+ // only build "v1-latest" when it's a "release" build
77
+ // put latest version with only 5 minutes caching
78
+ const majorVersion = pathVersion.split('.').reverse().pop()
79
+ await s3
80
+ .putObject({
81
+ ...options,
82
+ CacheControl: 'public,max-age=300,immutable',
83
+ Key: path.join(pathPrefix, `v${majorVersion}-latest`, f),
84
+ })
85
+ .promise()
86
+ }
87
+
88
+ progress++
89
+ logUpdate(`Progress: ${progress}/${total}`)
90
+
91
+ return output
92
+ })
93
+
94
+ await Promise.all(uploads)
95
+ }
96
+
97
+ async function release() {
98
+ console.log('Compiling Bundles')
99
+
100
+ const sha = await getSha()
101
+ let branch = process.env.GITHUB_REF_NAME ?? (await getBranch())
102
+
103
+ const meta = {
104
+ sha,
105
+ branch: `${branch}`,
106
+ }
107
+
108
+ console.table(meta)
109
+ const envVars = {
110
+ PATH_VERSION: pathVersion,
111
+ PATH_PREFIX: pathPrefix,
112
+ }
113
+ console.table(envVars)
114
+ console.log('Uploading Assets')
115
+ await upload(meta)
116
+ }
117
+
118
+ release().catch((err) => {
119
+ console.error(err)
120
+ process.exit(1)
121
+ })
@@ -0,0 +1,9 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ function main() {
6
+ node scripts/release.js
7
+ }
8
+
9
+ main
@@ -0,0 +1,8 @@
1
+ #!/bin/sh
2
+
3
+ # Allow the service to run without chamber (for ci, docker-compose, etc)
4
+ if [ -z "$NO_CHAMBER" ];then
5
+ exec chamber exec analytics-next -- node dist/src/boot.js
6
+ else
7
+ exec node dist/src/boot.js
8
+ fi;
@@ -0,0 +1,51 @@
1
+ import { sleep } from '@ht-sdks/events-sdk-js-core'
2
+ import { getBufferedPageCtxFixture } from '../../test-helpers/fixtures'
3
+ import unfetch from 'unfetch'
4
+ import { HtEventsBrowser } from '..'
5
+ import { Analytics } from '../../core/analytics'
6
+ import { createSuccess } from '../../test-helpers/factories'
7
+
8
+ jest.mock('unfetch')
9
+
10
+ const mockFetchSettingsSuccessResponse = () => {
11
+ return jest
12
+ .mocked(unfetch)
13
+ .mockImplementation(() => createSuccess({ integrations: {} }))
14
+ }
15
+
16
+ describe('Lazy initialization', () => {
17
+ let trackSpy: jest.SpiedFunction<Analytics['track']>
18
+ let fetched: jest.MockedFn<typeof unfetch>
19
+ beforeEach(() => {
20
+ fetched = mockFetchSettingsSuccessResponse()
21
+ trackSpy = jest.spyOn(Analytics.prototype, 'track')
22
+ })
23
+
24
+ it('Should be able to delay initialization ', async () => {
25
+ const analytics = new HtEventsBrowser()
26
+ const track = analytics.track('foo')
27
+ await sleep(100)
28
+ expect(trackSpy).not.toBeCalled()
29
+ analytics.load({ writeKey: 'abc' })
30
+ await track
31
+ expect(trackSpy).toBeCalledWith('foo', getBufferedPageCtxFixture())
32
+ })
33
+
34
+ it('.load method return an analytics instance', async () => {
35
+ const analytics = new HtEventsBrowser().load({ writeKey: 'foo' })
36
+ expect(analytics instanceof HtEventsBrowser).toBeTruthy()
37
+ })
38
+
39
+ // Load already defaults to NOT fetching external settings from CDN
40
+ it.skip('should ignore subsequent .load calls', async () => {
41
+ const analytics = new HtEventsBrowser()
42
+ await analytics.load({ writeKey: 'my-write-key' })
43
+ await analytics.load({ writeKey: 'def' })
44
+ expect(fetched).toBeCalledTimes(1)
45
+ expect(fetched).toBeCalledWith(
46
+ expect.stringContaining(
47
+ 'https://cdn.hightouch-events.com/v1/projects/my-write-key/settings'
48
+ )
49
+ )
50
+ })
51
+ })
@@ -0,0 +1,440 @@
1
+ import { HtEventsBrowser } from '../..'
2
+ import unfetch from 'unfetch'
3
+ import { Analytics } from '../../core/analytics'
4
+ import { Context } from '../../core/context'
5
+ import * as Factory from '../../test-helpers/factories'
6
+ import { sleep } from '../../lib/sleep'
7
+ import { setGlobalCDNUrl } from '../../lib/parse-cdn'
8
+ import { User } from '../../core/user'
9
+ import { getBufferedPageCtxFixture } from '../../test-helpers/fixtures'
10
+
11
+ jest.mock('unfetch')
12
+
13
+ const mockFetchSettingsSuccessResponse = () => {
14
+ jest
15
+ .mocked(unfetch)
16
+ .mockImplementation(() => Factory.createSuccess({ integrations: {} }))
17
+ }
18
+
19
+ const mockFetchSettingsErrorResponse = (response?: Partial<Response>) => {
20
+ jest.mocked(unfetch).mockImplementation(() => Factory.createError(response))
21
+ }
22
+
23
+ const writeKey = 'foo'
24
+
25
+ const errMsg = 'errMsg'
26
+
27
+ jest.spyOn(console, 'error').mockImplementation(() => {}) // silence console spam
28
+
29
+ describe('Pre-initialization', () => {
30
+ const trackSpy = jest.spyOn(Analytics.prototype, 'track')
31
+ const identifySpy = jest.spyOn(Analytics.prototype, 'identify')
32
+ const onSpy = jest.spyOn(Analytics.prototype, 'on')
33
+ const getOnSpyCalls = (event: string) =>
34
+ onSpy.mock.calls.filter(([arg1]) => arg1 === event)
35
+
36
+ const readySpy = jest.spyOn(Analytics.prototype, 'ready')
37
+ const browserLoadSpy = jest.spyOn(HtEventsBrowser, 'load')
38
+ const consoleErrorSpy = jest.spyOn(console, 'error')
39
+
40
+ beforeEach(() => {
41
+ setGlobalCDNUrl(undefined as any)
42
+ mockFetchSettingsSuccessResponse()
43
+ ;(window as any).htevents = undefined
44
+ })
45
+
46
+ describe('Smoke', () => {
47
+ test('load should instantiate an object that resolves into an Analytics object', async () => {
48
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
49
+ expect(ajsBrowser).toBeInstanceOf<typeof HtEventsBrowser>(HtEventsBrowser)
50
+ expect(ajsBrowser.instance).toBeUndefined()
51
+ const [ajs, ctx] = await ajsBrowser
52
+ expect(ajsBrowser.instance).toBeInstanceOf<typeof Analytics>(Analytics)
53
+ expect(ajsBrowser.ctx).toBeInstanceOf<typeof Context>(Context)
54
+ expect(ajs).toBeInstanceOf<typeof Analytics>(Analytics)
55
+ expect(ctx).toBeInstanceOf<typeof Context>(Context)
56
+ })
57
+
58
+ test('If a user sends a single pre-initialized track event, that event gets flushed', async () => {
59
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
60
+ const trackCtxPromise = ajsBrowser.track('foo', { name: 'john' })
61
+ const result = await trackCtxPromise
62
+ expect(result).toBeInstanceOf(Context)
63
+ expect(trackSpy).toBeCalledWith(
64
+ 'foo',
65
+ { name: 'john' },
66
+ getBufferedPageCtxFixture()
67
+ )
68
+ expect(trackSpy).toBeCalledTimes(1)
69
+ })
70
+
71
+ test('"return types should not change over the lifecycle for async methods', async () => {
72
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
73
+
74
+ const trackCtxPromise1 = ajsBrowser.track('foo', { name: 'john' })
75
+ expect(trackCtxPromise1).toBeInstanceOf(Promise)
76
+ await ajsBrowser
77
+
78
+ // loaded
79
+ const trackCtxPromise2 = ajsBrowser.track('foo', { name: 'john' })
80
+ expect(trackCtxPromise2).toBeInstanceOf(Promise)
81
+
82
+ expect(await trackCtxPromise1).toBeInstanceOf(Context)
83
+ expect(await trackCtxPromise2).toBeInstanceOf(Context)
84
+ })
85
+
86
+ test('return types should not change over lifecycle for sync methods', async () => {
87
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
88
+ const user = ajsBrowser.user()
89
+ expect(user).toBeInstanceOf(Promise)
90
+ await ajsBrowser
91
+
92
+ // loaded
93
+ const user2 = ajsBrowser.user()
94
+ expect(user2).toBeInstanceOf(Promise)
95
+
96
+ expect(await user).toBeInstanceOf(User)
97
+ expect(await user2).toBeInstanceOf(User)
98
+ })
99
+
100
+ test('version should return version', async () => {
101
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
102
+ expect(typeof ajsBrowser.VERSION).toBe('string')
103
+ })
104
+
105
+ test('If a user sends multiple events, all of those event gets flushed', async () => {
106
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
107
+ const trackCtxPromise = ajsBrowser.track('foo', { name: 'john' })
108
+ const trackCtxPromise2 = ajsBrowser.track('bar', { age: 123 })
109
+ const identifyCtxPromise = ajsBrowser.identify('hello')
110
+
111
+ await Promise.all([trackCtxPromise, trackCtxPromise2, identifyCtxPromise])
112
+
113
+ expect(trackSpy).toBeCalledWith(
114
+ 'foo',
115
+ { name: 'john' },
116
+ getBufferedPageCtxFixture()
117
+ )
118
+ expect(trackSpy).toBeCalledWith(
119
+ 'bar',
120
+ { age: 123 },
121
+ getBufferedPageCtxFixture()
122
+ )
123
+ expect(trackSpy).toBeCalledTimes(2)
124
+
125
+ expect(identifySpy).toBeCalledWith('hello', getBufferedPageCtxFixture())
126
+ expect(identifySpy).toBeCalledTimes(1)
127
+ })
128
+
129
+ // by default, we do not fetch settings from cdn
130
+ test.skip('should not throw on initialization failures', async () => {
131
+ mockFetchSettingsErrorResponse()
132
+ const ajs = HtEventsBrowser.load({ writeKey })
133
+ await sleep(100)
134
+ expect(ajs.instance).toBeUndefined()
135
+ void ajs.track('foo')
136
+ })
137
+
138
+ // by default, we do not fetch settings from cdn
139
+ test.skip('should log errors if network error', async () => {
140
+ const err = {
141
+ status: 403,
142
+ statusText: 'Forbidden',
143
+ json: undefined,
144
+ }
145
+ mockFetchSettingsErrorResponse(err)
146
+ const consoleSpy = jest
147
+ .spyOn(console, 'error')
148
+ .mockImplementationOnce(() => {})
149
+ HtEventsBrowser.load({ writeKey: 'abc' })
150
+ await sleep(500)
151
+ expect(consoleSpy).toBeCalled()
152
+ })
153
+ })
154
+
155
+ describe('Promise API', () => {
156
+ describe('.then', () => {
157
+ test('.then should be called on success', () => {
158
+ const ajsBrowser = HtEventsBrowser.load({ writeKey: 'abc' })
159
+ const newPromise = ajsBrowser.then(([analytics, context]) => {
160
+ expect(analytics).toBeInstanceOf<typeof Analytics>(Analytics)
161
+ expect(context).toBeInstanceOf<typeof Context>(Context)
162
+ })
163
+ expect(newPromise).toBeInstanceOf<typeof Promise>(Promise)
164
+ return newPromise
165
+ })
166
+
167
+ it('.then should pass to the next .then', async () => {
168
+ const ajsBrowser = HtEventsBrowser.load({ writeKey: 'abc' })
169
+ const obj = ajsBrowser.then(() => ({ foo: 123 } as const))
170
+ expect(obj).toBeInstanceOf(Promise)
171
+ await obj.then((el) => expect(el.foo).toBe(123))
172
+ })
173
+ })
174
+
175
+ describe('.catch', () => {
176
+ it('should be capable of handling errors if using promise syntax', async () => {
177
+ browserLoadSpy.mockImplementationOnce((): any => Promise.reject(errMsg))
178
+
179
+ await expect(() =>
180
+ HtEventsBrowser.load({ writeKey: 'abc' })
181
+ ).rejects.toEqual(errMsg)
182
+ })
183
+ })
184
+
185
+ describe('.finally', () => {
186
+ test('success', async () => {
187
+ const ajsBrowser = HtEventsBrowser.load({ writeKey: 'abc' })
188
+ const thenCb = jest.fn()
189
+ const finallyCb = jest.fn()
190
+ const catchCb = jest.fn()
191
+ await ajsBrowser.then(thenCb).catch(catchCb).finally(finallyCb)
192
+ expect(catchCb).not.toBeCalled()
193
+ expect(finallyCb).toBeCalledTimes(1)
194
+ expect(thenCb).toBeCalledTimes(1)
195
+ })
196
+ test('rejection', async () => {
197
+ browserLoadSpy.mockImplementationOnce((): any => Promise.reject(errMsg))
198
+ const ajsBrowser = HtEventsBrowser.load({ writeKey: 'abc' })
199
+ const onFinallyCb = jest.fn()
200
+ await ajsBrowser
201
+ .catch((reason) => {
202
+ expect(reason).toBe(errMsg)
203
+ })
204
+ .finally(() => {
205
+ onFinallyCb()
206
+ })
207
+ expect(onFinallyCb).toBeCalledTimes(1)
208
+ expect.assertions(2)
209
+ })
210
+ })
211
+ })
212
+
213
+ describe('Load failures', () => {
214
+ test('rejected promise should work as expected for buffered analytics instances', async () => {
215
+ trackSpy.mockImplementationOnce(() => Promise.reject(errMsg))
216
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
217
+ try {
218
+ await ajsBrowser.track('foo', { name: 'john' })
219
+ } catch (err) {
220
+ expect(err).toBe(errMsg)
221
+ }
222
+ expect.assertions(1)
223
+ })
224
+
225
+ test('rejected promise should work as expected for initialized analytics instances', async () => {
226
+ trackSpy.mockImplementationOnce(() => Promise.reject(errMsg))
227
+ const [analytics] = await HtEventsBrowser.load({ writeKey })
228
+ try {
229
+ await analytics.track('foo', { name: 'john' })
230
+ } catch (err) {
231
+ expect(err).toBe(errMsg)
232
+ }
233
+ expect.assertions(1)
234
+ })
235
+ })
236
+
237
+ describe('Snippet / standalone', () => {
238
+ test('If a snippet user sends multiple events, all of those event gets flushed', async () => {
239
+ const onTrackCb = jest.fn()
240
+ const onTrack = ['on', 'track', onTrackCb]
241
+ const track = ['track', 'foo']
242
+ const track2 = ['track', 'bar']
243
+ const identify = ['identify']
244
+
245
+ ;(window as any).htevents = [onTrack, track, track2, identify]
246
+
247
+ await HtEventsBrowser.standalone(writeKey)
248
+
249
+ await sleep(100) // the snippet does not return a promise (pre-initialization) ... it sometimes has a callback as the third argument.
250
+ expect(trackSpy).toBeCalledWith('foo', getBufferedPageCtxFixture())
251
+ expect(trackSpy).toBeCalledWith('bar', getBufferedPageCtxFixture())
252
+ expect(trackSpy).toBeCalledTimes(2)
253
+
254
+ expect(identifySpy).toBeCalledTimes(1)
255
+
256
+ expect(getOnSpyCalls('track').length).toBe(1)
257
+ expect(onTrackCb).toBeCalledTimes(2) // gets called once for each track event
258
+ expect(onTrackCb).toBeCalledWith('foo', {}, undefined)
259
+ expect(onTrackCb).toBeCalledWith('bar', {}, undefined)
260
+ })
261
+ test('If a snippet user has an event "fail", it will not create a promise rejection or effect other method calls', async () => {
262
+ identifySpy.mockImplementationOnce(() => {
263
+ return Promise.reject('identity rejection')
264
+ })
265
+ consoleErrorSpy.mockImplementationOnce(() => null)
266
+
267
+ const onTrackCb = jest.fn()
268
+ const onTrack = ['on', 'track', onTrackCb]
269
+ const track = ['track', 'foo']
270
+ const track2 = ['track', 'bar']
271
+ const identify = ['identify']
272
+
273
+ ;(window as any).htevents = [identify, onTrack, track, track2]
274
+
275
+ await HtEventsBrowser.standalone(writeKey)
276
+
277
+ await sleep(100) // the snippet does not return a promise (pre-initialization) ... it sometimes has a callback as the third argument.
278
+ expect(trackSpy).toBeCalledWith('foo', getBufferedPageCtxFixture())
279
+ expect(trackSpy).toBeCalledWith('bar', getBufferedPageCtxFixture())
280
+ expect(trackSpy).toBeCalledTimes(2)
281
+
282
+ expect(identifySpy).toBeCalledWith(getBufferedPageCtxFixture())
283
+ expect(identifySpy).toBeCalledTimes(1)
284
+ expect(consoleErrorSpy).toBeCalledTimes(1)
285
+
286
+ expect(consoleErrorSpy).toBeCalledWith('identity rejection')
287
+
288
+ expect(getOnSpyCalls('track').length).toBe(1)
289
+
290
+ expect(onTrackCb).toBeCalledTimes(2) // gets called once for each track event
291
+ expect(onTrackCb).toBeCalledWith('foo', {}, undefined)
292
+ expect(onTrackCb).toBeCalledWith('bar', {}, undefined)
293
+ })
294
+ test('events can be buffered under a custom window key', async () => {
295
+ const onTrackCb = jest.fn()
296
+ const onTrack = ['on', 'track', onTrackCb]
297
+ const track = ['track', 'foo']
298
+ const track2 = ['track', 'bar']
299
+ const identify = ['identify']
300
+
301
+ ;(window as any).hightouch = [onTrack, track, track2, identify]
302
+
303
+ await HtEventsBrowser.standalone(writeKey, {
304
+ globalAnalyticsKey: 'hightouch',
305
+ })
306
+
307
+ await sleep(100) // the snippet does not return a promise (pre-initialization) ... it sometimes has a callback as the third argument.
308
+ expect(trackSpy).toBeCalledWith('foo', getBufferedPageCtxFixture())
309
+ expect(trackSpy).toBeCalledWith('bar', getBufferedPageCtxFixture())
310
+ expect(trackSpy).toBeCalledTimes(2)
311
+
312
+ expect(identifySpy).toBeCalledTimes(1)
313
+
314
+ expect(getOnSpyCalls('track').length).toBe(1)
315
+ expect(onTrackCb).toBeCalledTimes(2) // gets called once for each track event
316
+ expect(onTrackCb).toBeCalledWith('foo', {}, undefined)
317
+ expect(onTrackCb).toBeCalledWith('bar', {}, undefined)
318
+ })
319
+ })
320
+
321
+ describe('Emitter methods', () => {
322
+ test('If, before initialization, .on("track") is called, the .on method should be called after analytics load', async () => {
323
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
324
+ const args = ['track', jest.fn()] as const
325
+ ajsBrowser.on(...args)
326
+ expect(onSpy).not.toHaveBeenCalledWith(...args)
327
+
328
+ await ajsBrowser
329
+ expect(onSpy).toBeCalledWith(...args)
330
+ expect(getOnSpyCalls('track').length).toBe(1)
331
+ })
332
+
333
+ test('If, before initialization .on("track") is called and then .track is called, the callback method should be called after analytics loads', async () => {
334
+ const onFnCb = jest.fn()
335
+ const analytics = HtEventsBrowser.load({ writeKey })
336
+ analytics.on('track', onFnCb)
337
+ const trackCtxPromise = analytics.track('foo', { name: 123 })
338
+
339
+ expect(onFnCb).not.toHaveBeenCalled()
340
+
341
+ await Promise.all([analytics, trackCtxPromise])
342
+
343
+ expect(onSpy).toBeCalledWith('track', onFnCb)
344
+ expect(getOnSpyCalls('track').length).toBe(1)
345
+
346
+ expect(onFnCb).toHaveBeenCalledWith('foo', { name: 123 }, undefined)
347
+ expect(onFnCb).toBeCalledTimes(1)
348
+ })
349
+
350
+ test('If, before initialization, .ready is called, the callback method should be called after analytics loads', async () => {
351
+ const onReadyCb = jest.fn()
352
+ const analytics = HtEventsBrowser.load({ writeKey })
353
+ const onReadyPromise = analytics.ready(onReadyCb)
354
+ expect(onReadyCb).not.toHaveBeenCalled()
355
+ await onReadyPromise
356
+ expect(readySpy).toHaveBeenCalledTimes(1)
357
+ expect(onReadyCb).toHaveBeenCalledTimes(1)
358
+ expect(readySpy).toHaveBeenCalledWith(expect.any(Function))
359
+ })
360
+
361
+ test('Should work with "on" events if a track event is called after load is complete', async () => {
362
+ const onTrackCb = jest.fn()
363
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
364
+ ajsBrowser.on('track', onTrackCb)
365
+ await ajsBrowser
366
+ await ajsBrowser.track('foo', { name: 123 })
367
+
368
+ expect(onTrackCb).toHaveBeenCalledTimes(1)
369
+ expect(onTrackCb).toHaveBeenCalledWith('foo', { name: 123 }, undefined)
370
+ })
371
+ test('"on, off, once" should return ajsBrowser', () => {
372
+ const analytics = HtEventsBrowser.load({ writeKey })
373
+ expect(
374
+ [
375
+ analytics.on('track', jest.fn),
376
+ analytics.off('track', jest.fn),
377
+ analytics.once('track', jest.fn),
378
+ ].map((el) => el instanceof HtEventsBrowser)
379
+ ).toEqual([true, true, true])
380
+ })
381
+
382
+ test('"emitted" events should be chainable', async () => {
383
+ const onTrackCb = jest.fn()
384
+ const onIdentifyCb = jest.fn()
385
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
386
+ const identifyResult = ajsBrowser.identify('bar')
387
+ const result = ajsBrowser
388
+ .on('track', onTrackCb)
389
+ .on('identify', onIdentifyCb)
390
+ .once('group', jest.fn)
391
+ .off('alias', jest.fn)
392
+
393
+ expect(result instanceof HtEventsBrowser).toBeTruthy()
394
+ await ajsBrowser.track('foo', { name: 123 })
395
+ expect(onTrackCb).toHaveBeenCalledTimes(1)
396
+ expect(onTrackCb).toHaveBeenCalledWith('foo', { name: 123 }, undefined)
397
+
398
+ await identifyResult
399
+ expect(onIdentifyCb).toHaveBeenCalledTimes(1)
400
+ expect(onIdentifyCb).toHaveBeenCalledWith('bar', {}, undefined)
401
+ })
402
+
403
+ test('the "this" value of "emitted" event callbacks should be Analytics', async () => {
404
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
405
+ ajsBrowser.on('track', function onTrackCb(this: any) {
406
+ expect(this).toBeInstanceOf(Analytics)
407
+ })
408
+ ajsBrowser.once('group', function trackOnceCb(this: any) {
409
+ expect(this).toBeInstanceOf(Analytics)
410
+ })
411
+
412
+ await Promise.all([
413
+ ajsBrowser.track('foo', { name: 123 }),
414
+ ajsBrowser.group('foo'),
415
+ ])
416
+ })
417
+
418
+ test('"return types should not change over the lifecycle for chainable methods', async () => {
419
+ const ajsBrowser = HtEventsBrowser.load({ writeKey })
420
+
421
+ const result1 = ajsBrowser.on('track', jest.fn)
422
+ expect(result1).toBeInstanceOf(HtEventsBrowser)
423
+ await result1
424
+ // loaded
425
+ const result2 = ajsBrowser.on('track', jest.fn)
426
+ expect(result2).toBeInstanceOf(HtEventsBrowser)
427
+ })
428
+ })
429
+
430
+ describe('Multi-instance', () => {
431
+ it('should not throw an error', async () => {
432
+ const ajsBrowser1 = HtEventsBrowser.load({ writeKey: 'foo' })
433
+ const ajsBrowser2 = HtEventsBrowser.load({ writeKey: 'abc' })
434
+ expect(ajsBrowser1).toBeInstanceOf(HtEventsBrowser)
435
+ expect(ajsBrowser2).toBeInstanceOf(HtEventsBrowser)
436
+ await ajsBrowser1
437
+ await ajsBrowser2
438
+ })
439
+ })
440
+ })