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.
- package/.editorconfig +10 -0
- package/.eslintrc.isomorphic.js +26 -0
- package/.eslintrc.js +86 -0
- package/.gitattributes +1 -0
- package/.github/workflows/ci.yml +33 -0
- package/.github/workflows/deploy-browser-cdn-candidate.yml +51 -0
- package/.github/workflows/deploy-releases.yml +178 -0
- package/.nvmrc +1 -0
- package/.prettierrc +7 -0
- package/.vscode/extensions.json +3 -0
- package/.vscode/launch.json +81 -0
- package/.vscode/settings.json +41 -0
- package/.yarn/plugins/@yarnpkg/plugin-constraints.cjs +52 -0
- package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +546 -0
- package/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
- package/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs +28 -0
- package/.yarn/releases/yarn-3.4.1.cjs +873 -0
- package/.yarnrc.yml +15 -0
- package/jest.config.js +18 -0
- package/package.json +59 -0
- package/packages/browser/.eslintrc.js +9 -0
- package/packages/browser/.lintstagedrc.js +1 -0
- package/packages/browser/ARCHITECTURE.md +48 -0
- package/packages/browser/LICENSE.MD +45 -0
- package/packages/browser/Makefile +64 -0
- package/packages/browser/README.md +227 -0
- package/packages/browser/e2e-tests/local-server.ts +28 -0
- package/packages/browser/e2e-tests/performance/ajs-perf-browser.test.ts +75 -0
- package/packages/browser/jest.config.js +15 -0
- package/packages/browser/jest.setup.js +10 -0
- package/packages/browser/package.json +106 -0
- package/packages/browser/qa/README.md +41 -0
- package/packages/browser/qa/__fixtures__/snippets.ts +148 -0
- package/packages/browser/qa/__tests__/backwards-compatibility.test.ts +180 -0
- package/packages/browser/qa/__tests__/destinations.test.ts +101 -0
- package/packages/browser/qa/__tests__/smoke.test.ts +170 -0
- package/packages/browser/qa/lib/benchmark.ts +36 -0
- package/packages/browser/qa/lib/browser.ts +28 -0
- package/packages/browser/qa/lib/jest-reporter.js +57 -0
- package/packages/browser/qa/lib/runner.ts +142 -0
- package/packages/browser/qa/lib/schema.ts +59 -0
- package/packages/browser/qa/lib/server.ts +54 -0
- package/packages/browser/qa/lib/stats.ts +52 -0
- package/packages/browser/scripts/build-prep.sh +7 -0
- package/packages/browser/scripts/ci.sh +15 -0
- package/packages/browser/scripts/release.js +121 -0
- package/packages/browser/scripts/release.sh +9 -0
- package/packages/browser/scripts/run.sh +8 -0
- package/packages/browser/src/browser/__tests__/analytics-lazy-init.integration.test.ts +51 -0
- package/packages/browser/src/browser/__tests__/analytics-pre-init.integration.test.ts +440 -0
- package/packages/browser/src/browser/__tests__/anon-id-and-reset.integration.test.ts +73 -0
- package/packages/browser/src/browser/__tests__/cdn.test.ts +53 -0
- package/packages/browser/src/browser/__tests__/csp-detection.test.ts +140 -0
- package/packages/browser/src/browser/__tests__/inspector.integration.test.ts +121 -0
- package/packages/browser/src/browser/__tests__/integration.test.ts +1213 -0
- package/packages/browser/src/browser/__tests__/integrations.integration.test.ts +260 -0
- package/packages/browser/src/browser/__tests__/page-enrichment.integration.test.ts +216 -0
- package/packages/browser/src/browser/__tests__/query-string.integration.test.ts +116 -0
- package/packages/browser/src/browser/__tests__/standalone-analytics.test.ts +303 -0
- package/packages/browser/src/browser/__tests__/standalone-errors.test.ts +136 -0
- package/packages/browser/src/browser/__tests__/standalone.test.ts +97 -0
- package/packages/browser/src/browser/__tests__/typedef-tests/analytics-browser.ts +150 -0
- package/packages/browser/src/browser/__tests__/update-cdn-settings.test.ts +71 -0
- package/packages/browser/src/browser/browser-umd.ts +19 -0
- package/packages/browser/src/browser/index.ts +486 -0
- package/packages/browser/src/browser/standalone-analytics.ts +62 -0
- package/packages/browser/src/browser/standalone-interface.ts +11 -0
- package/packages/browser/src/browser/standalone.ts +92 -0
- package/packages/browser/src/core/__tests__/track-form.test.ts +193 -0
- package/packages/browser/src/core/__tests__/track-link.test.ts +252 -0
- package/packages/browser/src/core/analytics/__tests__/integration.test.ts +334 -0
- package/packages/browser/src/core/analytics/__tests__/test-plugins.ts +94 -0
- package/packages/browser/src/core/analytics/index.ts +672 -0
- package/packages/browser/src/core/analytics/interfaces.ts +100 -0
- package/packages/browser/src/core/arguments-resolver/__tests__/index.test.ts +524 -0
- package/packages/browser/src/core/arguments-resolver/index.ts +200 -0
- package/packages/browser/src/core/auto-track.ts +152 -0
- package/packages/browser/src/core/buffer/__tests__/index.test.ts +455 -0
- package/packages/browser/src/core/buffer/index.ts +371 -0
- package/packages/browser/src/core/callback/index.ts +1 -0
- package/packages/browser/src/core/connection/__tests__/index.test.ts +25 -0
- package/packages/browser/src/core/connection/index.ts +13 -0
- package/packages/browser/src/core/constants/index.ts +1 -0
- package/packages/browser/src/core/context/__tests__/index.test.ts +201 -0
- package/packages/browser/src/core/context/index.ts +21 -0
- package/packages/browser/src/core/environment/index.ts +7 -0
- package/packages/browser/src/core/events/__tests__/index.test.ts +450 -0
- package/packages/browser/src/core/events/index.ts +280 -0
- package/packages/browser/src/core/events/interfaces.ts +36 -0
- package/packages/browser/src/core/inspector/index.ts +14 -0
- package/packages/browser/src/core/page/__tests__/index.test.ts +130 -0
- package/packages/browser/src/core/page/add-page-context.ts +33 -0
- package/packages/browser/src/core/page/get-page-context.ts +140 -0
- package/packages/browser/src/core/page/index.ts +2 -0
- package/packages/browser/src/core/plugin/index.ts +12 -0
- package/packages/browser/src/core/query-string/__tests__/gracefulDecodeURIComponent.test.ts +17 -0
- package/packages/browser/src/core/query-string/__tests__/index.test.ts +149 -0
- package/packages/browser/src/core/query-string/__tests__/pickPrefix.test.ts +31 -0
- package/packages/browser/src/core/query-string/__tests__/useQueryString.test.ts +60 -0
- package/packages/browser/src/core/query-string/gracefulDecodeURIComponent.ts +16 -0
- package/packages/browser/src/core/query-string/index.ts +64 -0
- package/packages/browser/src/core/query-string/pickPrefix.ts +20 -0
- package/packages/browser/src/core/queue/__tests__/event-queue.test.ts +82 -0
- package/packages/browser/src/core/queue/event-queue.ts +22 -0
- package/packages/browser/src/core/session/__tests__/index.test.ts +41 -0
- package/packages/browser/src/core/session/index.ts +107 -0
- package/packages/browser/src/core/stats/__tests__/index.test.ts +15 -0
- package/packages/browser/src/core/stats/__tests__/remote-metrics.test.ts +189 -0
- package/packages/browser/src/core/stats/index.ts +15 -0
- package/packages/browser/src/core/stats/remote-metrics.ts +144 -0
- package/packages/browser/src/core/storage/__tests__/cookieStorage.test.ts +58 -0
- package/packages/browser/src/core/storage/__tests__/localStorage.test.ts +70 -0
- package/packages/browser/src/core/storage/__tests__/test-helpers.ts +26 -0
- package/packages/browser/src/core/storage/__tests__/universalStorage.test.ts +167 -0
- package/packages/browser/src/core/storage/cookieStorage.ts +80 -0
- package/packages/browser/src/core/storage/index.ts +64 -0
- package/packages/browser/src/core/storage/localStorage.ts +45 -0
- package/packages/browser/src/core/storage/memoryStorage.ts +22 -0
- package/packages/browser/src/core/storage/settings.ts +23 -0
- package/packages/browser/src/core/storage/types.ts +49 -0
- package/packages/browser/src/core/storage/universalStorage.ts +78 -0
- package/packages/browser/src/core/user/__tests__/index.test.ts +922 -0
- package/packages/browser/src/core/user/__tests__/migrate.test.ts +101 -0
- package/packages/browser/src/core/user/__tests__/session.test.ts +136 -0
- package/packages/browser/src/core/user/__tests__/tld.test.ts +36 -0
- package/packages/browser/src/core/user/index.ts +399 -0
- package/packages/browser/src/core/user/migrate.ts +126 -0
- package/packages/browser/src/core/user/tld.ts +65 -0
- package/packages/browser/src/core/user/vendor/crypto-es/LICENSE +53 -0
- package/packages/browser/src/core/user/vendor/crypto-es/lib/aes.ts +302 -0
- package/packages/browser/src/core/user/vendor/crypto-es/lib/cipher-core.ts +922 -0
- package/packages/browser/src/core/user/vendor/crypto-es/lib/core.ts +806 -0
- package/packages/browser/src/core/user/vendor/crypto-es/lib/enc-base64.ts +110 -0
- package/packages/browser/src/core/user/vendor/crypto-es/lib/evpkdf.ts +110 -0
- package/packages/browser/src/core/user/vendor/crypto-es/lib/md5.ts +238 -0
- package/packages/browser/src/core/user/vendor/readme.md +7 -0
- package/packages/browser/src/generated/__tests__/version.test.ts +18 -0
- package/packages/browser/src/generated/version.ts +2 -0
- package/packages/browser/src/index.ts +13 -0
- package/packages/browser/src/lib/__tests__/embedded-write-key.test.ts +15 -0
- package/packages/browser/src/lib/__tests__/fetch.test.ts +35 -0
- package/packages/browser/src/lib/__tests__/get-process-env.test.ts +5 -0
- package/packages/browser/src/lib/__tests__/group-by.test.ts +96 -0
- package/packages/browser/src/lib/__tests__/is-plan-event-enabled.test.ts +36 -0
- package/packages/browser/src/lib/__tests__/is-thenable.test.ts +39 -0
- package/packages/browser/src/lib/__tests__/merged-options.test.ts +123 -0
- package/packages/browser/src/lib/__tests__/on-page-change.test.ts +74 -0
- package/packages/browser/src/lib/__tests__/parse-cdn.test.ts +88 -0
- package/packages/browser/src/lib/__tests__/pick.test.ts +34 -0
- package/packages/browser/src/lib/__tests__/pick.typedef.ts +39 -0
- package/packages/browser/src/lib/bind-all.ts +19 -0
- package/packages/browser/src/lib/browser-polyfill.ts +23 -0
- package/packages/browser/src/lib/client-hints/__tests__/index.test.ts +66 -0
- package/packages/browser/src/lib/client-hints/index.ts +16 -0
- package/packages/browser/src/lib/client-hints/interfaces.ts +42 -0
- package/packages/browser/src/lib/create-deferred.ts +16 -0
- package/packages/browser/src/lib/csp-detection.ts +8 -0
- package/packages/browser/src/lib/embedded-write-key.ts +24 -0
- package/packages/browser/src/lib/fetch.ts +10 -0
- package/packages/browser/src/lib/get-global.ts +16 -0
- package/packages/browser/src/lib/get-process-env.ts +11 -0
- package/packages/browser/src/lib/global-analytics-helper.ts +31 -0
- package/packages/browser/src/lib/group-by.ts +30 -0
- package/packages/browser/src/lib/is-plan-event-enabled.ts +20 -0
- package/packages/browser/src/lib/is-thenable.ts +9 -0
- package/packages/browser/src/lib/load-script.ts +66 -0
- package/packages/browser/src/lib/merged-options.ts +46 -0
- package/packages/browser/src/lib/on-page-change.ts +29 -0
- package/packages/browser/src/lib/p-while.ts +12 -0
- package/packages/browser/src/lib/parse-cdn.ts +56 -0
- package/packages/browser/src/lib/pick.ts +28 -0
- package/packages/browser/src/lib/priority-queue/__tests__/backoff.test.ts +23 -0
- package/packages/browser/src/lib/priority-queue/__tests__/index.test.ts +158 -0
- package/packages/browser/src/lib/priority-queue/__tests__/persisted.test.ts +228 -0
- package/packages/browser/src/lib/priority-queue/backoff.ts +24 -0
- package/packages/browser/src/lib/priority-queue/index.ts +6 -0
- package/packages/browser/src/lib/priority-queue/persisted.ts +127 -0
- package/packages/browser/src/lib/sleep.ts +4 -0
- package/packages/browser/src/lib/to-facade.ts +53 -0
- package/packages/browser/src/lib/version-type.ts +10 -0
- package/packages/browser/src/node/__tests__/node-integration.test.ts +19 -0
- package/packages/browser/src/node/index.ts +36 -0
- package/packages/browser/src/node/node.browser.ts +7 -0
- package/packages/browser/src/plugins/ajs-destination/__tests__/index.test.ts +834 -0
- package/packages/browser/src/plugins/ajs-destination/index.ts +392 -0
- package/packages/browser/src/plugins/ajs-destination/loader.ts +129 -0
- package/packages/browser/src/plugins/ajs-destination/types.ts +44 -0
- package/packages/browser/src/plugins/ajs-destination/utils.ts +32 -0
- package/packages/browser/src/plugins/analytics-node/__tests__/index.test.ts +69 -0
- package/packages/browser/src/plugins/analytics-node/index.ts +67 -0
- package/packages/browser/src/plugins/env-enrichment/__tests__/index.test.ts +421 -0
- package/packages/browser/src/plugins/env-enrichment/index.ts +208 -0
- package/packages/browser/src/plugins/hightouchio/__tests__/batched-dispatcher.test.ts +299 -0
- package/packages/browser/src/plugins/hightouchio/__tests__/index.test.ts +317 -0
- package/packages/browser/src/plugins/hightouchio/__tests__/normalize.test.ts +181 -0
- package/packages/browser/src/plugins/hightouchio/__tests__/retries.test.ts +82 -0
- package/packages/browser/src/plugins/hightouchio/batched-dispatcher.ts +127 -0
- package/packages/browser/src/plugins/hightouchio/fetch-dispatcher.ts +27 -0
- package/packages/browser/src/plugins/hightouchio/index.ts +147 -0
- package/packages/browser/src/plugins/hightouchio/normalize.ts +71 -0
- package/packages/browser/src/plugins/hightouchio/schedule-flush.ts +58 -0
- package/packages/browser/src/plugins/legacy-video-plugins/__tests__/index.test.ts +48 -0
- package/packages/browser/src/plugins/legacy-video-plugins/index.ts +16 -0
- package/packages/browser/src/plugins/middleware/__tests__/index.test.ts +268 -0
- package/packages/browser/src/plugins/middleware/index.ts +131 -0
- package/packages/browser/src/plugins/remote-loader/__tests__/index.test.ts +943 -0
- package/packages/browser/src/plugins/remote-loader/index.ts +256 -0
- package/packages/browser/src/plugins/remote-middleware/__tests__/index.test.ts +116 -0
- package/packages/browser/src/plugins/remote-middleware/index.ts +44 -0
- package/packages/browser/src/plugins/routing-middleware/__tests__/index.test.ts +64 -0
- package/packages/browser/src/plugins/routing-middleware/index.ts +37 -0
- package/packages/browser/src/plugins/schema-filter/__tests__/index.test.ts +520 -0
- package/packages/browser/src/plugins/schema-filter/index.ts +90 -0
- package/packages/browser/src/plugins/validation/__tests__/index.test.ts +78 -0
- package/packages/browser/src/plugins/validation/index.ts +44 -0
- package/packages/browser/src/test-helpers/browser-storage.ts +75 -0
- package/packages/browser/src/test-helpers/factories.ts +18 -0
- package/packages/browser/src/test-helpers/fetch-parse.ts +8 -0
- package/packages/browser/src/test-helpers/fixtures/cdn-settings.ts +301 -0
- package/packages/browser/src/test-helpers/fixtures/classic-destination.ts +25 -0
- package/packages/browser/src/test-helpers/fixtures/client-hints.ts +28 -0
- package/packages/browser/src/test-helpers/fixtures/create-fetch-method.ts +30 -0
- package/packages/browser/src/test-helpers/fixtures/index.ts +4 -0
- package/packages/browser/src/test-helpers/fixtures/page-context.ts +11 -0
- package/packages/browser/src/test-helpers/test-writekeys.ts +5 -0
- package/packages/browser/src/test-helpers/type-assertions.ts +11 -0
- package/packages/browser/src/tester/__fixtures__/hightouch-snippet.ts +64 -0
- package/packages/browser/src/tester/__fixtures__/index.html +8 -0
- package/packages/browser/src/tester/ajs-perf.ts +30 -0
- package/packages/browser/src/tester/ajs-tester.ts +119 -0
- package/packages/browser/src/tester/server.js +16 -0
- package/packages/browser/tsconfig.build.json +9 -0
- package/packages/browser/tsconfig.json +13 -0
- package/packages/browser/webpack.config.js +106 -0
- package/packages/config/package.json +10 -0
- package/packages/config/src/index.js +4 -0
- package/packages/config/src/jest/config.js +50 -0
- package/packages/config/src/jest/get-module-map.js +34 -0
- package/packages/config/src/lint-staged/config.js +4 -0
- package/packages/config-webpack/package.json +20 -0
- package/packages/config-webpack/webpack.config.common.js +75 -0
- package/packages/consent/consent-tools/.eslintrc.js +7 -0
- package/packages/consent/consent-tools/.lintstagedrc.js +1 -0
- package/packages/consent/consent-tools/LICENSE +45 -0
- package/packages/consent/consent-tools/README.md +104 -0
- package/packages/consent/consent-tools/jest.config.js +6 -0
- package/packages/consent/consent-tools/jest.setup.js +4 -0
- package/packages/consent/consent-tools/package.json +48 -0
- package/packages/consent/consent-tools/src/domain/__tests__/assertions/integrations-assertions.ts +37 -0
- package/packages/consent/consent-tools/src/domain/__tests__/consent-stamping.test.ts +45 -0
- package/packages/consent/consent-tools/src/domain/__tests__/create-wrapper.test.ts +816 -0
- package/packages/consent/consent-tools/src/domain/__tests__/typedef-tests.ts +21 -0
- package/packages/consent/consent-tools/src/domain/consent-changed.ts +51 -0
- package/packages/consent/consent-tools/src/domain/consent-stamping.ts +19 -0
- package/packages/consent/consent-tools/src/domain/create-wrapper.ts +238 -0
- package/packages/consent/consent-tools/src/domain/get-initialized-analytics.ts +25 -0
- package/packages/consent/consent-tools/src/domain/load-cancellation.ts +31 -0
- package/packages/consent/consent-tools/src/domain/validation/__tests__/options-validators.test.ts +77 -0
- package/packages/consent/consent-tools/src/domain/validation/__tests__/validation-error.test.ts +15 -0
- package/packages/consent/consent-tools/src/domain/validation/common-validators.ts +19 -0
- package/packages/consent/consent-tools/src/domain/validation/index.ts +1 -0
- package/packages/consent/consent-tools/src/domain/validation/options-validators.ts +74 -0
- package/packages/consent/consent-tools/src/domain/validation/validation-error.ts +11 -0
- package/packages/consent/consent-tools/src/index.ts +16 -0
- package/packages/consent/consent-tools/src/types/errors.ts +14 -0
- package/packages/consent/consent-tools/src/types/index.ts +3 -0
- package/packages/consent/consent-tools/src/types/settings.ts +121 -0
- package/packages/consent/consent-tools/src/types/wrapper.ts +107 -0
- package/packages/consent/consent-tools/src/utils/index.ts +4 -0
- package/packages/consent/consent-tools/src/utils/pick.ts +18 -0
- package/packages/consent/consent-tools/src/utils/pipe.ts +14 -0
- package/packages/consent/consent-tools/src/utils/resolve-when.ts +32 -0
- package/packages/consent/consent-tools/src/utils/uniq.ts +4 -0
- package/packages/consent/consent-tools/tsconfig.build.json +9 -0
- package/packages/consent/consent-tools/tsconfig.json +12 -0
- package/packages/consent/consent-wrapper-onetrust/.eslintrc.js +7 -0
- package/packages/consent/consent-wrapper-onetrust/.lintstagedrc.js +1 -0
- package/packages/consent/consent-wrapper-onetrust/LICENSE +45 -0
- package/packages/consent/consent-wrapper-onetrust/README.md +125 -0
- package/packages/consent/consent-wrapper-onetrust/img/onetrust-cat-id.jpg +0 -0
- package/packages/consent/consent-wrapper-onetrust/img/onetrust-popup.jpg +0 -0
- package/packages/consent/consent-wrapper-onetrust/jest.config.js +6 -0
- package/packages/consent/consent-wrapper-onetrust/jest.setup.js +4 -0
- package/packages/consent/consent-wrapper-onetrust/package.json +60 -0
- package/packages/consent/consent-wrapper-onetrust/src/domain/__tests__/wrapper.test.ts +151 -0
- package/packages/consent/consent-wrapper-onetrust/src/domain/wrapper.ts +61 -0
- package/packages/consent/consent-wrapper-onetrust/src/index.ts +6 -0
- package/packages/consent/consent-wrapper-onetrust/src/index.umd.ts +11 -0
- package/packages/consent/consent-wrapper-onetrust/src/lib/__tests__/onetrust-api.test.ts +181 -0
- package/packages/consent/consent-wrapper-onetrust/src/lib/onetrust-api.ts +155 -0
- package/packages/consent/consent-wrapper-onetrust/src/lib/validation/index.ts +1 -0
- package/packages/consent/consent-wrapper-onetrust/src/lib/validation/onetrust-api-error.ts +11 -0
- package/packages/consent/consent-wrapper-onetrust/src/test-helpers/mocks.ts +23 -0
- package/packages/consent/consent-wrapper-onetrust/src/test-helpers/onetrust-globals.d.ts +11 -0
- package/packages/consent/consent-wrapper-onetrust/src/test-helpers/utils.ts +3 -0
- package/packages/consent/consent-wrapper-onetrust/tsconfig.build.json +9 -0
- package/packages/consent/consent-wrapper-onetrust/tsconfig.json +11 -0
- package/packages/consent/consent-wrapper-onetrust/webpack.config.js +25 -0
- package/packages/core/.eslintrc.js +4 -0
- package/packages/core/.lintstagedrc.js +1 -0
- package/packages/core/LICENSE.MD +45 -0
- package/packages/core/README.md +3 -0
- package/packages/core/jest.config.js +5 -0
- package/packages/core/jest.setup.js +10 -0
- package/packages/core/package.json +40 -0
- package/packages/core/src/analytics/__tests__/dispatch.test.ts +95 -0
- package/packages/core/src/analytics/dispatch.ts +58 -0
- package/packages/core/src/analytics/index.ts +11 -0
- package/packages/core/src/callback/__tests__/index.test.ts +85 -0
- package/packages/core/src/callback/index.ts +51 -0
- package/packages/core/src/context/index.ts +123 -0
- package/packages/core/src/emitter/__tests__/emitter.test.ts +74 -0
- package/packages/core/src/emitter/index.ts +65 -0
- package/packages/core/src/emitter/interface.ts +31 -0
- package/packages/core/src/events/__tests__/index.test.ts +394 -0
- package/packages/core/src/events/index.ts +280 -0
- package/packages/core/src/events/interfaces.ts +475 -0
- package/packages/core/src/index.ts +19 -0
- package/packages/core/src/logger/__tests__/index.test.ts +66 -0
- package/packages/core/src/logger/index.ts +74 -0
- package/packages/core/src/plugins/index.ts +43 -0
- package/packages/core/src/priority-queue/__tests__/backoff.test.ts +23 -0
- package/packages/core/src/priority-queue/__tests__/index.test.ts +158 -0
- package/packages/core/src/priority-queue/backoff.ts +24 -0
- package/packages/core/src/priority-queue/index.ts +103 -0
- package/packages/core/src/queue/__tests__/event-queue.test.ts +678 -0
- package/packages/core/src/queue/__tests__/extension-flushing.test.ts +416 -0
- package/packages/core/src/queue/delivery.ts +73 -0
- package/packages/core/src/queue/event-queue.ts +318 -0
- package/packages/core/src/stats/__tests__/index.test.ts +103 -0
- package/packages/core/src/stats/index.ts +88 -0
- package/packages/core/src/task/__tests__/task-group.test.ts +26 -0
- package/packages/core/src/task/task-group.ts +31 -0
- package/packages/core/src/user/index.ts +7 -0
- package/packages/core/src/utils/__tests__/group-by.test.ts +96 -0
- package/packages/core/src/utils/__tests__/is-plain-object.test.ts +27 -0
- package/packages/core/src/utils/__tests__/is-thenable.test.ts +39 -0
- package/packages/core/src/utils/bind-all.ts +19 -0
- package/packages/core/src/utils/get-global.ts +17 -0
- package/packages/core/src/utils/group-by.ts +30 -0
- package/packages/core/src/utils/has-properties.ts +7 -0
- package/packages/core/src/utils/is-plain-object.ts +26 -0
- package/packages/core/src/utils/is-thenable.ts +9 -0
- package/packages/core/src/utils/p-while.ts +12 -0
- package/packages/core/src/utils/pick.ts +8 -0
- package/packages/core/src/utils/ts-helpers.ts +13 -0
- package/packages/core/src/validation/__tests__/assertions.test.ts +155 -0
- package/packages/core/src/validation/assertions.ts +72 -0
- package/packages/core/src/validation/errors.ts +8 -0
- package/packages/core/src/validation/helpers.ts +23 -0
- package/packages/core/test-helpers/index.ts +2 -0
- package/packages/core/test-helpers/test-ctx.ts +7 -0
- package/packages/core/test-helpers/test-event-queue.ts +7 -0
- package/packages/core/tsconfig.build.json +9 -0
- package/packages/core/tsconfig.json +11 -0
- package/packages/node/.eslintrc.js +7 -0
- package/packages/node/.lintstagedrc.js +1 -0
- package/packages/node/LICENSE +45 -0
- package/packages/node/README.md +138 -0
- package/packages/node/jest.config.js +5 -0
- package/packages/node/jest.setup.js +4 -0
- package/packages/node/package.json +50 -0
- package/packages/node/scripts/version.sh +11 -0
- package/packages/node/src/__tests__/callback.test.ts +47 -0
- package/packages/node/src/__tests__/disable.integration.test.ts +42 -0
- package/packages/node/src/__tests__/emitter.integration.test.ts +45 -0
- package/packages/node/src/__tests__/graceful-shutdown-integration.test.ts +244 -0
- package/packages/node/src/__tests__/http-client.integration.test.ts +69 -0
- package/packages/node/src/__tests__/http-integration.test.ts +362 -0
- package/packages/node/src/__tests__/integration.test.ts +357 -0
- package/packages/node/src/__tests__/plugins.test.ts +16 -0
- package/packages/node/src/__tests__/settings.test.ts +9 -0
- package/packages/node/src/__tests__/test-helpers/assert-shape/http-request-event.ts +13 -0
- package/packages/node/src/__tests__/test-helpers/assert-shape/index.ts +2 -0
- package/packages/node/src/__tests__/test-helpers/assert-shape/segment-http-api.ts +43 -0
- package/packages/node/src/__tests__/test-helpers/create-test-analytics.ts +42 -0
- package/packages/node/src/__tests__/test-helpers/factories.ts +17 -0
- package/packages/node/src/__tests__/test-helpers/is-valid-date.ts +6 -0
- package/packages/node/src/__tests__/test-helpers/resolve-ctx.ts +19 -0
- package/packages/node/src/__tests__/test-helpers/resolve-emitter.ts +11 -0
- package/packages/node/src/__tests__/test-helpers/sleep.ts +3 -0
- package/packages/node/src/__tests__/test-helpers/test-plugin.ts +16 -0
- package/packages/node/src/__tests__/typedef-tests.ts +120 -0
- package/packages/node/src/app/analytics-node.ts +299 -0
- package/packages/node/src/app/context.ts +11 -0
- package/packages/node/src/app/dispatch-emit.ts +42 -0
- package/packages/node/src/app/emitter.ts +23 -0
- package/packages/node/src/app/event-factory.ts +20 -0
- package/packages/node/src/app/event-queue.ts +23 -0
- package/packages/node/src/app/settings.ts +49 -0
- package/packages/node/src/app/types/index.ts +3 -0
- package/packages/node/src/app/types/params.ts +76 -0
- package/packages/node/src/app/types/plugin.ts +5 -0
- package/packages/node/src/app/types/segment-event.ts +7 -0
- package/packages/node/src/generated/version.ts +2 -0
- package/packages/node/src/index.ts +26 -0
- package/packages/node/src/lib/__tests__/abort.test.ts +54 -0
- package/packages/node/src/lib/__tests__/create-url.test.ts +35 -0
- package/packages/node/src/lib/__tests__/env.test.ts +52 -0
- package/packages/node/src/lib/__tests__/get-message-id.test.ts +21 -0
- package/packages/node/src/lib/abort.ts +77 -0
- package/packages/node/src/lib/base-64-encode.ts +8 -0
- package/packages/node/src/lib/create-url.ts +11 -0
- package/packages/node/src/lib/env.ts +45 -0
- package/packages/node/src/lib/extract-promise-parts.ts +21 -0
- package/packages/node/src/lib/fetch.ts +16 -0
- package/packages/node/src/lib/get-message-id.ts +10 -0
- package/packages/node/src/lib/http-client.ts +95 -0
- package/packages/node/src/lib/uuid.ts +1 -0
- package/packages/node/src/plugins/segmentio/__tests__/methods.test.ts +223 -0
- package/packages/node/src/plugins/segmentio/__tests__/publisher.test.ts +411 -0
- package/packages/node/src/plugins/segmentio/context-batch.ts +71 -0
- package/packages/node/src/plugins/segmentio/index.ts +66 -0
- package/packages/node/src/plugins/segmentio/publisher.ts +265 -0
- package/packages/node/tsconfig.build.json +9 -0
- package/packages/node/tsconfig.json +10 -0
- package/packages/test-helpers/.eslintrc.js +7 -0
- package/packages/test-helpers/.lintstagedrc.js +1 -0
- package/packages/test-helpers/jest.config.js +3 -0
- package/packages/test-helpers/package.json +26 -0
- package/packages/test-helpers/src/analytics/cdn-settings-builder.ts +79 -0
- package/packages/test-helpers/src/analytics/index.ts +1 -0
- package/packages/test-helpers/src/index.ts +2 -0
- package/packages/test-helpers/src/utils/index.ts +1 -0
- package/packages/test-helpers/src/utils/sleep.ts +4 -0
- package/packages/test-helpers/tsconfig.build.json +9 -0
- package/packages/test-helpers/tsconfig.json +11 -0
- package/tsconfig.json +21 -0
- package/turbo.json +39 -0
- package/typings/get-monorepo-packages.d.ts +9 -0
- package/typings/spawn.d.ts +10 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { CoreAnalytics, bindAll, pTimeout } from '@ht-sdks/events-sdk-js-core'
|
|
2
|
+
import { AnalyticsSettings, validateSettings } from './settings'
|
|
3
|
+
import { version } from '../generated/version'
|
|
4
|
+
import { createConfiguredNodePlugin } from '../plugins/segmentio'
|
|
5
|
+
import { NodeEventFactory } from './event-factory'
|
|
6
|
+
import { Callback, dispatchAndEmit } from './dispatch-emit'
|
|
7
|
+
import { NodeEmitter } from './emitter'
|
|
8
|
+
import {
|
|
9
|
+
AliasParams,
|
|
10
|
+
GroupParams,
|
|
11
|
+
IdentifyParams,
|
|
12
|
+
PageParams,
|
|
13
|
+
TrackParams,
|
|
14
|
+
Plugin,
|
|
15
|
+
HightouchEvent,
|
|
16
|
+
} from './types'
|
|
17
|
+
import { Context } from './context'
|
|
18
|
+
import { NodeEventQueue } from './event-queue'
|
|
19
|
+
import { FetchHTTPClient } from '../lib/http-client'
|
|
20
|
+
|
|
21
|
+
export class Analytics extends NodeEmitter implements CoreAnalytics {
|
|
22
|
+
private readonly _eventFactory: NodeEventFactory
|
|
23
|
+
private _isClosed = false
|
|
24
|
+
private _pendingEvents = 0
|
|
25
|
+
private readonly _closeAndFlushDefaultTimeout: number
|
|
26
|
+
private readonly _publisher: ReturnType<
|
|
27
|
+
typeof createConfiguredNodePlugin
|
|
28
|
+
>['publisher']
|
|
29
|
+
|
|
30
|
+
private readonly _queue: NodeEventQueue
|
|
31
|
+
|
|
32
|
+
ready: Promise<void>
|
|
33
|
+
|
|
34
|
+
constructor(settings: AnalyticsSettings) {
|
|
35
|
+
super()
|
|
36
|
+
validateSettings(settings)
|
|
37
|
+
|
|
38
|
+
this._eventFactory = new NodeEventFactory()
|
|
39
|
+
this._queue = new NodeEventQueue()
|
|
40
|
+
|
|
41
|
+
const flushInterval = settings.flushInterval ?? 10000
|
|
42
|
+
|
|
43
|
+
this._closeAndFlushDefaultTimeout = flushInterval * 1.25 // add arbitrary multiplier in case an event is in a plugin.
|
|
44
|
+
|
|
45
|
+
const { plugin, publisher } = createConfiguredNodePlugin(
|
|
46
|
+
{
|
|
47
|
+
writeKey: settings.writeKey,
|
|
48
|
+
host: settings.host,
|
|
49
|
+
path: settings.path,
|
|
50
|
+
maxRetries: settings.maxRetries ?? 3,
|
|
51
|
+
maxEventsInBatch: settings.maxEventsInBatch ?? 15,
|
|
52
|
+
httpRequestTimeout: settings.httpRequestTimeout,
|
|
53
|
+
disable: settings.disable,
|
|
54
|
+
flushInterval,
|
|
55
|
+
httpClient:
|
|
56
|
+
typeof settings.httpClient === 'function'
|
|
57
|
+
? new FetchHTTPClient(settings.httpClient)
|
|
58
|
+
: settings.httpClient ?? new FetchHTTPClient(),
|
|
59
|
+
},
|
|
60
|
+
this as NodeEmitter
|
|
61
|
+
)
|
|
62
|
+
this._publisher = publisher
|
|
63
|
+
this.ready = this.register(plugin).then(() => undefined)
|
|
64
|
+
|
|
65
|
+
this.emit('initialize', settings)
|
|
66
|
+
|
|
67
|
+
bindAll(this)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get VERSION() {
|
|
71
|
+
return version
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Call this method to stop collecting new events and flush all existing events.
|
|
76
|
+
* This method also waits for any event method-specific callbacks to be triggered,
|
|
77
|
+
* and any of their subsequent promises to be resolved/rejected.
|
|
78
|
+
*/
|
|
79
|
+
public closeAndFlush({
|
|
80
|
+
timeout = this._closeAndFlushDefaultTimeout,
|
|
81
|
+
}: {
|
|
82
|
+
/** Set a maximum time permitted to wait before resolving. */
|
|
83
|
+
timeout?: number
|
|
84
|
+
} = {}): Promise<void> {
|
|
85
|
+
this._publisher.flushAfterClose(this._pendingEvents)
|
|
86
|
+
this._isClosed = true
|
|
87
|
+
const promise = new Promise<void>((resolve) => {
|
|
88
|
+
if (!this._pendingEvents) {
|
|
89
|
+
resolve()
|
|
90
|
+
} else {
|
|
91
|
+
this.once('drained', () => resolve())
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
return timeout ? pTimeout(promise, timeout).catch(() => undefined) : promise
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private _dispatch(segmentEvent: HightouchEvent, callback?: Callback) {
|
|
98
|
+
if (this._isClosed) {
|
|
99
|
+
this.emit('call_after_close', segmentEvent as HightouchEvent)
|
|
100
|
+
return undefined
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this._pendingEvents++
|
|
104
|
+
|
|
105
|
+
dispatchAndEmit(segmentEvent, this._queue, this, callback)
|
|
106
|
+
.catch((ctx) => ctx)
|
|
107
|
+
.finally(() => {
|
|
108
|
+
this._pendingEvents--
|
|
109
|
+
|
|
110
|
+
if (!this._pendingEvents) {
|
|
111
|
+
this.emit('drained')
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Combines two unassociated user identities.
|
|
118
|
+
*/
|
|
119
|
+
alias(
|
|
120
|
+
{ userId, previousId, context, timestamp, integrations }: AliasParams,
|
|
121
|
+
callback?: Callback
|
|
122
|
+
): void {
|
|
123
|
+
const segmentEvent = this._eventFactory.alias(userId, previousId, {
|
|
124
|
+
context,
|
|
125
|
+
integrations,
|
|
126
|
+
timestamp,
|
|
127
|
+
})
|
|
128
|
+
this._dispatch(segmentEvent, callback)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Associates an identified user with a collective.
|
|
133
|
+
*/
|
|
134
|
+
group(
|
|
135
|
+
{
|
|
136
|
+
timestamp,
|
|
137
|
+
groupId,
|
|
138
|
+
userId,
|
|
139
|
+
anonymousId,
|
|
140
|
+
traits = {},
|
|
141
|
+
context,
|
|
142
|
+
integrations,
|
|
143
|
+
}: GroupParams,
|
|
144
|
+
callback?: Callback
|
|
145
|
+
): void {
|
|
146
|
+
const segmentEvent = this._eventFactory.group(groupId, traits, {
|
|
147
|
+
context,
|
|
148
|
+
anonymousId,
|
|
149
|
+
userId,
|
|
150
|
+
timestamp,
|
|
151
|
+
integrations,
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
this._dispatch(segmentEvent, callback)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Includes a unique userId and (maybe anonymousId) and any optional traits you know about them.
|
|
159
|
+
*/
|
|
160
|
+
identify(
|
|
161
|
+
{
|
|
162
|
+
userId,
|
|
163
|
+
anonymousId,
|
|
164
|
+
traits = {},
|
|
165
|
+
context,
|
|
166
|
+
timestamp,
|
|
167
|
+
integrations,
|
|
168
|
+
}: IdentifyParams,
|
|
169
|
+
callback?: Callback
|
|
170
|
+
): void {
|
|
171
|
+
const segmentEvent = this._eventFactory.identify(userId, traits, {
|
|
172
|
+
context,
|
|
173
|
+
anonymousId,
|
|
174
|
+
userId,
|
|
175
|
+
timestamp,
|
|
176
|
+
integrations,
|
|
177
|
+
})
|
|
178
|
+
this._dispatch(segmentEvent, callback)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* The page method lets you record page views on your website, along with optional extra information about the page being viewed.
|
|
183
|
+
*/
|
|
184
|
+
page(
|
|
185
|
+
{
|
|
186
|
+
userId,
|
|
187
|
+
anonymousId,
|
|
188
|
+
category,
|
|
189
|
+
name,
|
|
190
|
+
properties,
|
|
191
|
+
context,
|
|
192
|
+
timestamp,
|
|
193
|
+
integrations,
|
|
194
|
+
}: PageParams,
|
|
195
|
+
callback?: Callback
|
|
196
|
+
): void {
|
|
197
|
+
const segmentEvent = this._eventFactory.page(
|
|
198
|
+
category ?? null,
|
|
199
|
+
name ?? null,
|
|
200
|
+
properties,
|
|
201
|
+
{ context, anonymousId, userId, timestamp, integrations }
|
|
202
|
+
)
|
|
203
|
+
this._dispatch(segmentEvent, callback)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Records screen views on your app, along with optional extra information
|
|
208
|
+
* about the screen viewed by the user.
|
|
209
|
+
*
|
|
210
|
+
* TODO: This is not documented on the segment docs ATM (for node).
|
|
211
|
+
*/
|
|
212
|
+
screen(
|
|
213
|
+
{
|
|
214
|
+
userId,
|
|
215
|
+
anonymousId,
|
|
216
|
+
category,
|
|
217
|
+
name,
|
|
218
|
+
properties,
|
|
219
|
+
context,
|
|
220
|
+
timestamp,
|
|
221
|
+
integrations,
|
|
222
|
+
}: PageParams,
|
|
223
|
+
callback?: Callback
|
|
224
|
+
): void {
|
|
225
|
+
const segmentEvent = this._eventFactory.screen(
|
|
226
|
+
category ?? null,
|
|
227
|
+
name ?? null,
|
|
228
|
+
properties,
|
|
229
|
+
{ context, anonymousId, userId, timestamp, integrations }
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
this._dispatch(segmentEvent, callback)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Records actions your users perform.
|
|
237
|
+
*/
|
|
238
|
+
track(
|
|
239
|
+
{
|
|
240
|
+
userId,
|
|
241
|
+
anonymousId,
|
|
242
|
+
event,
|
|
243
|
+
properties,
|
|
244
|
+
context,
|
|
245
|
+
timestamp,
|
|
246
|
+
integrations,
|
|
247
|
+
}: TrackParams,
|
|
248
|
+
callback?: Callback
|
|
249
|
+
): void {
|
|
250
|
+
const segmentEvent = this._eventFactory.track(event, properties, {
|
|
251
|
+
context,
|
|
252
|
+
userId,
|
|
253
|
+
anonymousId,
|
|
254
|
+
timestamp,
|
|
255
|
+
integrations,
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
this._dispatch(segmentEvent, callback)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Registers one or more plugins to augment Analytics functionality.
|
|
263
|
+
* @param plugins
|
|
264
|
+
*/
|
|
265
|
+
register(...plugins: Plugin[]): Promise<void> {
|
|
266
|
+
return this._queue.criticalTasks.run(async () => {
|
|
267
|
+
const ctx = Context.system()
|
|
268
|
+
|
|
269
|
+
const registrations = plugins.map((xt) =>
|
|
270
|
+
this._queue.register(ctx, xt, this)
|
|
271
|
+
)
|
|
272
|
+
await Promise.all(registrations)
|
|
273
|
+
this.emit(
|
|
274
|
+
'register',
|
|
275
|
+
plugins.map((el) => el.name)
|
|
276
|
+
)
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Deregisters one or more plugins based on their names.
|
|
282
|
+
* @param pluginNames - The names of one or more plugins to deregister.
|
|
283
|
+
*/
|
|
284
|
+
async deregister(...pluginNames: string[]): Promise<void> {
|
|
285
|
+
const ctx = Context.system()
|
|
286
|
+
|
|
287
|
+
const deregistrations = pluginNames.map((pl) => {
|
|
288
|
+
const plugin = this._queue.plugins.find((p) => p.name === pl)
|
|
289
|
+
if (plugin) {
|
|
290
|
+
return this._queue.deregister(ctx, plugin, this)
|
|
291
|
+
} else {
|
|
292
|
+
ctx.log('warn', `plugin ${pl} not found`)
|
|
293
|
+
}
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
await Promise.all(deregistrations)
|
|
297
|
+
this.emit('deregister', pluginNames)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// create a derived class since we may want to add node specific things to Context later
|
|
2
|
+
|
|
3
|
+
import { CoreContext } from '@ht-sdks/events-sdk-js-core'
|
|
4
|
+
import { HightouchEvent } from './types'
|
|
5
|
+
|
|
6
|
+
// While this is not a type, it is a definition
|
|
7
|
+
export class Context extends CoreContext<HightouchEvent> {
|
|
8
|
+
static override system() {
|
|
9
|
+
return new this({ type: 'track', event: 'system' })
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { dispatch } from '@ht-sdks/events-sdk-js-core'
|
|
2
|
+
import type { NodeEmitter } from './emitter'
|
|
3
|
+
import { Context } from './context'
|
|
4
|
+
import { NodeEventQueue } from './event-queue'
|
|
5
|
+
import { HightouchEvent } from './types'
|
|
6
|
+
|
|
7
|
+
export type Callback = (err?: unknown, ctx?: Context) => void
|
|
8
|
+
|
|
9
|
+
const normalizeDispatchCb = (cb: Callback) => (ctx: Context) => {
|
|
10
|
+
const failedDelivery = ctx.failedDelivery()
|
|
11
|
+
return failedDelivery ? cb(failedDelivery.reason, ctx) : cb(undefined, ctx)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* Dispatch function, but swallow promise rejections and use event emitter instead */
|
|
15
|
+
export const dispatchAndEmit = async (
|
|
16
|
+
event: HightouchEvent,
|
|
17
|
+
queue: NodeEventQueue,
|
|
18
|
+
emitter: NodeEmitter,
|
|
19
|
+
callback?: Callback
|
|
20
|
+
): Promise<void> => {
|
|
21
|
+
try {
|
|
22
|
+
const context = new Context(event)
|
|
23
|
+
const ctx = await dispatch(context, queue, emitter, {
|
|
24
|
+
...(callback ? { callback: normalizeDispatchCb(callback) } : {}),
|
|
25
|
+
})
|
|
26
|
+
const failedDelivery = ctx.failedDelivery()
|
|
27
|
+
if (failedDelivery) {
|
|
28
|
+
emitter.emit('error', {
|
|
29
|
+
code: 'delivery_failure',
|
|
30
|
+
reason: failedDelivery.reason,
|
|
31
|
+
ctx: ctx,
|
|
32
|
+
})
|
|
33
|
+
} else {
|
|
34
|
+
emitter.emit(event.type, ctx)
|
|
35
|
+
}
|
|
36
|
+
} catch (err) {
|
|
37
|
+
emitter.emit('error', {
|
|
38
|
+
code: 'unknown',
|
|
39
|
+
reason: err,
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CoreEmitterContract, Emitter } from '@ht-sdks/events-sdk-js-core'
|
|
2
|
+
import { Context } from './context'
|
|
3
|
+
import type { AnalyticsSettings } from './settings'
|
|
4
|
+
import { HightouchEvent } from './types'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Map of emitter event names to method args.
|
|
8
|
+
*/
|
|
9
|
+
export type NodeEmitterEvents = CoreEmitterContract<Context> & {
|
|
10
|
+
initialize: [AnalyticsSettings]
|
|
11
|
+
call_after_close: [HightouchEvent] // any event that did not get dispatched due to close
|
|
12
|
+
http_request: [
|
|
13
|
+
{
|
|
14
|
+
url: string
|
|
15
|
+
method: string
|
|
16
|
+
headers: Record<string, string>
|
|
17
|
+
body: Record<string, any>
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
drained: []
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class NodeEmitter extends Emitter<NodeEmitterEvents> {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EventFactory } from '@ht-sdks/events-sdk-js-core'
|
|
2
|
+
import { createMessageId } from '../lib/get-message-id'
|
|
3
|
+
import { HightouchEvent } from './types'
|
|
4
|
+
|
|
5
|
+
// use declaration merging to downcast CoreHightouchEvent without adding any runtime code.
|
|
6
|
+
// if/when we decide to add an actual implementation to NodeEventFactory that actually changes the event shape, we can remove this.
|
|
7
|
+
export interface NodeEventFactory {
|
|
8
|
+
alias(...args: Parameters<EventFactory['alias']>): HightouchEvent
|
|
9
|
+
group(...args: Parameters<EventFactory['group']>): HightouchEvent
|
|
10
|
+
identify(...args: Parameters<EventFactory['identify']>): HightouchEvent
|
|
11
|
+
track(...args: Parameters<EventFactory['track']>): HightouchEvent
|
|
12
|
+
page(...args: Parameters<EventFactory['page']>): HightouchEvent
|
|
13
|
+
screen(...args: Parameters<EventFactory['screen']>): HightouchEvent
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class NodeEventFactory extends EventFactory {
|
|
17
|
+
constructor() {
|
|
18
|
+
super({ createMessageId })
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CoreEventQueue, PriorityQueue } from '@ht-sdks/events-sdk-js-core'
|
|
2
|
+
import type { Plugin } from '../app/types'
|
|
3
|
+
import type { Context } from './context'
|
|
4
|
+
|
|
5
|
+
class NodePriorityQueue extends PriorityQueue<Context> {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(1, [])
|
|
8
|
+
}
|
|
9
|
+
// do not use an internal "seen" map
|
|
10
|
+
getAttempts(ctx: Context): number {
|
|
11
|
+
return ctx.attempts ?? 0
|
|
12
|
+
}
|
|
13
|
+
updateAttempts(ctx: Context): number {
|
|
14
|
+
ctx.attempts = this.getAttempts(ctx) + 1
|
|
15
|
+
return this.getAttempts(ctx)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class NodeEventQueue extends CoreEventQueue<Context, Plugin> {
|
|
20
|
+
constructor() {
|
|
21
|
+
super(new NodePriorityQueue())
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ValidationError } from '@ht-sdks/events-sdk-js-core'
|
|
2
|
+
import { HTTPClient, HTTPFetchFn } from '../lib/http-client'
|
|
3
|
+
|
|
4
|
+
export interface AnalyticsSettings {
|
|
5
|
+
/**
|
|
6
|
+
* Key that corresponds to your Hightouch.io project
|
|
7
|
+
*/
|
|
8
|
+
writeKey: string
|
|
9
|
+
/**
|
|
10
|
+
* The base URL of the API. Default: "https://us-east-1.hightouch-events.com"
|
|
11
|
+
*/
|
|
12
|
+
host?: string
|
|
13
|
+
/**
|
|
14
|
+
* The API path route. Default: "/v1/batch"
|
|
15
|
+
*/
|
|
16
|
+
path?: string
|
|
17
|
+
/**
|
|
18
|
+
* The number of times to retry flushing a batch. Default: 3
|
|
19
|
+
*/
|
|
20
|
+
maxRetries?: number
|
|
21
|
+
/**
|
|
22
|
+
* The number of messages to enqueue before flushing. Default: 15
|
|
23
|
+
*/
|
|
24
|
+
maxEventsInBatch?: number
|
|
25
|
+
/**
|
|
26
|
+
* The number of milliseconds to wait before flushing the queue automatically. Default: 10000
|
|
27
|
+
*/
|
|
28
|
+
flushInterval?: number
|
|
29
|
+
/**
|
|
30
|
+
* The maximum number of milliseconds to wait for an http request. Default: 10000
|
|
31
|
+
*/
|
|
32
|
+
httpRequestTimeout?: number
|
|
33
|
+
/**
|
|
34
|
+
* Disable the analytics library. All calls will be a noop. Default: false.
|
|
35
|
+
*/
|
|
36
|
+
disable?: boolean
|
|
37
|
+
/**
|
|
38
|
+
* Supply a default http client implementation (such as one supporting proxy).
|
|
39
|
+
* Accepts either an HTTPClient instance or a fetch function.
|
|
40
|
+
* Default: an HTTP client that uses globalThis.fetch, with node-fetch as a fallback.
|
|
41
|
+
*/
|
|
42
|
+
httpClient?: HTTPFetchFn | HTTPClient
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const validateSettings = (settings: AnalyticsSettings) => {
|
|
46
|
+
if (!settings.writeKey) {
|
|
47
|
+
throw new ValidationError('writeKey', 'writeKey is missing.')
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
GroupTraits,
|
|
3
|
+
UserTraits,
|
|
4
|
+
CoreExtraContext,
|
|
5
|
+
EventProperties,
|
|
6
|
+
Integrations,
|
|
7
|
+
Timestamp,
|
|
8
|
+
} from '@ht-sdks/events-sdk-js-core'
|
|
9
|
+
|
|
10
|
+
export type { GroupTraits, UserTraits }
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A dictionary of extra context to attach to the call.
|
|
14
|
+
* Note: context differs from traits because it is not attributes of the user itself.
|
|
15
|
+
*/
|
|
16
|
+
export interface ExtraContext extends CoreExtraContext {}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* An ID associated with the user. Note: at least one of userId or anonymousId must be included.
|
|
20
|
+
**/
|
|
21
|
+
type IdentityOptions =
|
|
22
|
+
| { userId: string; anonymousId?: string }
|
|
23
|
+
| { userId?: string; anonymousId: string }
|
|
24
|
+
|
|
25
|
+
export type AliasParams = {
|
|
26
|
+
/* The new user id you want to associate with the user. */
|
|
27
|
+
userId: string
|
|
28
|
+
/* The previous id that the user was recognized by (this can be either a userId or an anonymousId). */
|
|
29
|
+
previousId: string
|
|
30
|
+
context?: ExtraContext
|
|
31
|
+
timestamp?: Timestamp
|
|
32
|
+
integrations?: Integrations
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type GroupParams = {
|
|
36
|
+
groupId: string
|
|
37
|
+
/**
|
|
38
|
+
* Traits are pieces of information you know about a group.
|
|
39
|
+
* This interface represents reserved traits that Hightouch has standardized.
|
|
40
|
+
*/
|
|
41
|
+
traits?: GroupTraits
|
|
42
|
+
context?: ExtraContext
|
|
43
|
+
timestamp?: Timestamp
|
|
44
|
+
integrations?: Integrations
|
|
45
|
+
} & IdentityOptions
|
|
46
|
+
|
|
47
|
+
export type IdentifyParams = {
|
|
48
|
+
/**
|
|
49
|
+
* Traits are pieces of information you know about a group.
|
|
50
|
+
* This interface represents reserved traits that Hightouch has standardized.
|
|
51
|
+
*/
|
|
52
|
+
traits?: UserTraits
|
|
53
|
+
context?: ExtraContext
|
|
54
|
+
timestamp?: Timestamp
|
|
55
|
+
integrations?: Integrations
|
|
56
|
+
} & IdentityOptions
|
|
57
|
+
|
|
58
|
+
export type PageParams = {
|
|
59
|
+
/* The category of the page. Useful for cases like ecommerce where many pages might live under a single category. */
|
|
60
|
+
category?: string
|
|
61
|
+
/* The name of the page.*/
|
|
62
|
+
name?: string
|
|
63
|
+
/* A dictionary of properties of the page. */
|
|
64
|
+
properties?: EventProperties
|
|
65
|
+
timestamp?: Timestamp
|
|
66
|
+
context?: ExtraContext
|
|
67
|
+
integrations?: Integrations
|
|
68
|
+
} & IdentityOptions
|
|
69
|
+
|
|
70
|
+
export type TrackParams = {
|
|
71
|
+
event: string
|
|
72
|
+
properties?: EventProperties
|
|
73
|
+
context?: ExtraContext
|
|
74
|
+
timestamp?: Timestamp
|
|
75
|
+
integrations?: Integrations
|
|
76
|
+
} & IdentityOptions
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export { Analytics } from './app/analytics-node'
|
|
2
|
+
export { Context } from './app/context'
|
|
3
|
+
export {
|
|
4
|
+
HTTPClient,
|
|
5
|
+
FetchHTTPClient,
|
|
6
|
+
HTTPFetchRequest,
|
|
7
|
+
HTTPResponse,
|
|
8
|
+
HTTPFetchFn,
|
|
9
|
+
HTTPClientRequest,
|
|
10
|
+
} from './lib/http-client'
|
|
11
|
+
|
|
12
|
+
export type {
|
|
13
|
+
Plugin,
|
|
14
|
+
GroupTraits,
|
|
15
|
+
UserTraits,
|
|
16
|
+
TrackParams,
|
|
17
|
+
IdentifyParams,
|
|
18
|
+
AliasParams,
|
|
19
|
+
GroupParams,
|
|
20
|
+
PageParams,
|
|
21
|
+
} from './app/types'
|
|
22
|
+
export type { AnalyticsSettings } from './app/settings'
|
|
23
|
+
|
|
24
|
+
// export Analytics as both a named export and a default export (for backwards-compat. reasons)
|
|
25
|
+
import { Analytics } from './app/analytics-node'
|
|
26
|
+
export default Analytics
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { abortSignalAfterTimeout } from '../abort'
|
|
2
|
+
import nock from 'nock'
|
|
3
|
+
import { sleep } from '@ht-sdks/events-sdk-js-core'
|
|
4
|
+
import { fetch as _fetch } from '../fetch'
|
|
5
|
+
|
|
6
|
+
const fetch = _fetch as typeof globalThis.fetch
|
|
7
|
+
|
|
8
|
+
describe(abortSignalAfterTimeout, () => {
|
|
9
|
+
const HOST = 'https://foo.com'
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
nock.cleanAll()
|
|
12
|
+
})
|
|
13
|
+
it('should not abort operation if timeout has not expired', async () => {
|
|
14
|
+
jest.useRealTimers()
|
|
15
|
+
nock(HOST).get('/').reply(201)
|
|
16
|
+
try {
|
|
17
|
+
const [signal] = abortSignalAfterTimeout(1000)
|
|
18
|
+
await fetch(HOST, { signal })
|
|
19
|
+
} catch (err: any) {
|
|
20
|
+
throw Error('fail')
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should abort operation if timeout expires', async () => {
|
|
25
|
+
jest.useFakeTimers()
|
|
26
|
+
nock(HOST)
|
|
27
|
+
.get('/')
|
|
28
|
+
.reply(201, async () => {
|
|
29
|
+
await sleep(10000)
|
|
30
|
+
return true
|
|
31
|
+
})
|
|
32
|
+
try {
|
|
33
|
+
const [signal] = abortSignalAfterTimeout(2000)
|
|
34
|
+
jest.advanceTimersByTime(6000)
|
|
35
|
+
await fetch(HOST, { signal })
|
|
36
|
+
throw Error('fail test.')
|
|
37
|
+
} catch (err: any) {
|
|
38
|
+
expect(err.name).toMatch('AbortError')
|
|
39
|
+
expect(err.message).toMatch('The user aborted a request')
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
it('should abort operation immediately if timeout is 0', async () => {
|
|
43
|
+
jest.useRealTimers()
|
|
44
|
+
nock(HOST).get('/').reply(201)
|
|
45
|
+
const [signal] = abortSignalAfterTimeout(0)
|
|
46
|
+
try {
|
|
47
|
+
await fetch(HOST, { signal })
|
|
48
|
+
throw Error('fail test.')
|
|
49
|
+
} catch (err: any) {
|
|
50
|
+
expect(err.name).toMatch('AbortError')
|
|
51
|
+
expect(err.message).toMatch('The user aborted a request')
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { tryCreateFormattedUrl } from '../create-url'
|
|
2
|
+
|
|
3
|
+
describe(tryCreateFormattedUrl, () => {
|
|
4
|
+
it('should create a valid url', () => {
|
|
5
|
+
expect(tryCreateFormattedUrl('http://foo.com', '/bar')).toBe(
|
|
6
|
+
'http://foo.com/bar'
|
|
7
|
+
)
|
|
8
|
+
})
|
|
9
|
+
it('should work if the path has many', () => {
|
|
10
|
+
expect(tryCreateFormattedUrl('http://foo.com', '/bar/baz')).toBe(
|
|
11
|
+
'http://foo.com/bar/baz'
|
|
12
|
+
)
|
|
13
|
+
})
|
|
14
|
+
it('should ignore slashes', () => {
|
|
15
|
+
const result = 'http://foo.com/bar'
|
|
16
|
+
expect(tryCreateFormattedUrl('http://foo.com/', '/bar')).toBe(result)
|
|
17
|
+
expect(tryCreateFormattedUrl('http://foo.com', 'bar')).toBe(result)
|
|
18
|
+
expect(tryCreateFormattedUrl('http://foo.com', '/bar')).toBe(result)
|
|
19
|
+
})
|
|
20
|
+
it('should throw if no http', () => {
|
|
21
|
+
expect(() => tryCreateFormattedUrl('foo.com', '/bar')).toThrowError()
|
|
22
|
+
})
|
|
23
|
+
it('should throw if no url', () => {
|
|
24
|
+
expect(() => tryCreateFormattedUrl('', '/bar')).toThrowError()
|
|
25
|
+
})
|
|
26
|
+
it('should not require .com', () => {
|
|
27
|
+
expect(tryCreateFormattedUrl('http://foo', 'bar')).toBe('http://foo/bar')
|
|
28
|
+
})
|
|
29
|
+
it('should strip the trailing slash if path is', () => {
|
|
30
|
+
expect(tryCreateFormattedUrl('http://foo.com/')).toBe('http://foo.com')
|
|
31
|
+
expect(tryCreateFormattedUrl('http://foo.com/', 'bar/')).toBe(
|
|
32
|
+
'http://foo.com/bar'
|
|
33
|
+
)
|
|
34
|
+
})
|
|
35
|
+
})
|