From bd32975ffb7b2db64ed2052f78caf89359eb3f0d Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 19:10:33 -0700 Subject: [PATCH 01/17] feat: add authentication failure and retry policy enums and types --- src/core/enums/IterableAuthFailureReason.ts | 39 +++++++++++++++++++++ src/core/enums/IterableRetryBackoff.ts | 15 ++++++++ src/core/enums/index.ts | 2 ++ src/core/types/IterableAuthFailure.ts | 18 ++++++++++ src/core/types/IterableRetryPolicy.ts | 16 +++++++++ src/core/types/index.ts | 3 ++ 6 files changed, 93 insertions(+) create mode 100644 src/core/enums/IterableAuthFailureReason.ts create mode 100644 src/core/enums/IterableRetryBackoff.ts create mode 100644 src/core/types/IterableAuthFailure.ts create mode 100644 src/core/types/IterableRetryPolicy.ts diff --git a/src/core/enums/IterableAuthFailureReason.ts b/src/core/enums/IterableAuthFailureReason.ts new file mode 100644 index 000000000..a61f7fa7e --- /dev/null +++ b/src/core/enums/IterableAuthFailureReason.ts @@ -0,0 +1,39 @@ +/** + * The reason for the failure of an authentication attempt. + * + * This is generally related to JWT token validation. + */ +export enum IterableAuthFailureReason { + /** + * An auth token's expiration must be less than one year from its issued-at + * time. + */ + AUTH_TOKEN_EXPIRATION_INVALID, + /** The token has expired. */ + AUTH_TOKEN_EXPIRED, + /** Token has an invalid format (failed a regular expression check). */ + AUTH_TOKEN_FORMAT_INVALID, + /** `onAuthTokenRequested` threw an exception. */ + AUTH_TOKEN_GENERATION_ERROR, + /** Any other error not captured by another constant. */ + AUTH_TOKEN_GENERIC_ERROR, + /** Iterable has invalidated this token and it cannot be used. */ + AUTH_TOKEN_INVALIDATED, + /** The request to Iterable's API did not include a JWT authorization header. */ + AUTH_TOKEN_MISSING, + /** `onAuthTokenRequested` returned a null JWT token. */ + AUTH_TOKEN_NULL, + /** + * Iterable could not decode the token's payload (`iat`, `exp`, `email`, + * or `userId`). + */ + AUTH_TOKEN_PAYLOAD_INVALID, + /** Iterable could not validate the token's authenticity. */ + AUTH_TOKEN_SIGNATURE_INVALID, + /** + * The token doesn't include an `email` or a `userId`. Or, one of these + * values is included, but it references a user that isn't in the Iterable + * project. + */ + AUTH_TOKEN_USER_KEY_INVALID, +} diff --git a/src/core/enums/IterableRetryBackoff.ts b/src/core/enums/IterableRetryBackoff.ts new file mode 100644 index 000000000..4afcf9046 --- /dev/null +++ b/src/core/enums/IterableRetryBackoff.ts @@ -0,0 +1,15 @@ +/** + * The type of backoff to use when retrying a request. + */ +export enum IterableRetryBackoff { + /** + * Linear backoff (each retry will wait for a fixed interval) + * TODO: check with @Ayyanchira if this is correct + */ + LINEAR = 'LINEAR', + /** + * Exponential backoff (each retry will wait for an interval that increases exponentially) + * TODO: check with @Ayyanchira if this is correct + */ + EXPONENTIAL = 'EXPONENTIAL', +} diff --git a/src/core/enums/index.ts b/src/core/enums/index.ts index e95b5350c..52f4eb20d 100644 --- a/src/core/enums/index.ts +++ b/src/core/enums/index.ts @@ -1,6 +1,8 @@ export * from './IterableActionSource'; +export * from './IterableAuthFailureReason'; export * from './IterableAuthResponseResult'; export * from './IterableDataRegion'; export * from './IterableEventName'; export * from './IterableLogLevel'; export * from './IterablePushPlatform'; +export * from './IterableRetryBackoff'; diff --git a/src/core/types/IterableAuthFailure.ts b/src/core/types/IterableAuthFailure.ts new file mode 100644 index 000000000..0f2d1cf5e --- /dev/null +++ b/src/core/types/IterableAuthFailure.ts @@ -0,0 +1,18 @@ +import type { IterableAuthFailureReason } from "../enums/IterableAuthFailureReason"; + +/** + * The details of an auth failure. + */ +export interface IterableAuthFailure { + /** `userId` or `email` of the signed-in user */ + userKey: string; + + /** The `authToken` which caused the failure */ + failedAuthToken: string; + + /** The timestamp of the failed request */ + failedRequestTime: number; + + /** Indicates a reason for failure */ + failureReason: IterableAuthFailureReason; +} diff --git a/src/core/types/IterableRetryPolicy.ts b/src/core/types/IterableRetryPolicy.ts new file mode 100644 index 000000000..318b705a0 --- /dev/null +++ b/src/core/types/IterableRetryPolicy.ts @@ -0,0 +1,16 @@ +import type { IterableRetryBackoff } from "../enums/IterableRetryBackoff"; + +/** + * The policy for retrying an authentication attempt. + */ +export interface IterableRetryPolicy { + /** Number of consecutive JWT refresh retries the SDK should attempt */ + maxRetry: number; + /** + * Duration between JWT refresh retries in seconds + * (starting point for retry backoff) + */ + retryInterval: number; + /** The backoff pattern to apply between retry attempts. */ + retryBackoff: IterableRetryBackoff; +} diff --git a/src/core/types/index.ts b/src/core/types/index.ts index f5d846482..9f5c58fd0 100644 --- a/src/core/types/index.ts +++ b/src/core/types/index.ts @@ -1 +1,4 @@ +export * from './IterableAuthFailure'; export * from './IterableEdgeInsetDetails'; +export * from './IterableRetryPolicy'; + From 50ef0e6e8a130748371cea22af0630e92f6ae38c Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 19:29:52 -0700 Subject: [PATCH 02/17] chore: update eslint-config-prettier and add prettier-eslint dependency --- package.json | 3 +- yarn.lock | 245 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 229 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index eed044283..2b18c052c 100644 --- a/package.json +++ b/package.json @@ -84,12 +84,13 @@ "commitlint": "^19.6.1", "del-cli": "^5.1.0", "eslint": "^8.51.0", - "eslint-config-prettier": "^9.0.0", + "eslint-config-prettier": "^10.1.8", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-tsdoc": "^0.3.0", "jest": "^29.7.0", "prettier": "^3.0.3", + "prettier-eslint": "^16.4.2", "react": "19.0.0", "react-native": "0.79.3", "react-native-builder-bob": "^0.40.4", diff --git a/yarn.lock b/yarn.lock index 5e6aee08c..a65a65936 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1974,12 +1974,13 @@ __metadata: commitlint: ^19.6.1 del-cli: ^5.1.0 eslint: ^8.51.0 - eslint-config-prettier: ^9.0.0 + eslint-config-prettier: ^10.1.8 eslint-plugin-jest: ^28.9.0 eslint-plugin-prettier: ^5.0.1 eslint-plugin-tsdoc: ^0.3.0 jest: ^29.7.0 prettier: ^3.0.3 + prettier-eslint: ^16.4.2 react: 19.0.0 react-native: 0.79.3 react-native-builder-bob: ^0.40.4 @@ -3540,6 +3541,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/parser@npm:^6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/parser@npm:6.21.0" + dependencies: + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + debug: ^4.3.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 162fe3a867eeeffda7328bce32dae45b52283c68c8cb23258fb9f44971f761991af61f71b8c9fe1aa389e93dfe6386f8509c1273d870736c507d76dd40647b68 + languageName: node + linkType: hard + "@typescript-eslint/parser@npm:^7.1.1": version: 7.18.0 resolution: "@typescript-eslint/parser@npm:7.18.0" @@ -3597,6 +3616,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/scope-manager@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + checksum: 71028b757da9694528c4c3294a96cc80bc7d396e383a405eab3bc224cda7341b88e0fc292120b35d3f31f47beac69f7083196c70616434072fbcd3d3e62d3376 + languageName: node + linkType: hard + "@typescript-eslint/scope-manager@npm:7.18.0": version: 7.18.0 resolution: "@typescript-eslint/scope-manager@npm:7.18.0" @@ -3666,6 +3695,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/types@npm:6.21.0" + checksum: 9501b47d7403417af95fc1fb72b2038c5ac46feac0e1598a46bcb43e56a606c387e9dcd8a2a0abe174c91b509f2d2a8078b093786219eb9a01ab2fbf9ee7b684 + languageName: node + linkType: hard + "@typescript-eslint/types@npm:7.18.0": version: 7.18.0 resolution: "@typescript-eslint/types@npm:7.18.0" @@ -3698,6 +3734,25 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + minimatch: 9.0.3 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependenciesMeta: + typescript: + optional: true + checksum: dec02dc107c4a541e14fb0c96148f3764b92117c3b635db3a577b5a56fc48df7a556fa853fb82b07c0663b4bf2c484c9f245c28ba3e17e5cb0918ea4cab2ea21 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:7.18.0": version: 7.18.0 resolution: "@typescript-eslint/typescript-estree@npm:7.18.0" @@ -3794,6 +3849,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + eslint-visitor-keys: ^3.4.1 + checksum: 67c7e6003d5af042d8703d11538fca9d76899f0119130b373402819ae43f0bc90d18656aa7add25a24427ccf1a0efd0804157ba83b0d4e145f06107d7d1b7433 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:7.18.0": version: 7.18.0 resolution: "@typescript-eslint/visitor-keys@npm:7.18.0" @@ -3990,6 +4055,13 @@ __metadata: languageName: node linkType: hard +"ansi-regex@npm:^2.0.0": + version: 2.1.1 + resolution: "ansi-regex@npm:2.1.1" + checksum: 190abd03e4ff86794f338a31795d262c1dfe8c91f7e01d04f13f646f1dcb16c5800818f886047876f1272f065570ab86b24b99089f8b68a0e11ff19aed4ca8f1 + languageName: node + linkType: hard + "ansi-regex@npm:^4.1.0": version: 4.1.1 resolution: "ansi-regex@npm:4.1.1" @@ -4011,6 +4083,13 @@ __metadata: languageName: node linkType: hard +"ansi-styles@npm:^2.2.1": + version: 2.2.1 + resolution: "ansi-styles@npm:2.2.1" + checksum: ebc0e00381f2a29000d1dac8466a640ce11943cef3bda3cd0020dc042e31e1058ab59bf6169cd794a54c3a7338a61ebc404b7c91e004092dd20e028c432c9c2c + languageName: node + linkType: hard + "ansi-styles@npm:^3.2.0": version: 3.2.1 resolution: "ansi-styles@npm:3.2.1" @@ -4726,6 +4805,19 @@ __metadata: languageName: node linkType: hard +"chalk@npm:^1.1.3": + version: 1.1.3 + resolution: "chalk@npm:1.1.3" + dependencies: + ansi-styles: ^2.2.1 + escape-string-regexp: ^1.0.2 + has-ansi: ^2.0.0 + strip-ansi: ^3.0.0 + supports-color: ^2.0.0 + checksum: 9d2ea6b98fc2b7878829eec223abcf404622db6c48396a9b9257f6d0ead2acf18231ae368d6a664a83f272b0679158da12e97b5229f794939e555cc574478acd + languageName: node + linkType: hard + "chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" @@ -5049,6 +5141,13 @@ __metadata: languageName: node linkType: hard +"common-tags@npm:^1.8.2": + version: 1.8.2 + resolution: "common-tags@npm:1.8.2" + checksum: 767a6255a84bbc47df49a60ab583053bb29a7d9687066a18500a516188a062c4e4cd52de341f22de0b07062e699b1b8fe3cfa1cb55b241cb9301aeb4f45b4dff + languageName: node + linkType: hard + "compare-func@npm:^2.0.0": version: 2.0.0 resolution: "compare-func@npm:2.0.0" @@ -5759,6 +5858,13 @@ __metadata: languageName: node linkType: hard +"dlv@npm:^1.1.3": + version: 1.1.3 + resolution: "dlv@npm:1.1.3" + checksum: d7381bca22ed11933a1ccf376db7a94bee2c57aa61e490f680124fa2d1cd27e94eba641d9f45be57caab4f9a6579de0983466f620a2cd6230d7ec93312105ae7 + languageName: node + linkType: hard + "doctrine@npm:^2.1.0": version: 2.1.0 resolution: "doctrine@npm:2.1.0" @@ -6128,7 +6234,7 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:^1.0.5": +"escape-string-regexp@npm:^1.0.2, escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 @@ -6167,25 +6273,25 @@ __metadata: languageName: node linkType: hard -"eslint-config-prettier@npm:^8.5.0": - version: 8.10.2 - resolution: "eslint-config-prettier@npm:8.10.2" +"eslint-config-prettier@npm:^10.1.8": + version: 10.1.8 + resolution: "eslint-config-prettier@npm:10.1.8" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: a92b7e8a996e65adf79de1579524235687e9d3552d088cfab4f170da60d23762addb4276169c8ca3a9551329dda8408c59f7e414101b238a6385379ac1bc3b16 + checksum: 9140e19f78f0dbc888b160bb72b85f8043bada7b12a548faa56cea0ba74f8ef16653250ffd014d85d9a376a88c4941c96a3cdc9d39a07eb3def6967166635bd8 languageName: node linkType: hard -"eslint-config-prettier@npm:^9.0.0": - version: 9.1.2 - resolution: "eslint-config-prettier@npm:9.1.2" +"eslint-config-prettier@npm:^8.5.0": + version: 8.10.2 + resolution: "eslint-config-prettier@npm:8.10.2" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: e786b767331094fd024cb1b0899964a9da0602eaf4ebd617d6d9794752ccd04dbe997e3c14c17f256c97af20bee1c83c9273f69b74cb2081b6f514580d62408f + checksum: a92b7e8a996e65adf79de1579524235687e9d3552d088cfab4f170da60d23762addb4276169c8ca3a9551329dda8408c59f7e414101b238a6385379ac1bc3b16 languageName: node linkType: hard @@ -6345,7 +6451,7 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.2.2": +"eslint-scope@npm:^7.1.1, eslint-scope@npm:^7.2.2": version: 7.2.2 resolution: "eslint-scope@npm:7.2.2" dependencies: @@ -6376,7 +6482,7 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.51.0": +"eslint@npm:^8.51.0, eslint@npm:^8.57.1": version: 8.57.1 resolution: "eslint@npm:8.57.1" dependencies: @@ -6424,7 +6530,7 @@ __metadata: languageName: node linkType: hard -"espree@npm:^9.6.0, espree@npm:^9.6.1": +"espree@npm:^9.3.1, espree@npm:^9.6.0, espree@npm:^9.6.1": version: 9.6.1 resolution: "espree@npm:9.6.1" dependencies: @@ -6445,7 +6551,7 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.2": +"esquery@npm:^1.4.0, esquery@npm:^1.4.2": version: 1.6.0 resolution: "esquery@npm:1.6.0" dependencies: @@ -7260,6 +7366,15 @@ __metadata: languageName: node linkType: hard +"has-ansi@npm:^2.0.0": + version: 2.0.0 + resolution: "has-ansi@npm:2.0.0" + dependencies: + ansi-regex: ^2.0.0 + checksum: 1b51daa0214440db171ff359d0a2d17bc20061164c57e76234f614c91dbd2a79ddd68dfc8ee73629366f7be45a6df5f2ea9de83f52e1ca24433f2cc78c35d8ec + languageName: node + linkType: hard + "has-bigints@npm:^1.0.2": version: 1.1.0 resolution: "has-bigints@npm:1.1.0" @@ -9261,6 +9376,23 @@ __metadata: languageName: node linkType: hard +"loglevel-colored-level-prefix@npm:^1.0.0": + version: 1.0.0 + resolution: "loglevel-colored-level-prefix@npm:1.0.0" + dependencies: + chalk: ^1.1.3 + loglevel: ^1.4.1 + checksum: 146aa7d0ea900d6d8523e945b2265be240e4c7c4752dae678983764dd756c44194684af1ee8ea721feff4c4f8c5771544a02a6cd8b269a663cffe9b4fcf955f1 + languageName: node + linkType: hard + +"loglevel@npm:^1.4.1": + version: 1.9.2 + resolution: "loglevel@npm:1.9.2" + checksum: 896c67b90a507bfcfc1e9a4daa7bf789a441dd70d95cd13b998d6dd46233a3bfadfb8fadb07250432bbfb53bf61e95f2520f9b11f9d3175cc460e5c251eca0af + languageName: node + linkType: hard + "loose-envify@npm:^1.0.0, loose-envify@npm:^1.4.0": version: 1.4.0 resolution: "loose-envify@npm:1.4.0" @@ -10063,6 +10195,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:9.0.3": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: ^2.0.1 + checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 + languageName: node + linkType: hard + "minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -11019,6 +11160,34 @@ __metadata: languageName: node linkType: hard +"prettier-eslint@npm:^16.4.2": + version: 16.4.2 + resolution: "prettier-eslint@npm:16.4.2" + dependencies: + "@typescript-eslint/parser": ^6.21.0 + common-tags: ^1.8.2 + dlv: ^1.1.3 + eslint: ^8.57.1 + indent-string: ^4.0.0 + lodash.merge: ^4.6.2 + loglevel-colored-level-prefix: ^1.0.0 + prettier: ^3.5.3 + pretty-format: ^29.7.0 + require-relative: ^0.8.7 + tslib: ^2.8.1 + vue-eslint-parser: ^9.4.3 + peerDependencies: + prettier-plugin-svelte: ^3.0.0 + svelte-eslint-parser: "*" + peerDependenciesMeta: + prettier-plugin-svelte: + optional: true + svelte-eslint-parser: + optional: true + checksum: ad420f2d3b6f0c055e0eefed2f32876e4ac29d5c0202778ae531438224c7d07b67dcfb64054bc61a0cc88f231988198f229395361a9b2112ad048d08b6d5bc80 + languageName: node + linkType: hard + "prettier-linter-helpers@npm:^1.0.0": version: 1.0.0 resolution: "prettier-linter-helpers@npm:1.0.0" @@ -11028,7 +11197,7 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.0.3": +"prettier@npm:^3.0.3, prettier@npm:^3.5.3": version: 3.6.2 resolution: "prettier@npm:3.6.2" bin: @@ -11847,6 +12016,13 @@ __metadata: languageName: node linkType: hard +"require-relative@npm:^0.8.7": + version: 0.8.7 + resolution: "require-relative@npm:0.8.7" + checksum: f1c3be06977823bba43600344d9ea6fbf8a55bdb81ec76533126849ab4024e6c31c6666f37fa4b5cfeda9c41dee89b8e19597cac02bdefaab42255c6708661ab + languageName: node + linkType: hard + "reselect@npm:^4.1.7": version: 4.1.8 resolution: "reselect@npm:4.1.8" @@ -12107,7 +12283,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.1.3, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": +"semver@npm:^7.1.3, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.6, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": version: 7.7.2 resolution: "semver@npm:7.7.2" bin: @@ -12721,6 +12897,15 @@ __metadata: languageName: node linkType: hard +"strip-ansi@npm:^3.0.0": + version: 3.0.1 + resolution: "strip-ansi@npm:3.0.1" + dependencies: + ansi-regex: ^2.0.0 + checksum: 9b974de611ce5075c70629c00fa98c46144043db92ae17748fb780f706f7a789e9989fd10597b7c2053ae8d1513fd707816a91f1879b2f71e6ac0b6a863db465 + languageName: node + linkType: hard + "strip-ansi@npm:^5.0.0": version: 5.2.0 resolution: "strip-ansi@npm:5.2.0" @@ -12804,6 +12989,13 @@ __metadata: languageName: node linkType: hard +"supports-color@npm:^2.0.0": + version: 2.0.0 + resolution: "supports-color@npm:2.0.0" + checksum: 602538c5812b9006404370b5a4b885d3e2a1f6567d314f8b4a41974ffe7d08e525bf92ae0f9c7030e3b4c78e4e34ace55d6a67a74f1571bc205959f5972f88f0 + languageName: node + linkType: hard + "supports-color@npm:^7.1.0": version: 7.2.0 resolution: "supports-color@npm:7.2.0" @@ -12977,7 +13169,7 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^1.3.0": +"ts-api-utils@npm:^1.0.1, ts-api-utils@npm:^1.3.0": version: 1.4.3 resolution: "ts-api-utils@npm:1.4.3" peerDependencies: @@ -13002,7 +13194,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.1, tslib@npm:^2.1.0": +"tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.8.1": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: e4aba30e632b8c8902b47587fd13345e2827fa639e7c3121074d5ee0880723282411a8838f830b55100cbe4517672f84a2472667d355b81e8af165a55dc6203a @@ -13585,6 +13777,23 @@ __metadata: languageName: node linkType: hard +"vue-eslint-parser@npm:^9.4.3": + version: 9.4.3 + resolution: "vue-eslint-parser@npm:9.4.3" + dependencies: + debug: ^4.3.4 + eslint-scope: ^7.1.1 + eslint-visitor-keys: ^3.3.0 + espree: ^9.3.1 + esquery: ^1.4.0 + lodash: ^4.17.21 + semver: ^7.3.6 + peerDependencies: + eslint: ">=6.0.0" + checksum: 8d5b7ef7c5ee264ca2ba78da4b95ac7a66175a458d153a35e92cd7c55b794db0f2c31a8fdd40021bab4496f2f64ab80d7dbb6dccff4103beb4564c439a88fa42 + languageName: node + linkType: hard + "walker@npm:^1.0.7, walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" From af0065ee69bb563b9b57d5e35c75c5a32ed7c243 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 19:31:24 -0700 Subject: [PATCH 03/17] feat: export new authentication and retry policy types in index files --- src/core/types/index.ts | 1 - src/index.tsx | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/types/index.ts b/src/core/types/index.ts index 9f5c58fd0..7659a76e4 100644 --- a/src/core/types/index.ts +++ b/src/core/types/index.ts @@ -1,4 +1,3 @@ export * from './IterableAuthFailure'; export * from './IterableEdgeInsetDetails'; export * from './IterableRetryPolicy'; - diff --git a/src/index.tsx b/src/index.tsx index 885cd74bd..240ac51f5 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -14,17 +14,24 @@ export { } from './core/classes'; export { IterableActionSource, + IterableAuthFailureReason, + IterableAuthResponseResult, IterableDataRegion, IterableEventName, IterableLogLevel, IterablePushPlatform, + IterableRetryBackoff, } from './core/enums'; export { useAppStateListener, useDeviceOrientation, type IterableDeviceOrientation, } from './core/hooks'; -export { type IterableEdgeInsetDetails } from './core/types'; +export type { + IterableAuthFailure, + IterableEdgeInsetDetails, + IterableRetryPolicy, +} from './core/types'; export { IterableHtmlInAppContent, IterableInAppCloseSource, From 762f3339c6c7320ea656915d39e166e30de9721a Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 19:44:13 -0700 Subject: [PATCH 04/17] feat: enhance IterableConfig with JWT error handling and retry policy support --- src/core/classes/IterableConfig.ts | 39 ++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/core/classes/IterableConfig.ts b/src/core/classes/IterableConfig.ts index 1c0550b0c..8961e49f8 100644 --- a/src/core/classes/IterableConfig.ts +++ b/src/core/classes/IterableConfig.ts @@ -1,10 +1,10 @@ import { type IterableInAppMessage } from '../../inApp/classes/IterableInAppMessage'; -import { IterableInAppShowResponse } from '../../inApp/enums'; -import { - IterableDataRegion, - IterableLogLevel, - IterablePushPlatform, -} from '../enums'; +import { IterableInAppShowResponse } from '../../inApp/enums/IterableInAppShowResponse'; +import { IterableDataRegion } from '../enums/IterableDataRegion'; +import { IterableLogLevel } from '../enums/IterableLogLevel'; +import { IterablePushPlatform } from '../enums/IterablePushPlatform'; +import type { IterableAuthFailure } from '../types/IterableAuthFailure'; +import type { IterableRetryPolicy } from '../types/IterableRetryPolicy'; import { IterableAction } from './IterableAction'; import type { IterableActionContext } from './IterableActionContext'; import type { IterableAuthResponse } from './IterableAuthResponse'; @@ -204,7 +204,27 @@ export class IterableConfig { * @returns A promise that resolves to an `IterableAuthResponse`, a `string`, * or `undefined`. */ - authHandler?: () => Promise; + authHandler?: () => Promise< + IterableAuthResponse | IterableAuthFailure | string | undefined + >; + + /** + * A callback function which is called when an error occurs while validating a JWT. + * + * The retry for JWT should be automatically handled by the native SDK, so + * this is just for logging/transparency purposes. + * + * @param authFailure - The details of the auth failure. + * + * @example + * ```typescript + * const config = new IterableConfig(); + * config.onJWTError = (authFailure) => { + * console.error('Error fetching JWT:', authFailure); + * }; + * ``` + */ + onJWTError?: (authFailure: IterableAuthFailure) => void; /** * Set the verbosity of Android and iOS project's log system. @@ -213,6 +233,11 @@ export class IterableConfig { */ logLevel: IterableLogLevel = IterableLogLevel.info; + /** + * The retry policy to use when retrying a request. + */ + retryPolicy?: IterableRetryPolicy; + /** * Set whether the React Native SDK should print function calls to console. * From cfe1de275f8c99611506812b380eac57a1a500e2 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 19:58:10 -0700 Subject: [PATCH 05/17] feat: add onAuthFailure and pauseAuthRetries methods to Iterable class --- src/api/NativeRNIterableAPI.ts | 2 + src/core/classes/Iterable.ts | 106 ++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 36 deletions(-) diff --git a/src/api/NativeRNIterableAPI.ts b/src/api/NativeRNIterableAPI.ts index de903cece..dd6921367 100644 --- a/src/api/NativeRNIterableAPI.ts +++ b/src/api/NativeRNIterableAPI.ts @@ -116,6 +116,8 @@ export interface Spec extends TurboModule { // Auth passAlongAuthToken(authToken?: string | null): void; + onAuthFailure(authFailure: { userKey: string; failedAuthToken: string; failedRequestTime: number; failureReason: string }): void; + pauseAuthRetries(pauseRetry: boolean): void; // Wake app -- android only wakeApp(): void; diff --git a/src/core/classes/Iterable.ts b/src/core/classes/Iterable.ts index e9572f69c..60221f5b6 100644 --- a/src/core/classes/Iterable.ts +++ b/src/core/classes/Iterable.ts @@ -1,8 +1,4 @@ -import { - Linking, - NativeEventEmitter, - Platform, -} from 'react-native'; +import { Linking, NativeEventEmitter, Platform } from 'react-native'; import { buildInfo } from '../../itblBuildInfo'; @@ -13,7 +9,8 @@ import { IterableInAppMessage } from '../../inApp/classes/IterableInAppMessage'; import { IterableInAppCloseSource } from '../../inApp/enums/IterableInAppCloseSource'; import { IterableInAppDeleteSource } from '../../inApp/enums/IterableInAppDeleteSource'; import { IterableInAppLocation } from '../../inApp/enums/IterableInAppLocation'; -import { IterableAuthResponseResult, IterableEventName } from '../enums'; +import { IterableAuthResponseResult } from '../enums/IterableAuthResponseResult'; +import { IterableEventName } from '../enums/IterableEventName'; // Add this type-only import to avoid circular dependency import type { IterableInAppManager } from '../../inApp/classes/IterableInAppManager'; @@ -25,6 +22,7 @@ import { IterableAuthResponse } from './IterableAuthResponse'; import type { IterableCommerceItem } from './IterableCommerceItem'; import { IterableConfig } from './IterableConfig'; import { IterableLogger } from './IterableLogger'; +import type { IterableAuthFailure } from '../types/IterableAuthFailure'; const RNEventEmitter = new NativeEventEmitter(RNIterableAPI); @@ -79,8 +77,11 @@ export class Iterable { // Lazy initialization to avoid circular dependency if (!this._inAppManager) { // Import here to avoid circular dependency at module level - // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-require-imports - const { IterableInAppManager } = require('../../inApp/classes/IterableInAppManager'); + + const { + IterableInAppManager, + // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-require-imports + } = require('../../inApp/classes/IterableInAppManager'); this._inAppManager = new IterableInAppManager(); } return this._inAppManager; @@ -357,7 +358,13 @@ export class Iterable { Iterable?.logger?.log('getAttributionInfo'); return RNIterableAPI.getAttributionInfo().then( - (dict: { campaignId: number; templateId: number; messageId: string } | null) => { + ( + dict: { + campaignId: number; + templateId: number; + messageId: string; + } | null + ) => { if (dict) { return new IterableAttributionInfo( dict.campaignId as number, @@ -398,7 +405,11 @@ export class Iterable { static setAttributionInfo(attributionInfo?: IterableAttributionInfo) { Iterable?.logger?.log('setAttributionInfo'); - RNIterableAPI.setAttributionInfo(attributionInfo as unknown as { [key: string]: string | number | boolean; } | null); + RNIterableAPI.setAttributionInfo( + attributionInfo as unknown as { + [key: string]: string | number | boolean; + } | null + ); } /** @@ -477,7 +488,9 @@ export class Iterable { static updateCart(items: IterableCommerceItem[]) { Iterable?.logger?.log('updateCart'); - RNIterableAPI.updateCart(items as unknown as { [key: string]: string | number | boolean }[]); + RNIterableAPI.updateCart( + items as unknown as { [key: string]: string | number | boolean }[] + ); } /** @@ -529,7 +542,11 @@ export class Iterable { ) { Iterable?.logger?.log('trackPurchase'); - RNIterableAPI.trackPurchase(total, items as unknown as { [key: string]: string | number | boolean }[], dataFields as { [key: string]: string | number | boolean } | undefined); + RNIterableAPI.trackPurchase( + total, + items as unknown as { [key: string]: string | number | boolean }[], + dataFields as { [key: string]: string | number | boolean } | undefined + ); } /** @@ -698,7 +715,10 @@ export class Iterable { static trackEvent(name: string, dataFields?: unknown) { Iterable?.logger?.log('trackEvent'); - RNIterableAPI.trackEvent(name, dataFields as { [key: string]: string | number | boolean } | undefined); + RNIterableAPI.trackEvent( + name, + dataFields as { [key: string]: string | number | boolean } | undefined + ); } /** @@ -746,7 +766,10 @@ export class Iterable { ) { Iterable?.logger?.log('updateUser'); - RNIterableAPI.updateUser(dataFields as { [key: string]: string | number | boolean }, mergeNestedObjects); + RNIterableAPI.updateUser( + dataFields as { [key: string]: string | number | boolean }, + mergeNestedObjects + ); } /** @@ -911,34 +934,45 @@ export class Iterable { } /** - * Sets up event handlers for various Iterable events. + * A callback function that is called when an authentication failure occurs. * - * This method performs the following actions: - * - Removes all existing listeners to avoid duplicate listeners. - * - Adds listeners for URL handling, custom actions, in-app messages, and authentication. + * @param authFailure - The auth failure details * - * Event Handlers: - * - `handleUrlCalled`: Invokes the URL handler if configured, with a delay on Android to allow the activity to wake up. - * - `handleCustomActionCalled`: Invokes the custom action handler if configured. - * - `handleInAppCalled`: Invokes the in-app handler if configured and sets the in-app show response. - * - `handleAuthCalled`: Invokes the authentication handler if configured and handles the promise result. - * - `handleAuthSuccessCalled`: Sets the authentication response callback to success. - * - `handleAuthFailureCalled`: Sets the authentication response callback to failure. + * @example + * ```typescript + * Iterable.onAuthFailure({ + * userKey: '1234567890', + * failedAuthToken: '1234567890', + * failedRequestTime: 1234567890, + * failureReason: IterableAuthFailureReason.AUTH_TOKEN_EXPIRED, + * }); + * ``` + */ + static onAuthFailure(authFailure: IterableAuthFailure) { + Iterable?.logger?.log('onAuthFailure'); + + RNIterableAPI.onAuthFailure(authFailure); + } + + /** + * Pause the authentication retry mechanism. * - * Helper Functions: - * - `callUrlHandler`: Calls the URL handler and attempts to open the URL if the handler returns false. + * @param pauseRetry - Whether to pause the authentication retry mechanism * - * @internal + * @example + * ```typescript + * Iterable.pauseAuthRetries(true); + * ``` */ - private static setupEventHandlers() { - //Remove all listeners to avoid duplicate listeners - RNEventEmitter.removeAllListeners(IterableEventName.handleUrlCalled); - RNEventEmitter.removeAllListeners(IterableEventName.handleInAppCalled); - RNEventEmitter.removeAllListeners( - IterableEventName.handleCustomActionCalled - ); - RNEventEmitter.removeAllListeners(IterableEventName.handleAuthCalled); + static pauseAuthRetries(pauseRetry: boolean) { + Iterable?.logger?.log('pauseAuthRetries'); + + RNIterableAPI.pauseAuthRetries(pauseRetry); + } + /** * @internal + */ + private static setupEventHandlers() { if (Iterable.savedConfig.urlHandler) { RNEventEmitter.addListener(IterableEventName.handleUrlCalled, (dict) => { const url = dict.url; From 7fde4e759330e348ad759d7437214f299ba78887 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 20:01:46 -0700 Subject: [PATCH 06/17] feat: implement retry policy and JWT error handling in IterableAppProvider --- example/src/hooks/useIterableApp.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/example/src/hooks/useIterableApp.tsx b/example/src/hooks/useIterableApp.tsx index 32270003c..f19daef5d 100644 --- a/example/src/hooks/useIterableApp.tsx +++ b/example/src/hooks/useIterableApp.tsx @@ -14,6 +14,7 @@ import { IterableConfig, IterableInAppShowResponse, IterableLogLevel, + IterableRetryBackoff, } from '@iterable/react-native-sdk'; import { Route } from '../constants/routes'; @@ -96,7 +97,9 @@ export const IterableAppProvider: FunctionComponent< const [apiKey, setApiKey] = useState( process.env.ITBL_API_KEY ); - const [userId, setUserId] = useState(process.env.ITBL_ID ?? null); + const [userId, setUserId] = useState( + process.env.ITBL_ID ?? null + ); const [loginInProgress, setLoginInProgress] = useState(false); const getUserId = useCallback(() => userId ?? process.env.ITBL_ID, [userId]); @@ -124,6 +127,16 @@ export const IterableAppProvider: FunctionComponent< config.inAppDisplayInterval = 1.0; // Min gap between in-apps. No need to set this in production. + config.retryPolicy = { + maxRetry: 5, + retryInterval: 10, + retryBackoff: IterableRetryBackoff.LINEAR, + }; + + config.onJWTError = (authFailure) => { + console.error('Error fetching JWT:', authFailure); + }; + config.urlHandler = (url: string) => { const routeNames = [Route.Commerce, Route.Inbox, Route.User]; for (const route of routeNames) { From 5810a0ab7f5500f98dd3dffcef58ccc84f6e533f Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 20:58:19 -0700 Subject: [PATCH 07/17] feat: improve JWT error handling and enhance IterableConfig with additional flags --- src/core/classes/Iterable.ts | 12 ++++++++++-- src/core/classes/IterableConfig.ts | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/core/classes/Iterable.ts b/src/core/classes/Iterable.ts index 60221f5b6..a297b5be1 100644 --- a/src/core/classes/Iterable.ts +++ b/src/core/classes/Iterable.ts @@ -1017,7 +1017,7 @@ export class Iterable { let authResponseCallback: IterableAuthResponseResult; RNEventEmitter.addListener(IterableEventName.handleAuthCalled, () => { // MOB-10423: Check if we can use chain operator (?.) here instead - + // Asks frontend of the client/app to pass authToken Iterable.savedConfig.authHandler!() .then((promiseResult) => { // Promise result can be either just String OR of type AuthResponse. @@ -1038,6 +1038,8 @@ export class Iterable { } else if ( authResponseCallback === IterableAuthResponseResult.FAILURE ) { + // We are currently only reporting JWT related errors. In + // the future, we should handle other types of errors as well. if ((promiseResult as IterableAuthResponse).failureCallback) { (promiseResult as IterableAuthResponse).failureCallback?.(); } @@ -1067,8 +1069,14 @@ export class Iterable { ); RNEventEmitter.addListener( IterableEventName.handleAuthFailureCalled, - () => { + (authFailureResponse: IterableAuthFailure) => { + // Mark the flag for above listener to indicate something failed. + // `catch(err)` will only indicate failure on high level. No actions + // should be taken inside `catch(err)`. authResponseCallback = IterableAuthResponseResult.FAILURE; + + // Call the actual JWT error with `authFailure` object. + Iterable.savedConfig?.onJWTError?.(authFailureResponse); } ); } diff --git a/src/core/classes/IterableConfig.ts b/src/core/classes/IterableConfig.ts index 8961e49f8..c45558ac0 100644 --- a/src/core/classes/IterableConfig.ts +++ b/src/core/classes/IterableConfig.ts @@ -209,7 +209,8 @@ export class IterableConfig { >; /** - * A callback function which is called when an error occurs while validating a JWT. + * A callback function that is called when the SDK encounters an error while + * validing the JWT. * * The retry for JWT should be automatically handled by the native SDK, so * this is just for logging/transparency purposes. @@ -234,7 +235,8 @@ export class IterableConfig { logLevel: IterableLogLevel = IterableLogLevel.info; /** - * The retry policy to use when retrying a request. + * Configuration for JWT refresh retry behavior. + * If not specified, the SDK will use default retry behavior. */ retryPolicy?: IterableRetryPolicy; @@ -357,6 +359,13 @@ export class IterableConfig { */ // eslint-disable-next-line eqeqeq authHandlerPresent: this.authHandler != undefined, + /** + * A boolean indicating if an onJWTError handler is present. + * + * TODO: Figure out if this is purposeful + */ + // eslint-disable-next-line eqeqeq + onJWTErrorPresent: this.onJWTError != undefined, /** The log level for the SDK. */ logLevel: this.logLevel, expiringAuthTokenRefreshPeriod: this.expiringAuthTokenRefreshPeriod, @@ -367,6 +376,7 @@ export class IterableConfig { dataRegion: this.dataRegion, pushPlatform: this.pushPlatform, encryptionEnforced: this.encryptionEnforced, + retryPolicy: this.retryPolicy, }; } } From e85d660b9532a587e35647d7477044f18f528c27 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 21:27:08 -0700 Subject: [PATCH 08/17] refactor: remove onAuthFailure method and update event handler setup in Iterable class --- src/api/NativeRNIterableAPI.ts | 2 -- src/core/classes/Iterable.ts | 49 +++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/api/NativeRNIterableAPI.ts b/src/api/NativeRNIterableAPI.ts index dd6921367..391fadbb7 100644 --- a/src/api/NativeRNIterableAPI.ts +++ b/src/api/NativeRNIterableAPI.ts @@ -116,13 +116,11 @@ export interface Spec extends TurboModule { // Auth passAlongAuthToken(authToken?: string | null): void; - onAuthFailure(authFailure: { userKey: string; failedAuthToken: string; failedRequestTime: number; failureReason: string }): void; pauseAuthRetries(pauseRetry: boolean): void; // Wake app -- android only wakeApp(): void; - // REQUIRED for RCTEventEmitter addListener(eventName: string): void; removeListeners(count: number): void; diff --git a/src/core/classes/Iterable.ts b/src/core/classes/Iterable.ts index a297b5be1..440f65e25 100644 --- a/src/core/classes/Iterable.ts +++ b/src/core/classes/Iterable.ts @@ -933,27 +933,6 @@ export class Iterable { ); } - /** - * A callback function that is called when an authentication failure occurs. - * - * @param authFailure - The auth failure details - * - * @example - * ```typescript - * Iterable.onAuthFailure({ - * userKey: '1234567890', - * failedAuthToken: '1234567890', - * failedRequestTime: 1234567890, - * failureReason: IterableAuthFailureReason.AUTH_TOKEN_EXPIRED, - * }); - * ``` - */ - static onAuthFailure(authFailure: IterableAuthFailure) { - Iterable?.logger?.log('onAuthFailure'); - - RNIterableAPI.onAuthFailure(authFailure); - } - /** * Pause the authentication retry mechanism. * @@ -970,9 +949,35 @@ export class Iterable { RNIterableAPI.pauseAuthRetries(pauseRetry); } - /** * @internal + /** + * Sets up event handlers for various Iterable events. + * + * This method performs the following actions: + * - Removes all existing listeners to avoid duplicate listeners. + * - Adds listeners for URL handling, custom actions, in-app messages, and authentication. + * + * Event Handlers: + * - `handleUrlCalled`: Invokes the URL handler if configured, with a delay on Android to allow the activity to wake up. + * - `handleCustomActionCalled`: Invokes the custom action handler if configured. + * - `handleInAppCalled`: Invokes the in-app handler if configured and sets the in-app show response. + * - `handleAuthCalled`: Invokes the authentication handler if configured and handles the promise result. + * - `handleAuthSuccessCalled`: Sets the authentication response callback to success. + * - `handleAuthFailureCalled`: Sets the authentication response callback to failure. + * + * Helper Functions: + * - `callUrlHandler`: Calls the URL handler and attempts to open the URL if the handler returns false. + * + * @internal */ private static setupEventHandlers() { + // Remove all listeners to avoid duplicate listeners + RNEventEmitter.removeAllListeners(IterableEventName.handleUrlCalled); + RNEventEmitter.removeAllListeners(IterableEventName.handleInAppCalled); + RNEventEmitter.removeAllListeners( + IterableEventName.handleCustomActionCalled + ); + RNEventEmitter.removeAllListeners(IterableEventName.handleAuthCalled); + if (Iterable.savedConfig.urlHandler) { RNEventEmitter.addListener(IterableEventName.handleUrlCalled, (dict) => { const url = dict.url; From c32447fb3f7b93509963031d28fca1cebf8f6259 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 21:32:33 -0700 Subject: [PATCH 09/17] chore: remove unused index.ts file from hooks directory --- src/hooks/index.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/hooks/index.ts diff --git a/src/hooks/index.ts b/src/hooks/index.ts deleted file mode 100644 index e69de29bb..000000000 From 6d8c45ae0fa585dee881b652e17e28dd89f0f1b4 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 21:49:53 -0700 Subject: [PATCH 10/17] refactor: simplify authHandler type and standardize IterableAuthFailureReason enum values --- src/core/classes/IterableConfig.ts | 4 +--- src/core/enums/IterableAuthFailureReason.ts | 22 ++++++++++----------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/core/classes/IterableConfig.ts b/src/core/classes/IterableConfig.ts index c45558ac0..b690cdcb6 100644 --- a/src/core/classes/IterableConfig.ts +++ b/src/core/classes/IterableConfig.ts @@ -204,9 +204,7 @@ export class IterableConfig { * @returns A promise that resolves to an `IterableAuthResponse`, a `string`, * or `undefined`. */ - authHandler?: () => Promise< - IterableAuthResponse | IterableAuthFailure | string | undefined - >; + authHandler?: () => Promise; /** * A callback function that is called when the SDK encounters an error while diff --git a/src/core/enums/IterableAuthFailureReason.ts b/src/core/enums/IterableAuthFailureReason.ts index a61f7fa7e..a86c6f782 100644 --- a/src/core/enums/IterableAuthFailureReason.ts +++ b/src/core/enums/IterableAuthFailureReason.ts @@ -8,32 +8,32 @@ export enum IterableAuthFailureReason { * An auth token's expiration must be less than one year from its issued-at * time. */ - AUTH_TOKEN_EXPIRATION_INVALID, + AUTH_TOKEN_EXPIRATION_INVALID = 'AUTH_TOKEN_EXPIRATION_INVALID', /** The token has expired. */ - AUTH_TOKEN_EXPIRED, + AUTH_TOKEN_EXPIRED = 'AUTH_TOKEN_EXPIRED', /** Token has an invalid format (failed a regular expression check). */ - AUTH_TOKEN_FORMAT_INVALID, + AUTH_TOKEN_FORMAT_INVALID = 'AUTH_TOKEN_FORMAT_INVALID', /** `onAuthTokenRequested` threw an exception. */ - AUTH_TOKEN_GENERATION_ERROR, + AUTH_TOKEN_GENERATION_ERROR = 'AUTH_TOKEN_GENERATION_ERROR', /** Any other error not captured by another constant. */ - AUTH_TOKEN_GENERIC_ERROR, + AUTH_TOKEN_GENERIC_ERROR = 'AUTH_TOKEN_GENERIC_ERROR', /** Iterable has invalidated this token and it cannot be used. */ - AUTH_TOKEN_INVALIDATED, + AUTH_TOKEN_INVALIDATED = 'AUTH_TOKEN_INVALIDATED', /** The request to Iterable's API did not include a JWT authorization header. */ - AUTH_TOKEN_MISSING, + AUTH_TOKEN_MISSING = 'AUTH_TOKEN_MISSING', /** `onAuthTokenRequested` returned a null JWT token. */ - AUTH_TOKEN_NULL, + AUTH_TOKEN_NULL = 'AUTH_TOKEN_NULL', /** * Iterable could not decode the token's payload (`iat`, `exp`, `email`, * or `userId`). */ - AUTH_TOKEN_PAYLOAD_INVALID, + AUTH_TOKEN_PAYLOAD_INVALID = 'AUTH_TOKEN_PAYLOAD_INVALID', /** Iterable could not validate the token's authenticity. */ - AUTH_TOKEN_SIGNATURE_INVALID, + AUTH_TOKEN_SIGNATURE_INVALID = 'AUTH_TOKEN_SIGNATURE_INVALID', /** * The token doesn't include an `email` or a `userId`. Or, one of these * values is included, but it references a user that isn't in the Iterable * project. */ - AUTH_TOKEN_USER_KEY_INVALID, + AUTH_TOKEN_USER_KEY_INVALID = 'AUTH_TOKEN_USER_KEY_INVALID', } From a63b9dce2941ed0dc4d1d8305fc242ea0c87a384 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 6 Oct 2025 22:04:01 -0700 Subject: [PATCH 11/17] refactor: remove onJWTErrorPresent flag from IterableConfig to streamline configuration --- src/core/classes/IterableConfig.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/core/classes/IterableConfig.ts b/src/core/classes/IterableConfig.ts index b690cdcb6..c8ee67400 100644 --- a/src/core/classes/IterableConfig.ts +++ b/src/core/classes/IterableConfig.ts @@ -357,13 +357,6 @@ export class IterableConfig { */ // eslint-disable-next-line eqeqeq authHandlerPresent: this.authHandler != undefined, - /** - * A boolean indicating if an onJWTError handler is present. - * - * TODO: Figure out if this is purposeful - */ - // eslint-disable-next-line eqeqeq - onJWTErrorPresent: this.onJWTError != undefined, /** The log level for the SDK. */ logLevel: this.logLevel, expiringAuthTokenRefreshPeriod: this.expiringAuthTokenRefreshPeriod, From f1d10cba5f6966d93cbd0f6e409deea88a445a0c Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Thu, 9 Oct 2025 04:03:54 -0700 Subject: [PATCH 12/17] chore: update yarn.lock --- yarn.lock | 839 +++++++++++++++++++----------------------------------- 1 file changed, 299 insertions(+), 540 deletions(-) diff --git a/yarn.lock b/yarn.lock index a65a65936..9445d2b60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1797,15 +1797,28 @@ __metadata: linkType: hard "@evilmartians/lefthook@npm:^1.5.0": - version: 1.13.4 - resolution: "@evilmartians/lefthook@npm:1.13.4" + version: 1.13.6 + resolution: "@evilmartians/lefthook@npm:1.13.6" bin: lefthook: bin/index.js - checksum: 287bf75a46bdac72592141a7e56c494eee9de2ea049e7428e39dda6854634e7cc6d76a40f62b1cbc68fc68dd5fa014c37caffd83251f8c222574eeccdd0d1265 + checksum: 6cceca3e874015678f50818ae14a74d959816cfaba6638f8852d007332404d6819b15c71538985a3650a1ef057aa6975c17fadfe43ece7a0da1aeb9faaf02946 conditions: (os=darwin | os=linux | os=win32) & (cpu=x64 | cpu=arm64 | cpu=ia32) languageName: node linkType: hard +"@gerrit0/mini-shiki@npm:^3.12.0": + version: 3.13.0 + resolution: "@gerrit0/mini-shiki@npm:3.13.0" + dependencies: + "@shikijs/engine-oniguruma": ^3.13.0 + "@shikijs/langs": ^3.13.0 + "@shikijs/themes": ^3.13.0 + "@shikijs/types": ^3.13.0 + "@shikijs/vscode-textmate": ^10.0.2 + checksum: 748d28e2dce67fac31cf36e97d849fc2bc60762b98a13c7bb50b6be181656c12ea58c5c6af7955fee99018b53fc9fd72dbf3a0552de7ad5845688b6c03312270 + languageName: node + linkType: hard + "@hapi/hoek@npm:^9.0.0, @hapi/hoek@npm:^9.3.0": version: 9.3.0 resolution: "@hapi/hoek@npm:9.3.0" @@ -1965,7 +1978,7 @@ __metadata: "@react-navigation/native": ^7.1.14 "@release-it/conventional-changelog": ^9.0.4 "@testing-library/jest-native": ^5.4.3 - "@testing-library/react-native": ^12.7.2 + "@testing-library/react-native": ^13.3.3 "@types/jest": ^29.5.5 "@types/react": ^19.0.0 "@types/react-native-vector-icons": ^6.4.18 @@ -1992,7 +2005,7 @@ __metadata: react-test-renderer: 19.0.0 release-it: ^17.10.0 turbo: ^1.10.7 - typedoc: ^0.26.11 + typedoc: ^0.28.13 typedoc-plugin-coverage: ^3.3.0 typedoc-plugin-mermaid: ^1.12.0 typescript: ^5.2.2 @@ -2073,6 +2086,13 @@ __metadata: languageName: node linkType: hard +"@jest/diff-sequences@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/diff-sequences@npm:30.0.1" + checksum: e5f931ca69c15a9b3a9b23b723f51ffc97f031b2f3ca37f901333dab99bd4dfa1ad4192a5cd893cd1272f7602eb09b9cfb5fc6bb62a0232c96fb8b5e96094970 + languageName: node + linkType: hard + "@jest/environment@npm:^29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" @@ -2118,6 +2138,13 @@ __metadata: languageName: node linkType: hard +"@jest/get-type@npm:30.1.0": + version: 30.1.0 + resolution: "@jest/get-type@npm:30.1.0" + checksum: e2a95fbb49ce2d15547db8af5602626caf9b05f62a5e583b4a2de9bd93a2bfe7175f9bbb2b8a5c3909ce261d467b6991d7265bb1d547cb60e7e97f571f361a70 + languageName: node + linkType: hard + "@jest/globals@npm:^29.7.0": version: 29.7.0 resolution: "@jest/globals@npm:29.7.0" @@ -2167,6 +2194,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:30.0.5": + version: 30.0.5 + resolution: "@jest/schemas@npm:30.0.5" + dependencies: + "@sinclair/typebox": ^0.34.0 + checksum: 7a4fc4166f688947c22d81e61aaf2cb22f178dbf6ee806b0931b75136899d426a72a8330762f27f0cf6f79da0d2a56f49a22fe09f5f80df95a683ed237a0f3b0 + languageName: node + linkType: hard + "@jest/schemas@npm:^29.6.3": version: 29.6.3 resolution: "@jest/schemas@npm:29.6.3" @@ -2972,18 +3008,18 @@ __metadata: linkType: hard "@react-navigation/bottom-tabs@npm:^7.0.0": - version: 7.4.7 - resolution: "@react-navigation/bottom-tabs@npm:7.4.7" + version: 7.4.8 + resolution: "@react-navigation/bottom-tabs@npm:7.4.8" dependencies: - "@react-navigation/elements": ^2.6.4 + "@react-navigation/elements": ^2.6.5 color: ^4.2.3 peerDependencies: - "@react-navigation/native": ^7.1.17 + "@react-navigation/native": ^7.1.18 react: ">= 18.2.0" react-native: "*" react-native-safe-area-context: ">= 4.0.0" react-native-screens: ">= 4.0.0" - checksum: 9ff291b086b00d4f656d67fd29b084c7d801c68e8db41c3b18192076d9593e6d4c9d4d28d1bde12be71c0499b6af83331cbe348549c15ff5fa5f8daf42c6bae3 + checksum: b983a9fbb81b88609df1947a310ebc64008eff37421b481c57262bff2dc9e68f116ff44bb7c173ab4ecdb5d0b6dcbb32928d43c9ecdd656bb11e9d97a3089d03 languageName: node linkType: hard @@ -3004,45 +3040,45 @@ __metadata: languageName: node linkType: hard -"@react-navigation/elements@npm:^2.6.4": - version: 2.6.4 - resolution: "@react-navigation/elements@npm:2.6.4" +"@react-navigation/elements@npm:^2.6.5": + version: 2.6.5 + resolution: "@react-navigation/elements@npm:2.6.5" dependencies: color: ^4.2.3 use-latest-callback: ^0.2.4 use-sync-external-store: ^1.5.0 peerDependencies: "@react-native-masked-view/masked-view": ">= 0.2.0" - "@react-navigation/native": ^7.1.17 + "@react-navigation/native": ^7.1.18 react: ">= 18.2.0" react-native: "*" react-native-safe-area-context: ">= 4.0.0" peerDependenciesMeta: "@react-native-masked-view/masked-view": optional: true - checksum: 5ebcf77ca85755efbc35983a32caf6f82371bd8ca7ba705deb4317c250a9a9c1898765d02fe2373adfb2aae852666ac54f07b9185bf1a91fbfe185920ac9c46d + checksum: ed6542b9dfaf04693445bb847651cc6bfdac5c2ffb687c1a5dcc473a05d12cd5e951c3ef5df854978aa93b6ced0bab1bbe94390df10cf24f2e3f9b72688661fb languageName: node linkType: hard "@react-navigation/native-stack@npm:^7.0.0": - version: 7.3.26 - resolution: "@react-navigation/native-stack@npm:7.3.26" + version: 7.3.27 + resolution: "@react-navigation/native-stack@npm:7.3.27" dependencies: - "@react-navigation/elements": ^2.6.4 + "@react-navigation/elements": ^2.6.5 warn-once: ^0.1.1 peerDependencies: - "@react-navigation/native": ^7.1.17 + "@react-navigation/native": ^7.1.18 react: ">= 18.2.0" react-native: "*" react-native-safe-area-context: ">= 4.0.0" react-native-screens: ">= 4.0.0" - checksum: 81146d65c73f731bb40a5df35aa31047077869e9ace2131f6f061795e965892be16dd82bae6c8c7510eee772afe0e1c1374a526663b0e0f0c578effff0c5ef8b + checksum: 7719e78b86e3465a8a51ef302a54c059aa0e7ff38d671c898f71e91265a71843f6fc17ef783ff08e80b00c4f16902cba58f41fdd06efbc735b11a090d7f371d0 languageName: node linkType: hard "@react-navigation/native@npm:^7.1.14": - version: 7.1.17 - resolution: "@react-navigation/native@npm:7.1.17" + version: 7.1.18 + resolution: "@react-navigation/native@npm:7.1.18" dependencies: "@react-navigation/core": ^7.12.4 escape-string-regexp: ^4.0.0 @@ -3052,7 +3088,7 @@ __metadata: peerDependencies: react: ">= 18.2.0" react-native: "*" - checksum: f0caa70f777c32861ce23a834d3afe6891c7829016649bf1491ba6b540fd4443dd6c5e6d8b44f58b92efed6074ea986e04b88ff84e9e19c09d68d9302ebd977a + checksum: c7f0f6ae439a4d74cc7f42fe693aa014acdaaf3205c07cf40448eac5ef0417a307a08da0b8ad79516028182e3377c77332e40697874ceee3bd8ec52be7f8d459 languageName: node linkType: hard @@ -3066,19 +3102,19 @@ __metadata: linkType: hard "@react-navigation/stack@npm:^7.4.2": - version: 7.4.8 - resolution: "@react-navigation/stack@npm:7.4.8" + version: 7.4.9 + resolution: "@react-navigation/stack@npm:7.4.9" dependencies: - "@react-navigation/elements": ^2.6.4 + "@react-navigation/elements": ^2.6.5 color: ^4.2.3 peerDependencies: - "@react-navigation/native": ^7.1.17 + "@react-navigation/native": ^7.1.18 react: ">= 18.2.0" react-native: "*" react-native-gesture-handler: ">= 2.0.0" react-native-safe-area-context: ">= 4.0.0" react-native-screens: ">= 4.0.0" - checksum: 8c6b0997716ef65b8a4c96e40ae3d0799c2de6749b5f3c3e83d614efea7a15e4139f1a81cde04ae7e1649ef7fc1b9b7b9fc0c9db97a4984f4edf052cc87f89c4 + checksum: 2efe2b33cea7a789d47f4721441d3cd66036b8425dbb1abbb4551560b34b8b83e852e9a8b5747d2a6fc4d3ef8ee41c24726e3205731534bf1445e6f77736b4ce languageName: node linkType: hard @@ -3097,70 +3133,45 @@ __metadata: languageName: node linkType: hard -"@shikijs/core@npm:1.29.2": - version: 1.29.2 - resolution: "@shikijs/core@npm:1.29.2" - dependencies: - "@shikijs/engine-javascript": 1.29.2 - "@shikijs/engine-oniguruma": 1.29.2 - "@shikijs/types": 1.29.2 - "@shikijs/vscode-textmate": ^10.0.1 - "@types/hast": ^3.0.4 - hast-util-to-html: ^9.0.4 - checksum: bcee4bfba8548b04505a6ac0fb45e2211fea068441bb64c4fa7b1608ae3e10e7922c6ef7a4cb4bfce20ff05256ba23d4873e6c053fb23814bb9eca689a24a158 - languageName: node - linkType: hard - -"@shikijs/engine-javascript@npm:1.29.2": - version: 1.29.2 - resolution: "@shikijs/engine-javascript@npm:1.29.2" +"@shikijs/engine-oniguruma@npm:^3.13.0": + version: 3.13.0 + resolution: "@shikijs/engine-oniguruma@npm:3.13.0" dependencies: - "@shikijs/types": 1.29.2 - "@shikijs/vscode-textmate": ^10.0.1 - oniguruma-to-es: ^2.2.0 - checksum: 748a2b1bdabc1caa7464a9622ae4b16e1a6312267ab32ae2552f50e554ff06cf7033d354946b22a7acd44e54bfbc4c85ecba16f1ae3b38e5738cd3daa26f23fd + "@shikijs/types": 3.13.0 + "@shikijs/vscode-textmate": ^10.0.2 + checksum: a0add08a52718270158f56b59d523f211fa56ee46d737f42108ebe8c84ba59ce2342db84c6c0f6b127767b10a0d91fb1a2925c7d6be06fa92923272c2c7c3b10 languageName: node linkType: hard -"@shikijs/engine-oniguruma@npm:1.29.2": - version: 1.29.2 - resolution: "@shikijs/engine-oniguruma@npm:1.29.2" +"@shikijs/langs@npm:^3.13.0": + version: 3.13.0 + resolution: "@shikijs/langs@npm:3.13.0" dependencies: - "@shikijs/types": 1.29.2 - "@shikijs/vscode-textmate": ^10.0.1 - checksum: 8713ada50e8875d22d928bd605d509a2c7d5e8c2c8a67b215b169f999457123082a02000182b37b9621903577dae5ac8067c614037fbf0aeb5b6dc2c195e58a2 + "@shikijs/types": 3.13.0 + checksum: 7eafa1b7e0399c3932a2231bb3f317c98388fab6f2a280e53370a3617e67ba2aab88d1354280c65c036feeff3344dfc7323a3f7e0e17211a385b9982bb05c90c languageName: node linkType: hard -"@shikijs/langs@npm:1.29.2": - version: 1.29.2 - resolution: "@shikijs/langs@npm:1.29.2" +"@shikijs/themes@npm:^3.13.0": + version: 3.13.0 + resolution: "@shikijs/themes@npm:3.13.0" dependencies: - "@shikijs/types": 1.29.2 - checksum: 120ac62c0f79de6903dfd9fc84d5784c6fa260eb9433ed2bc354c0edd4e8b73184e54379f9f85eb098922b1640bd111f270fdc2f694fd4aabab77a8a1d88bdca + "@shikijs/types": 3.13.0 + checksum: 00cc605ea77e3443f1b111d44b792dd94d55ab86a5ffd5c9a040bc7e9ce40a687738fb8d41b205367cb6ae09927c97930d7804d446a9c05349c2aca266166375 languageName: node linkType: hard -"@shikijs/themes@npm:1.29.2": - version: 1.29.2 - resolution: "@shikijs/themes@npm:1.29.2" +"@shikijs/types@npm:3.13.0, @shikijs/types@npm:^3.13.0": + version: 3.13.0 + resolution: "@shikijs/types@npm:3.13.0" dependencies: - "@shikijs/types": 1.29.2 - checksum: c75ddc446feb6f71bb4cd8b4e2e18dcac615b0ec7f79381b9ee3f4b26a53c37823b31f5471e5c48cf87a11bedf8642e734361147c15c0f364aab30ea66f98f77 - languageName: node - linkType: hard - -"@shikijs/types@npm:1.29.2": - version: 1.29.2 - resolution: "@shikijs/types@npm:1.29.2" - dependencies: - "@shikijs/vscode-textmate": ^10.0.1 + "@shikijs/vscode-textmate": ^10.0.2 "@types/hast": ^3.0.4 - checksum: 3aeb2933b5ceda8afe6e4be624847de5fab392085ddf77fb785cf33014120d1afd6825e666d58895e4c489981196abc161c8a4d2e41f7da33d8f5e83b58cc606 + checksum: 524ddea254f5c7dddd7a365d681e16376129ae80a2d8ce748b486644a17f0ebfde6fab5eefadb3f9008d718e987195c183e19bdeac9605413e5a22cd5b152fa9 languageName: node linkType: hard -"@shikijs/vscode-textmate@npm:^10.0.1": +"@shikijs/vscode-textmate@npm:^10.0.2": version: 10.0.2 resolution: "@shikijs/vscode-textmate@npm:10.0.2" checksum: e68f27a3dc1584d7414b8acafb9c177a2181eb0b06ef178d8609142f49d28d85fd10ab129affde40a45a7d9238997e457ce47931b3a3815980e2b98b2d26724c @@ -3197,6 +3208,13 @@ __metadata: languageName: node linkType: hard +"@sinclair/typebox@npm:^0.34.0": + version: 0.34.41 + resolution: "@sinclair/typebox@npm:0.34.41" + checksum: dbcfdc55caef47ef5b728c2bc6979e50d00ee943b63eaaf604551be9a039187cdd256d810b790e61fdf63131df54b236149aef739d83bfe9a594a9863ac28115 + languageName: node + linkType: hard + "@sindresorhus/merge-streams@npm:^2.1.0": version: 2.3.0 resolution: "@sindresorhus/merge-streams@npm:2.3.0" @@ -3239,22 +3257,23 @@ __metadata: languageName: node linkType: hard -"@testing-library/react-native@npm:^12.7.2": - version: 12.9.0 - resolution: "@testing-library/react-native@npm:12.9.0" +"@testing-library/react-native@npm:^13.3.3": + version: 13.3.3 + resolution: "@testing-library/react-native@npm:13.3.3" dependencies: - jest-matcher-utils: ^29.7.0 - pretty-format: ^29.7.0 + jest-matcher-utils: ^30.0.5 + picocolors: ^1.1.1 + pretty-format: ^30.0.5 redent: ^3.0.0 peerDependencies: - jest: ">=28.0.0" - react: ">=16.8.0" - react-native: ">=0.59" - react-test-renderer: ">=16.8.0" + jest: ">=29.0.0" + react: ">=18.2.0" + react-native: ">=0.71" + react-test-renderer: ">=18.2.0" peerDependenciesMeta: jest: optional: true - checksum: 88115b22c127f39b2e1e8098dc1c93ea9c7393800a24f4f380bed64425cc685f98cad5b56b9cb48d85f0dbed1f0f208d0de44137c6e789c98161ff2715f70646 + checksum: 5688918384ce834e3667a56b72c8b776a2f9a5afae0a2738e7d0077f342b3ade7eca628cbe122943201caee75f3718379ef7b3ca00cd50c4ee607b4131d09505 languageName: node linkType: hard @@ -3331,7 +3350,7 @@ __metadata: languageName: node linkType: hard -"@types/hast@npm:^3.0.0, @types/hast@npm:^3.0.4": +"@types/hast@npm:^3.0.4": version: 3.0.4 resolution: "@types/hast@npm:3.0.4" dependencies: @@ -3382,15 +3401,6 @@ __metadata: languageName: node linkType: hard -"@types/mdast@npm:^4.0.0": - version: 4.0.4 - resolution: "@types/mdast@npm:4.0.4" - dependencies: - "@types/unist": "*" - checksum: 20c4e9574cc409db662a35cba52b068b91eb696b3049e94321219d47d34c8ccc99a142be5c76c80a538b612457b03586bc2f6b727a3e9e7530f4c8568f6282ee - languageName: node - linkType: hard - "@types/minimist@npm:^1.2.2": version: 1.2.5 resolution: "@types/minimist@npm:1.2.5" @@ -3399,11 +3409,11 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 24.5.2 - resolution: "@types/node@npm:24.5.2" + version: 24.7.0 + resolution: "@types/node@npm:24.7.0" dependencies: - undici-types: ~7.12.0 - checksum: 5d859c117a3e15e2e7cca429ba2db9b7c5ef167eb6386ab3db9f9aad7f705baee45957ad11d6c3d7514dc189ee9ec311905944dfbe9823497ad80a9f15add048 + undici-types: ~7.14.0 + checksum: 154e6113dae3e551386d37d9e84e15bbf2a81ee14700ce42815f123ff35904363ab86a5650f98b555a892f1502b45a0aaa91666a979ec8860d95b09179d7100f languageName: node linkType: hard @@ -3443,11 +3453,11 @@ __metadata: linkType: hard "@types/react@npm:^19.0.0": - version: 19.1.14 - resolution: "@types/react@npm:19.1.14" + version: 19.2.2 + resolution: "@types/react@npm:19.2.2" dependencies: csstype: ^3.0.2 - checksum: 6528ca368d3e209fe7c74d466f252e862e4ac3bbd61a414d48421a0e07525635acc927d4a2d5d2dabf8307beb493a0276ef0b3bf51554eaf685c5766461df7ac + checksum: 7eb2d316dd5a6c02acb416524b50bae932c38d055d26e0f561ca23c009c686d16a2b22fcbb941eecbe2ecb167f119e29b9d0142d9d056dd381352c43413b60da languageName: node linkType: hard @@ -3465,7 +3475,7 @@ __metadata: languageName: node linkType: hard -"@types/unist@npm:*, @types/unist@npm:^3.0.0": +"@types/unist@npm:*": version: 3.0.3 resolution: "@types/unist@npm:3.0.3" checksum: 96e6453da9e075aaef1dc22482463898198acdc1eeb99b465e65e34303e2ec1e3b1ed4469a9118275ec284dc98019f63c3f5d49422f0e4ac707e5ab90fb3b71a @@ -3521,23 +3531,23 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^8.13.0": - version: 8.44.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.44.1" + version: 8.46.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.46.0" dependencies: "@eslint-community/regexpp": ^4.10.0 - "@typescript-eslint/scope-manager": 8.44.1 - "@typescript-eslint/type-utils": 8.44.1 - "@typescript-eslint/utils": 8.44.1 - "@typescript-eslint/visitor-keys": 8.44.1 + "@typescript-eslint/scope-manager": 8.46.0 + "@typescript-eslint/type-utils": 8.46.0 + "@typescript-eslint/utils": 8.46.0 + "@typescript-eslint/visitor-keys": 8.46.0 graphemer: ^1.4.0 ignore: ^7.0.0 natural-compare: ^1.4.0 ts-api-utils: ^2.1.0 peerDependencies: - "@typescript-eslint/parser": ^8.44.1 + "@typescript-eslint/parser": ^8.46.0 eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: e6d04ae8201af95cab838bd280f547d75a2d1f2301eed78990a6940ba82a1d74d1fd93b6d50ae310b9ce00497a94a968ca2215aa58a4bd9fdfa986f1e2fc5e39 + checksum: b3a33bbdeffeefc5798abde387b440cfbc1c0ec6778ed2fe16238f10adae28193015ecf923f305bf9a67fcb108dced47216c9dbc6778736b6db5a97e71e212af languageName: node linkType: hard @@ -3578,31 +3588,31 @@ __metadata: linkType: hard "@typescript-eslint/parser@npm:^8.13.0": - version: 8.44.1 - resolution: "@typescript-eslint/parser@npm:8.44.1" + version: 8.46.0 + resolution: "@typescript-eslint/parser@npm:8.46.0" dependencies: - "@typescript-eslint/scope-manager": 8.44.1 - "@typescript-eslint/types": 8.44.1 - "@typescript-eslint/typescript-estree": 8.44.1 - "@typescript-eslint/visitor-keys": 8.44.1 + "@typescript-eslint/scope-manager": 8.46.0 + "@typescript-eslint/types": 8.46.0 + "@typescript-eslint/typescript-estree": 8.46.0 + "@typescript-eslint/visitor-keys": 8.46.0 debug: ^4.3.4 peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 0f25f1a677c7e3cc20423f15c48d35f28de6fe6171bc0314775620812c7025e54f887da886b60e8234a6dadc132730ed84960a52a08a2ee04ab7e559aa8c9bcb + checksum: 9447250aa770eee131d81475784404b2b07caacf9bae8cef38b9ee639d8225504849a5586b5746b575f2c5dfbc9c612eb742acd8612bb1c425245f324f574613 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.44.1": - version: 8.44.1 - resolution: "@typescript-eslint/project-service@npm:8.44.1" +"@typescript-eslint/project-service@npm:8.46.0": + version: 8.46.0 + resolution: "@typescript-eslint/project-service@npm:8.46.0" dependencies: - "@typescript-eslint/tsconfig-utils": ^8.44.1 - "@typescript-eslint/types": ^8.44.1 + "@typescript-eslint/tsconfig-utils": ^8.46.0 + "@typescript-eslint/types": ^8.46.0 debug: ^4.3.4 peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: c7f006afe3690f0f44a2071cb0cf3b0ccebd56c72affe4c11238a3af315e6a12e16a08167f03e55671b817721a2ef838960963b67b16c2fb13981b2423750ae3 + checksum: ae8365cdbae5c8ee622727295f7cb59c42ccb0a4672d72692f2f31b26a052b7a9e46f58326740ca8d471a7e85998b885858be6c21921d465ce57de1d3ea7355f languageName: node linkType: hard @@ -3636,22 +3646,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.44.1": - version: 8.44.1 - resolution: "@typescript-eslint/scope-manager@npm:8.44.1" +"@typescript-eslint/scope-manager@npm:8.46.0": + version: 8.46.0 + resolution: "@typescript-eslint/scope-manager@npm:8.46.0" dependencies: - "@typescript-eslint/types": 8.44.1 - "@typescript-eslint/visitor-keys": 8.44.1 - checksum: 10a179043d240825fa4b781b8f041d401c6c9736a8769bb5f52b83bce2a7a7ea970ef97e8a51c8a633ecefcfe5b23dca7ade4dff24490aab811ea100459d69ef + "@typescript-eslint/types": 8.46.0 + "@typescript-eslint/visitor-keys": 8.46.0 + checksum: 0995be736f153314b7744594b7b5e27e63cf7b00b64b3a8cf23b4f01fc9cc01b9e652e433da438fe93efe63e505d61adb5c25319fe25e9f0ccdfea1ad7848fba languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.44.1, @typescript-eslint/tsconfig-utils@npm:^8.44.1": - version: 8.44.1 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.44.1" +"@typescript-eslint/tsconfig-utils@npm:8.46.0, @typescript-eslint/tsconfig-utils@npm:^8.46.0": + version: 8.46.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.46.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 942d4bb9ec3d0f1f6c7fe0dc0fef2ae83a12b43ff3537fbd74007d0c9b80f166db2e5fa2f422f0b10ade348e330204dc70fc50e235ee66dc13ba488ac1490778 + checksum: d4516fb18c577a47f614efe6233354efefc582eaa4e915ae3d20c23f3b17e098b254594aa26d9c51eec1116d18665f06d9ed51229600df3ce3daecae83c76865 languageName: node linkType: hard @@ -3672,19 +3682,19 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.44.1": - version: 8.44.1 - resolution: "@typescript-eslint/type-utils@npm:8.44.1" +"@typescript-eslint/type-utils@npm:8.46.0": + version: 8.46.0 + resolution: "@typescript-eslint/type-utils@npm:8.46.0" dependencies: - "@typescript-eslint/types": 8.44.1 - "@typescript-eslint/typescript-estree": 8.44.1 - "@typescript-eslint/utils": 8.44.1 + "@typescript-eslint/types": 8.46.0 + "@typescript-eslint/typescript-estree": 8.46.0 + "@typescript-eslint/utils": 8.46.0 debug: ^4.3.4 ts-api-utils: ^2.1.0 peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 5e0ecf096ba3f8924a6fa9e2beddf66fd2fd8df48383a02031a99f3273e8d704069f4100c3ebb02b5b69631e4b7588f1af55996ff06b0e3fb2d4105f0afe339a + checksum: 864f7bc0df053089d09bc757abf4f728f6fc942e162baa727f24cf68d1d79f53ccd1dff151e74b0e43c25dc53d5ce32f916a2218786d365e1027d99c6799d6d9 languageName: node linkType: hard @@ -3709,10 +3719,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:8.44.1, @typescript-eslint/types@npm:^8.44.1": - version: 8.44.1 - resolution: "@typescript-eslint/types@npm:8.44.1" - checksum: ced07574069e2118d125c5b6f9ca6ecd78530858922fcdd4202eb4c2f28eb0cdf1b4d853a834f81b9bfe54070dec5fa6b8b69d942612f916cedabc57f05814c1 +"@typescript-eslint/types@npm:8.46.0, @typescript-eslint/types@npm:^8.46.0": + version: 8.46.0 + resolution: "@typescript-eslint/types@npm:8.46.0" + checksum: 71b7e0845da160cbd8ef1a5f853a1b8626f5bd00a1db56b75218eb94d5f3433f7815635e70df52118657c57109458f2e0d2bec8dcca0c620af10c66205fe54cd languageName: node linkType: hard @@ -3772,14 +3782,14 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.44.1": - version: 8.44.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.44.1" +"@typescript-eslint/typescript-estree@npm:8.46.0": + version: 8.46.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.46.0" dependencies: - "@typescript-eslint/project-service": 8.44.1 - "@typescript-eslint/tsconfig-utils": 8.44.1 - "@typescript-eslint/types": 8.44.1 - "@typescript-eslint/visitor-keys": 8.44.1 + "@typescript-eslint/project-service": 8.46.0 + "@typescript-eslint/tsconfig-utils": 8.46.0 + "@typescript-eslint/types": 8.46.0 + "@typescript-eslint/visitor-keys": 8.46.0 debug: ^4.3.4 fast-glob: ^3.3.2 is-glob: ^4.0.3 @@ -3788,7 +3798,7 @@ __metadata: ts-api-utils: ^2.1.0 peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 453e67eb1d9fe7bdc5f78a4ae586cde35fc9799c429919ac3fe0bb806a0383ce91ebf620b50cadaa74d1096d24db1e2aea9feae3ca694d2cb3f752da078bd52b + checksum: 70f5523d266097c96e5de2cf28c86c5bb3c9d4f48ba129a9c13e620733d395008dc809c77f1af19fc4617133c0665bf65a6a688fbf40da29d5a6ebe137ea41ae languageName: node linkType: hard @@ -3806,18 +3816,18 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.44.1, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0": - version: 8.44.1 - resolution: "@typescript-eslint/utils@npm:8.44.1" +"@typescript-eslint/utils@npm:8.46.0, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0": + version: 8.46.0 + resolution: "@typescript-eslint/utils@npm:8.46.0" dependencies: "@eslint-community/eslint-utils": ^4.7.0 - "@typescript-eslint/scope-manager": 8.44.1 - "@typescript-eslint/types": 8.44.1 - "@typescript-eslint/typescript-estree": 8.44.1 + "@typescript-eslint/scope-manager": 8.46.0 + "@typescript-eslint/types": 8.46.0 + "@typescript-eslint/typescript-estree": 8.46.0 peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: a2634244709258f27f32e32c2fa4bd939b9771db698c3076e4143c923f05bf83339bf0390c7c2d2eb732e158f21bee6f4bf3e7437fbe4400a3ac2bb0f95ffa2e + checksum: 63c9f4df8f823ef7f83fe2c53f85fd5e278d60240d41414f69c8ecb37061fec74ad34851faf28283042a1a0b983ddca57dbd97a7e653073068c7f22e919f84ea languageName: node linkType: hard @@ -3869,17 +3879,17 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.44.1": - version: 8.44.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.44.1" +"@typescript-eslint/visitor-keys@npm:8.46.0": + version: 8.46.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.46.0" dependencies: - "@typescript-eslint/types": 8.44.1 + "@typescript-eslint/types": 8.46.0 eslint-visitor-keys: ^4.2.1 - checksum: 5e336a3dbda5050470b8c9d46dbd6ef2b720a712bf7d74bc1ab501cfa211147488a0e6cd5f1d61228715bb8f2a2b55c62c4a98009ae36239484cec12c5f1e5f3 + checksum: 888adc68bd8d80adb185520f2016b81a934f793db323cd62452027fad2e76a5ab64ed9500c4e5a2be2e5d2458e071776ea86a62e40e32faa4348ca4ab84dddda languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.0.0, @ungap/structured-clone@npm:^1.2.0": +"@ungap/structured-clone@npm:^1.2.0": version: 1.3.0 resolution: "@ungap/structured-clone@npm:1.3.0" checksum: 64ed518f49c2b31f5b50f8570a1e37bde3b62f2460042c50f132430b2d869c4a6586f13aa33a58a4722715b8158c68cae2827389d6752ac54da2893c83e480fc @@ -4108,7 +4118,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0": +"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 @@ -4308,6 +4318,13 @@ __metadata: languageName: node linkType: hard +"async-generator-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-generator-function@npm:1.0.0" + checksum: 74a71a4a2dd7afd06ebb612f6d612c7f4766a351bedffde466023bf6dae629e46b0d2cd38786239e0fbf245de0c7df76035465e16d1213774a0efb22fec0d713 + languageName: node + linkType: hard + "async-limiter@npm:~1.0.0": version: 1.0.1 resolution: "async-limiter@npm:1.0.1" @@ -4512,12 +4529,12 @@ __metadata: languageName: node linkType: hard -"baseline-browser-mapping@npm:^2.8.3": - version: 2.8.8 - resolution: "baseline-browser-mapping@npm:2.8.8" +"baseline-browser-mapping@npm:^2.8.9": + version: 2.8.14 + resolution: "baseline-browser-mapping@npm:2.8.14" bin: baseline-browser-mapping: dist/cli.js - checksum: d8cd9047549b7b54aed40f15036d9023e77a3919a1eea9db1bad9befb365321ff5bf580d8924de8ddf0022c037feb779f26d14bae4efb1dbc61042f3978d3311 + checksum: 422a3c25169ef6ffb89d2fab297f92c72496e0e87bcff6c7af3fbe917a9ee4ca3092ea8bd0ca128d915b2c1b2a0c7921edacdefb701e347d87158f2fa5b2bb1a languageName: node linkType: hard @@ -4611,17 +4628,17 @@ __metadata: linkType: hard "browserslist@npm:^4.20.4, browserslist@npm:^4.24.0, browserslist@npm:^4.25.3": - version: 4.26.2 - resolution: "browserslist@npm:4.26.2" + version: 4.26.3 + resolution: "browserslist@npm:4.26.3" dependencies: - baseline-browser-mapping: ^2.8.3 - caniuse-lite: ^1.0.30001741 - electron-to-chromium: ^1.5.218 + baseline-browser-mapping: ^2.8.9 + caniuse-lite: ^1.0.30001746 + electron-to-chromium: ^1.5.227 node-releases: ^2.0.21 update-browserslist-db: ^1.1.3 bin: browserslist: cli.js - checksum: ebd96e8895cdfc72be074281eb377332b69ceb944ec0c063739d8eeb8e513b168ac1e27d26ce5cc260e69a340a44c6bb5e9408565449d7a16739e5844453d4c7 + checksum: aa5bbcda9db1eeb9952b4c2f11f9a5a2247da7bcce7fa14d3cc215e67246a93394eda2f86378a41c3f73e6e1a1561bf0e7eade93c5392cb6d37bc66f70d0c53f languageName: node linkType: hard @@ -4784,17 +4801,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001741": - version: 1.0.30001745 - resolution: "caniuse-lite@npm:1.0.30001745" - checksum: a018bfbf6eda6e2728184cd39f3d0438cea04011893664fc7de19568d8e6f26cbc09e59460137bb2f4e792d1cdb7f1a48ad35f31a1c1388c1d7f74b3c889d35b - languageName: node - linkType: hard - -"ccount@npm:^2.0.0": - version: 2.0.1 - resolution: "ccount@npm:2.0.1" - checksum: 48193dada54c9e260e0acf57fc16171a225305548f9ad20d5471e0f7a8c026aedd8747091dccb0d900cde7df4e4ddbd235df0d8de4a64c71b12f0d3303eeafd4 +"caniuse-lite@npm:^1.0.30001746": + version: 1.0.30001749 + resolution: "caniuse-lite@npm:1.0.30001749" + checksum: 0a2692a7d51e4f4cecd2e8714e1d3d9982479fb59fa2fc8d6a462844bb7f5243ffe0bc94b25a1ff944f63bb2372ff5f6d01ef422729ca3c262975f1b91d78c07 languageName: node linkType: hard @@ -4842,20 +4852,6 @@ __metadata: languageName: node linkType: hard -"character-entities-html4@npm:^2.0.0": - version: 2.1.0 - resolution: "character-entities-html4@npm:2.1.0" - checksum: 7034aa7c7fa90309667f6dd50499c8a760c3d3a6fb159adb4e0bada0107d194551cdbad0714302f62d06ce4ed68565c8c2e15fdef2e8f8764eb63fa92b34b11d - languageName: node - linkType: hard - -"character-entities-legacy@npm:^3.0.0": - version: 3.0.0 - resolution: "character-entities-legacy@npm:3.0.0" - checksum: 7582af055cb488b626d364b7d7a4e46b06abd526fb63c0e4eb35bcb9c9799cc4f76b39f34fdccef2d1174ac95e53e9ab355aae83227c1a2505877893fce77731 - languageName: node - linkType: hard - "chardet@npm:^0.7.0": version: 0.7.0 resolution: "chardet@npm:0.7.0" @@ -4913,9 +4909,9 @@ __metadata: linkType: hard "ci-info@npm:^4.1.0": - version: 4.3.0 - resolution: "ci-info@npm:4.3.0" - checksum: 77a851ec826e1fbcd993e0e3ef402e6a5e499c733c475af056b7808dea9c9ede53e560ed433020489a8efea2d824fd68ca203446c9988a0bac8475210b0d4491 + version: 4.3.1 + resolution: "ci-info@npm:4.3.1" + checksum: 66c159d92648e8a07acab0a3a0681bff6ccc39aa44916263208c4d97bbbeedbbc886d7611fd30c21df1aa624ce3c6fcdfde982e74689e3e014e064e1d0805f94 languageName: node linkType: hard @@ -5094,13 +5090,6 @@ __metadata: languageName: node linkType: hard -"comma-separated-tokens@npm:^2.0.0": - version: 2.0.3 - resolution: "comma-separated-tokens@npm:2.0.3" - checksum: e3bf9e0332a5c45f49b90e79bcdb4a7a85f28d6a6f0876a94f1bb9b2bfbdbbb9292aac50e1e742d8c0db1e62a0229a106f57917e2d067fca951d81737651700d - languageName: node - linkType: hard - "command-exists@npm:^1.2.8": version: 1.2.9 resolution: "command-exists@npm:1.2.9" @@ -5812,13 +5801,6 @@ __metadata: languageName: node linkType: hard -"dequal@npm:^2.0.0": - version: 2.0.3 - resolution: "dequal@npm:2.0.3" - checksum: 8679b850e1a3d0ebbc46ee780d5df7b478c23f335887464023a631d1b9af051ad4a6595a44220f9ff8ff95a8ddccf019b5ad778a976fd7bbf77383d36f412f90 - languageName: node - linkType: hard - "destroy@npm:1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" @@ -5833,15 +5815,6 @@ __metadata: languageName: node linkType: hard -"devlop@npm:^1.0.0": - version: 1.1.0 - resolution: "devlop@npm:1.1.0" - dependencies: - dequal: ^2.0.0 - checksum: d2ff650bac0bb6ef08c48f3ba98640bb5fec5cce81e9957eb620408d1bab1204d382a45b785c6b3314dc867bb0684936b84c6867820da6db97cbb5d3c15dd185 - languageName: node - linkType: hard - "diff-sequences@npm:^29.6.3": version: 29.6.3 resolution: "diff-sequences@npm:29.6.3" @@ -5933,10 +5906,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.5.218": - version: 1.5.225 - resolution: "electron-to-chromium@npm:1.5.225" - checksum: 78051ebb8583117085db6cf3f5b9073d9c6e387e93e8281c3db9c2a88fd94bd6797b86dbaa630999aab0ef80194e637c5e09c91cfc63abe86a2c78e922b3f7dc +"electron-to-chromium@npm:^1.5.227": + version: 1.5.233 + resolution: "electron-to-chromium@npm:1.5.233" + checksum: 84c36a12b6099ef2584cee8e181f01e8efc4d1d81f1e5802c8beaae18d50ca03e9706267f6b93f3b95716ed084b5b628dfe340accf0d8b1670f714a90bccc4c0 languageName: node linkType: hard @@ -5947,13 +5920,6 @@ __metadata: languageName: node linkType: hard -"emoji-regex-xs@npm:^1.0.0": - version: 1.0.0 - resolution: "emoji-regex-xs@npm:1.0.0" - checksum: c33be159da769836f83281f2802d90169093ebf3c2c1643d6801d891c53beac5ef785fd8279f9b02fa6dc6c47c367818e076949f1e13bd1b3f921b416de4cbea - languageName: node - linkType: hard - "emoji-regex@npm:^10.3.0": version: 10.5.0 resolution: "emoji-regex@npm:10.5.0" @@ -6022,11 +5988,11 @@ __metadata: linkType: hard "envinfo@npm:^7.13.0": - version: 7.15.0 - resolution: "envinfo@npm:7.15.0" + version: 7.17.0 + resolution: "envinfo@npm:7.17.0" bin: envinfo: dist/cli.js - checksum: 38595c11134ecb66a40289980d8ca82e89fdcd68849dd72560c1bbc3cfc55c867573b4150967707ff9ff2e5cad6f1d0cb6cc56c333a6eccdcd3533452141c0a8 + checksum: d09e6d2d5dea999f9b5e1a8c496337b5e470f843c046843603e28132a7f391eef18589735c5bc8cc529a3cd8848bd1d4750fe8851f5de7b9d0d6b1d2f415adf9 languageName: node linkType: hard @@ -7014,6 +6980,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 3bf87f7b0230de5d74529677e6c3ceb3b7b5d9618b5a22d92b45ce3876defbaf5a77791b25a61b0fa7d13f95675b5ff67a7769f3b9af33f096e34653519e873d + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -7036,20 +7009,23 @@ __metadata: linkType: hard "get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7, get-intrinsic@npm:^1.3.0": - version: 1.3.0 - resolution: "get-intrinsic@npm:1.3.0" + version: 1.3.1 + resolution: "get-intrinsic@npm:1.3.1" dependencies: + async-function: ^1.0.0 + async-generator-function: ^1.0.0 call-bind-apply-helpers: ^1.0.2 es-define-property: ^1.0.1 es-errors: ^1.3.0 es-object-atoms: ^1.1.1 function-bind: ^1.1.2 + generator-function: ^2.0.0 get-proto: ^1.0.1 gopd: ^1.2.0 has-symbols: ^1.1.0 hasown: ^2.0.2 math-intrinsics: ^1.1.0 - checksum: 301008e4482bb9a9cb49e132b88fee093bff373b4e6def8ba219b1e96b60158a6084f273ef5cafe832e42cd93462f4accb46a618d35fe59a2b507f2388c5b79d + checksum: c02b3b6a445f9cd53e14896303794ac60f9751f58a69099127248abdb0251957174c6524245fc68579dc8e6a35161d3d94c93e665f808274716f4248b269436a languageName: node linkType: hard @@ -7432,34 +7408,6 @@ __metadata: languageName: node linkType: hard -"hast-util-to-html@npm:^9.0.4": - version: 9.0.5 - resolution: "hast-util-to-html@npm:9.0.5" - dependencies: - "@types/hast": ^3.0.0 - "@types/unist": ^3.0.0 - ccount: ^2.0.0 - comma-separated-tokens: ^2.0.0 - hast-util-whitespace: ^3.0.0 - html-void-elements: ^3.0.0 - mdast-util-to-hast: ^13.0.0 - property-information: ^7.0.0 - space-separated-tokens: ^2.0.0 - stringify-entities: ^4.0.0 - zwitch: ^2.0.4 - checksum: 1ebd013ad340cf646ea944100427917747f69543800e79b2186521dc29c205b4fe75d8062f3eddedf6d66f6180ca06fe127b9e53ff15a8f3579e36637ca43e16 - languageName: node - linkType: hard - -"hast-util-whitespace@npm:^3.0.0": - version: 3.0.0 - resolution: "hast-util-whitespace@npm:3.0.0" - dependencies: - "@types/hast": ^3.0.0 - checksum: 41d93ccce218ba935dc3c12acdf586193c35069489c8c8f50c2aa824c00dec94a3c78b03d1db40fa75381942a189161922e4b7bca700b3a2cc779634c351a1e4 - languageName: node - linkType: hard - "hermes-estree@npm:0.23.1": version: 0.23.1 resolution: "hermes-estree@npm:0.23.1" @@ -7565,13 +7513,6 @@ __metadata: languageName: node linkType: hard -"html-void-elements@npm:^3.0.0": - version: 3.0.0 - resolution: "html-void-elements@npm:3.0.0" - checksum: 59be397525465a7489028afa064c55763d9cccd1d7d9f630cca47137317f0e897a9ca26cef7e745e7cff1abc44260cfa407742b243a54261dfacd42230e94fce - languageName: node - linkType: hard - "http-cache-semantics@npm:^4.1.1": version: 4.2.0 resolution: "http-cache-semantics@npm:4.2.0" @@ -8002,14 +7943,15 @@ __metadata: linkType: hard "is-generator-function@npm:^1.0.10": - version: 1.1.0 - resolution: "is-generator-function@npm:1.1.0" + version: 1.1.2 + resolution: "is-generator-function@npm:1.1.2" dependencies: - call-bound: ^1.0.3 - get-proto: ^1.0.0 + call-bound: ^1.0.4 + generator-function: ^2.0.0 + get-proto: ^1.0.1 has-tostringtag: ^1.0.2 safe-regex-test: ^1.1.0 - checksum: f7f7276131bdf7e28169b86ac55a5b080012a597f9d85a0cbef6fe202a7133fa450a3b453e394870e3cb3685c5a764c64a9f12f614684b46969b1e6f297bed6b + checksum: 0b81c613752a5e534939e5b3835ff722446837a5b94c3a3934af5ded36a651d9aa31c3f11f8a3453884b9658bf26dbfb7eb855e744d920b07f084bd890a43414 languageName: node linkType: hard @@ -8589,6 +8531,18 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:30.2.0": + version: 30.2.0 + resolution: "jest-diff@npm:30.2.0" + dependencies: + "@jest/diff-sequences": 30.0.1 + "@jest/get-type": 30.1.0 + chalk: ^4.1.2 + pretty-format: 30.2.0 + checksum: 62fd17d3174316bf0140c2d342ac5ad84574763fa78fc4dd4e5ee605f121699033c9bfb7507ba8f1c5cc7fa95539a19abab13d3909a5aec1b447ab14d03c5386 + languageName: node + linkType: hard + "jest-diff@npm:^29.0.1, jest-diff@npm:^29.7.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" @@ -8689,6 +8643,18 @@ __metadata: languageName: node linkType: hard +"jest-matcher-utils@npm:^30.0.5": + version: 30.2.0 + resolution: "jest-matcher-utils@npm:30.2.0" + dependencies: + "@jest/get-type": 30.1.0 + chalk: ^4.1.2 + jest-diff: 30.2.0 + pretty-format: 30.2.0 + checksum: 33154f3fc10b19608af7f8bc91eec129f9aba0a3d89f74ffbae659159c8e2dea69c85ef1d742b1d5dd6a8be57503d77d37351edc86ce9ef3f57ecc8585e0b154 + languageName: node + linkType: hard + "jest-message-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-message-util@npm:29.7.0" @@ -8926,11 +8892,11 @@ __metadata: linkType: hard "jiti@npm:^2.4.1": - version: 2.6.0 - resolution: "jiti@npm:2.6.0" + version: 2.6.1 + resolution: "jiti@npm:2.6.1" bin: jiti: lib/jiti-cli.mjs - checksum: 2bd869527bfbb23b5210344881b4f2f5fd86b7c9c703001036544762411af73fe0f95097ba025a738874085143939664173360aafea7d7cbc4ca3bbc325774a9 + checksum: 9394e29c5e40d1ca8267923160d8d86706173c9ff30c901097883434b0c4866de2c060427b6a9a5843bb3e42fa3a3c8b5b2228531d3dd4f4f10c5c6af355bb86 languageName: node linkType: hard @@ -9531,23 +9497,6 @@ __metadata: languageName: node linkType: hard -"mdast-util-to-hast@npm:^13.0.0": - version: 13.2.0 - resolution: "mdast-util-to-hast@npm:13.2.0" - dependencies: - "@types/hast": ^3.0.0 - "@types/mdast": ^4.0.0 - "@ungap/structured-clone": ^1.0.0 - devlop: ^1.0.0 - micromark-util-sanitize-uri: ^2.0.0 - trim-lines: ^3.0.0 - unist-util-position: ^5.0.0 - unist-util-visit: ^5.0.0 - vfile: ^6.0.0 - checksum: 7e5231ff3d4e35e1421908437577fd5098141f64918ff5cc8a0f7a8a76c5407f7a3ee88d75f7a1f7afb763989c9f357475fa0ba8296c00aaff1e940098fe86a6 - languageName: node - linkType: hard - "mdurl@npm:^2.0.0": version: 2.0.0 resolution: "mdurl@npm:2.0.0" @@ -10074,48 +10023,6 @@ __metadata: languageName: node linkType: hard -"micromark-util-character@npm:^2.0.0": - version: 2.1.1 - resolution: "micromark-util-character@npm:2.1.1" - dependencies: - micromark-util-symbol: ^2.0.0 - micromark-util-types: ^2.0.0 - checksum: e9e409efe4f2596acd44587e8591b722bfc041c1577e8fe0d9c007a4776fb800f9b3637a22862ad2ba9489f4bdf72bb547fce5767dbbfe0a5e6760e2a21c6495 - languageName: node - linkType: hard - -"micromark-util-encode@npm:^2.0.0": - version: 2.0.1 - resolution: "micromark-util-encode@npm:2.0.1" - checksum: be890b98e78dd0cdd953a313f4148c4692cc2fb05533e56fef5f421287d3c08feee38ca679f318e740530791fc251bfe8c80efa926fcceb4419b269c9343d226 - languageName: node - linkType: hard - -"micromark-util-sanitize-uri@npm:^2.0.0": - version: 2.0.1 - resolution: "micromark-util-sanitize-uri@npm:2.0.1" - dependencies: - micromark-util-character: ^2.0.0 - micromark-util-encode: ^2.0.0 - micromark-util-symbol: ^2.0.0 - checksum: d01517840c17de67aaa0b0f03bfe05fac8a41d99723cd8ce16c62f6810e99cd3695364a34c335485018e5e2c00e69031744630a1b85c6868aa2f2ca1b36daa2f - languageName: node - linkType: hard - -"micromark-util-symbol@npm:^2.0.0": - version: 2.0.1 - resolution: "micromark-util-symbol@npm:2.0.1" - checksum: fb7346950550bc85a55793dda94a8b3cb3abc068dbd7570d1162db7aee803411d06c0a5de4ae59cd945f46143bdeadd4bba02a02248fa0d18cc577babaa00044 - languageName: node - linkType: hard - -"micromark-util-types@npm:^2.0.0": - version: 2.0.2 - resolution: "micromark-util-types@npm:2.0.2" - checksum: 884f7974839e4bc6d2bd662e57c973a9164fd5c0d8fe16cddf07472b86a7e6726747c00674952c0321d17685d700cd3295e9f58a842a53acdf6c6d55ab051aab - languageName: node - linkType: hard - "micromatch@npm:^4.0.4, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" @@ -10473,9 +10380,9 @@ __metadata: linkType: hard "node-releases@npm:^2.0.21": - version: 2.0.21 - resolution: "node-releases@npm:2.0.21" - checksum: 191f8245e18272971650eb45151c5891313bca27507a8f634085bd8c98a9cb9492686ef6182176866ceebff049646ef6cd5fb5ca46d5b5ca00ce2c69185d84c4 + version: 2.0.23 + resolution: "node-releases@npm:2.0.23" + checksum: dc3194ffdf04975f8525a5e175c03f5a95cecd7607b6b0e80d28aaa03900706d920722b5f2ae2e8e28e029e6ae75f0d0f7eae87e8ee2a363c704785e3118f13d languageName: node linkType: hard @@ -10702,17 +10609,6 @@ __metadata: languageName: node linkType: hard -"oniguruma-to-es@npm:^2.2.0": - version: 2.3.0 - resolution: "oniguruma-to-es@npm:2.3.0" - dependencies: - emoji-regex-xs: ^1.0.0 - regex: ^5.1.1 - regex-recursion: ^5.1.1 - checksum: b9af262ecad9d8b0817203efceed25f2675c6e4018b4778bbe3c4092506924d726f1e2f9116d7321c2bd08110d1ddef5bbbeab863d6ef2937ce554087adb6938 - languageName: node - linkType: hard - "open@npm:10.1.0": version: 10.1.0 resolution: "open@npm:10.1.0" @@ -11206,6 +11102,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:30.2.0, pretty-format@npm:^30.0.5": + version: 30.2.0 + resolution: "pretty-format@npm:30.2.0" + dependencies: + "@jest/schemas": 30.0.5 + ansi-styles: ^5.2.0 + react-is: ^18.3.1 + checksum: 4c54f5ed8bcf450df9d5d70726c3373f26896845a9704f5a4a835913dacea794fabb5de4ab19fabb0d867de496f9fc8bf854ccdb661c45af334026308557d622 + languageName: node + linkType: hard + "pretty-format@npm:^26.6.2": version: 26.6.2 resolution: "pretty-format@npm:26.6.2" @@ -11283,13 +11190,6 @@ __metadata: languageName: node linkType: hard -"property-information@npm:^7.0.0": - version: 7.1.0 - resolution: "property-information@npm:7.1.0" - checksum: 3875161d204bac89d75181f6d3ebc3ecaeb2699b4e2ecfcf5452201d7cdd275168c6742d7ff8cec5ab0c342fae72369ac705e1f8e9680a9acd911692e80dfb88 - languageName: node - linkType: hard - "proto-list@npm:~1.2.1": version: 1.2.4 resolution: "proto-list@npm:1.2.4" @@ -11477,7 +11377,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0": +"react-is@npm:^18.0.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: e20fe84c86ff172fc8d898251b7cc2c43645d108bf96d0b8edf39b98f9a2cae97b40520ee7ed8ee0085ccc94736c4886294456033304151c3f94978cec03df21 @@ -11485,9 +11385,9 @@ __metadata: linkType: hard "react-is@npm:^19.0.0, react-is@npm:^19.1.0": - version: 19.1.1 - resolution: "react-is@npm:19.1.1" - checksum: e60ed01c27fe4d22b08f8a31f18831d144a801d08a909ca31fb1d02721b4f4cde0759148d6341f660a4d6ce54a78e22b8b39520b67e2e76254e583885868ab43 + version: 19.2.0 + resolution: "react-is@npm:19.2.0" + checksum: 9a23e1c2d0bbc13b383bc59a05f54e6eb95dd87e01aec8aa92a88618364b7b0ee8a5b057ad813cf61e2f7ae7d24503b624706acb609d07c54754e5ad2c522568 languageName: node linkType: hard @@ -11871,32 +11771,6 @@ __metadata: languageName: node linkType: hard -"regex-recursion@npm:^5.1.1": - version: 5.1.1 - resolution: "regex-recursion@npm:5.1.1" - dependencies: - regex: ^5.1.1 - regex-utilities: ^2.3.0 - checksum: 4f203ae8f4a2ebf9004f4e4119df5106ba07b39bd3778d7040a83b17f3a82fe22c202661adc3f5586e4eb782fece77e8a01eba8b7033f92147ad7a1e7e1531d7 - languageName: node - linkType: hard - -"regex-utilities@npm:^2.3.0": - version: 2.3.0 - resolution: "regex-utilities@npm:2.3.0" - checksum: 41408777df45cefe1b276281030213235aa1143809c4c10eb5573d2cc27ff2c4aa746c6f4d4c235e3d2f4830eff76b28906ce82fbe72895beca8e15204c2da51 - languageName: node - linkType: hard - -"regex@npm:^5.1.1": - version: 5.1.1 - resolution: "regex@npm:5.1.1" - dependencies: - regex-utilities: ^2.3.0 - checksum: bff664d0c001bf2929c2a5c92399419f719ef5ac9e7198bce653695d37628a3bd21595cea571f93ee13b55c5bbeff7fbab307a9ef569e36b149caf09601d4a31 - languageName: node - linkType: hard - "regexp.prototype.flags@npm:^1.5.3, regexp.prototype.flags@npm:^1.5.4": version: 1.5.4 resolution: "regexp.prototype.flags@npm:1.5.4" @@ -12284,11 +12158,11 @@ __metadata: linkType: hard "semver@npm:^7.1.3, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.6, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": - version: 7.7.2 - resolution: "semver@npm:7.7.2" + version: 7.7.3 + resolution: "semver@npm:7.7.3" bin: semver: bin/semver.js - checksum: dd94ba8f1cbc903d8eeb4dd8bf19f46b3deb14262b6717d0de3c804b594058ae785ef2e4b46c5c3b58733c99c83339068203002f9e37cfe44f7e2cc5e3d2f621 + checksum: f013a3ee4607857bcd3503b6ac1d80165f7f8ea94f5d55e2d3e33df82fce487aa3313b987abf9b39e0793c83c9fc67b76c36c067625141a9f6f704ae0ea18db2 languageName: node linkType: hard @@ -12419,22 +12293,6 @@ __metadata: languageName: node linkType: hard -"shiki@npm:^1.16.2": - version: 1.29.2 - resolution: "shiki@npm:1.29.2" - dependencies: - "@shikijs/core": 1.29.2 - "@shikijs/engine-javascript": 1.29.2 - "@shikijs/engine-oniguruma": 1.29.2 - "@shikijs/langs": 1.29.2 - "@shikijs/themes": 1.29.2 - "@shikijs/types": 1.29.2 - "@shikijs/vscode-textmate": ^10.0.1 - "@types/hast": ^3.0.4 - checksum: ec78cb84205cb5eb4709269c2d0cc3e87004d81052b7c4e4b10a96fbe781dab20af4331599c1f2a77fa5ab4bb1824b735542c36de8c2866033702a7df0c3b80d - languageName: node - linkType: hard - "side-channel-list@npm:^1.0.0": version: 1.0.0 resolution: "side-channel-list@npm:1.0.0" @@ -12607,13 +12465,6 @@ __metadata: languageName: node linkType: hard -"space-separated-tokens@npm:^2.0.0": - version: 2.0.2 - resolution: "space-separated-tokens@npm:2.0.2" - checksum: 202e97d7ca1ba0758a0aa4fe226ff98142073bcceeff2da3aad037968878552c3bbce3b3231970025375bbba5aee00c5b8206eda408da837ab2dc9c0f26be990 - languageName: node - linkType: hard - "spdx-correct@npm:^3.0.0": version: 3.2.0 resolution: "spdx-correct@npm:3.2.0" @@ -12878,16 +12729,6 @@ __metadata: languageName: node linkType: hard -"stringify-entities@npm:^4.0.0": - version: 4.0.4 - resolution: "stringify-entities@npm:4.0.4" - dependencies: - character-entities-html4: ^2.0.0 - character-entities-legacy: ^3.0.0 - checksum: ac1344ef211eacf6cf0a0a8feaf96f9c36083835b406560d2c6ff5a87406a41b13f2f0b4c570a3b391f465121c4fd6822b863ffb197e8c0601a64097862cc5b5 - languageName: node - linkType: hard - "strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": version: 6.0.1 resolution: "strip-ansi@npm:6.0.1" @@ -13155,13 +12996,6 @@ __metadata: languageName: node linkType: hard -"trim-lines@npm:^3.0.0": - version: 3.0.1 - resolution: "trim-lines@npm:3.0.1" - checksum: e241da104682a0e0d807222cc1496b92e716af4db7a002f4aeff33ae6a0024fef93165d49eab11aa07c71e1347c42d46563f91dfaa4d3fb945aa535cdead53ed - languageName: node - linkType: hard - "trim-newlines@npm:^4.0.2": version: 4.1.1 resolution: "trim-newlines@npm:4.1.1" @@ -13431,40 +13265,40 @@ __metadata: languageName: node linkType: hard -"typedoc@npm:^0.26.11": - version: 0.26.11 - resolution: "typedoc@npm:0.26.11" +"typedoc@npm:^0.28.13": + version: 0.28.13 + resolution: "typedoc@npm:0.28.13" dependencies: + "@gerrit0/mini-shiki": ^3.12.0 lunr: ^2.3.9 markdown-it: ^14.1.0 minimatch: ^9.0.5 - shiki: ^1.16.2 - yaml: ^2.5.1 + yaml: ^2.8.1 peerDependencies: - typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x + typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x bin: typedoc: bin/typedoc - checksum: 9ed037ec3c10e487268078768eb68c5e68769343f71605c772c022b1b55445d34e17fba48e70ec49f535fbd27ab33ce58211f340103fc161c8367d4c6731bc11 + checksum: 238b567661d4118eaf1bc61696ce2129dc0f0d4bd9b0928942bdd40ab9165df842143a04bc1fd8c7c1c2a8978ad2b48118f4bfcd753be322476568a8cc27e355 languageName: node linkType: hard "typescript@npm:^5.2.2": - version: 5.9.2 - resolution: "typescript@npm:5.9.2" + version: 5.9.3 + resolution: "typescript@npm:5.9.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: f619cf6773cfe31409279711afd68cdf0859780006c50bc2a7a0c3227f85dea89a3b97248846326f3a17dad72ea90ec27cf61a8387772c680b2252fd02d8497b + checksum: 0d0ffb84f2cd072c3e164c79a2e5a1a1f4f168e84cb2882ff8967b92afe1def6c2a91f6838fb58b168428f9458c57a2ba06a6737711fdd87a256bbe83e9a217f languageName: node linkType: hard "typescript@patch:typescript@^5.2.2#~builtin": - version: 5.9.2 - resolution: "typescript@patch:typescript@npm%3A5.9.2#~builtin::version=5.9.2&hash=14eedb" + version: 5.9.3 + resolution: "typescript@patch:typescript@npm%3A5.9.3#~builtin::version=5.9.3&hash=14eedb" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: e42a701947325500008334622321a6ad073f842f5e7d5e7b588a6346b31fdf51d56082b9ce5cef24312ecd3e48d6c0d4d44da7555f65e2feec18cf62ec540385 + checksum: 8bb8d86819ac86a498eada254cad7fb69c5f74778506c700c2a712daeaff21d3a6f51fd0d534fe16903cb010d1b74f89437a3d02d4d0ff5ca2ba9a4660de8497 languageName: node linkType: hard @@ -13503,10 +13337,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~7.12.0": - version: 7.12.0 - resolution: "undici-types@npm:7.12.0" - checksum: 4ad2770b92835757eee6416e8518972d83fc77286c11af81d368a55578d9e4f7ab1b8a3b13c304b0e25a400583e66f3c58464a051f8b5c801ab5d092da13903e +"undici-types@npm:~7.14.0": + version: 7.14.0 + resolution: "undici-types@npm:7.14.0" + checksum: bd28cb36b33a51359f02c27b84bfe8563cdad57bdab0aa6ac605ce64d51aff49fd0aa4cb2d3b043caaa93c3ec42e96b5757df5d2d9bcc06a5f3e71899c765035 languageName: node linkType: hard @@ -13566,54 +13400,6 @@ __metadata: languageName: node linkType: hard -"unist-util-is@npm:^6.0.0": - version: 6.0.0 - resolution: "unist-util-is@npm:6.0.0" - dependencies: - "@types/unist": ^3.0.0 - checksum: f630a925126594af9993b091cf807b86811371e465b5049a6283e08537d3e6ba0f7e248e1e7dab52cfe33f9002606acef093441137181b327f6fe504884b20e2 - languageName: node - linkType: hard - -"unist-util-position@npm:^5.0.0": - version: 5.0.0 - resolution: "unist-util-position@npm:5.0.0" - dependencies: - "@types/unist": ^3.0.0 - checksum: f89b27989b19f07878de9579cd8db2aa0194c8360db69e2c99bd2124a480d79c08f04b73a64daf01a8fb3af7cba65ff4b45a0b978ca243226084ad5f5d441dde - languageName: node - linkType: hard - -"unist-util-stringify-position@npm:^4.0.0": - version: 4.0.0 - resolution: "unist-util-stringify-position@npm:4.0.0" - dependencies: - "@types/unist": ^3.0.0 - checksum: e2e7aee4b92ddb64d314b4ac89eef7a46e4c829cbd3ee4aee516d100772b490eb6b4974f653ba0717a0071ca6ea0770bf22b0a2ea62c65fcba1d071285e96324 - languageName: node - linkType: hard - -"unist-util-visit-parents@npm:^6.0.0": - version: 6.0.1 - resolution: "unist-util-visit-parents@npm:6.0.1" - dependencies: - "@types/unist": ^3.0.0 - unist-util-is: ^6.0.0 - checksum: 08927647c579f63b91aafcbec9966dc4a7d0af1e5e26fc69f4e3e6a01215084835a2321b06f3cbe7bf7914a852830fc1439f0fc3d7153d8804ac3ef851ddfa20 - languageName: node - linkType: hard - -"unist-util-visit@npm:^5.0.0": - version: 5.0.0 - resolution: "unist-util-visit@npm:5.0.0" - dependencies: - "@types/unist": ^3.0.0 - unist-util-is: ^6.0.0 - unist-util-visit-parents: ^6.0.0 - checksum: 9ec42e618e7e5d0202f3c191cd30791b51641285732767ee2e6bcd035931032e3c1b29093f4d7fd0c79175bbc1f26f24f26ee49770d32be76f8730a652a857e6 - languageName: node - linkType: hard - "universal-user-agent@npm:^6.0.0": version: 6.0.1 resolution: "universal-user-agent@npm:6.0.1" @@ -13691,20 +13477,20 @@ __metadata: linkType: hard "use-latest-callback@npm:^0.2.4": - version: 0.2.4 - resolution: "use-latest-callback@npm:0.2.4" + version: 0.2.5 + resolution: "use-latest-callback@npm:0.2.5" peerDependencies: react: ">=16.8" - checksum: 60c3a6b1b6567e1794f9e48cd86b8cde8a149485cc2fed60570f69ec3b157f6812e0ff0a877f0b971592fb9254b1363cc21c120fd1fc993b1dad1406c69211df + checksum: 8008a9c6635fa107ea3e84aba53c8f5334ea81bfe25a6866d76294045f53a34f9ad81ea7e2db595ceb1acf75064050b9cb7e800adee02e8a833b2f17ccdef88e languageName: node linkType: hard "use-sync-external-store@npm:^1.5.0": - version: 1.5.0 - resolution: "use-sync-external-store@npm:1.5.0" + version: 1.6.0 + resolution: "use-sync-external-store@npm:1.6.0" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 5e639c9273200adb6985b512c96a3a02c458bc8ca1a72e91da9cdc6426144fc6538dca434b0f99b28fb1baabc82e1c383ba7900b25ccdcb43758fb058dc66c34 + checksum: 61a62e910713adfaf91bdb72ff2cd30e5ba83687accaf3b6e75a903b45bf635f5722e3694af30d83a03e92cb533c0a5c699298d2fef639a03ffc86b469f4eee2 languageName: node linkType: hard @@ -13750,26 +13536,6 @@ __metadata: languageName: node linkType: hard -"vfile-message@npm:^4.0.0": - version: 4.0.3 - resolution: "vfile-message@npm:4.0.3" - dependencies: - "@types/unist": ^3.0.0 - unist-util-stringify-position: ^4.0.0 - checksum: f5e8516f2aa0feb4c866d507543d4e90f9ab309e2c988577dbf4ebd268d495f72f2b48149849d14300164d5d60b5f74b5641cd285bb4408a3942b758683d9276 - languageName: node - linkType: hard - -"vfile@npm:^6.0.0": - version: 6.0.3 - resolution: "vfile@npm:6.0.3" - dependencies: - "@types/unist": ^3.0.0 - vfile-message: ^4.0.0 - checksum: 152b6729be1af70df723efb65c1a1170fd483d41086557da3651eea69a1dd1f0c22ea4344834d56d30734b9185bcab63e22edc81d3f0e9bed8aa4660d61080af - languageName: node - linkType: hard - "vlq@npm:^1.0.0": version: 1.0.1 resolution: "vlq@npm:1.0.1" @@ -14096,7 +13862,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.2.1, yaml@npm:^2.5.1": +"yaml@npm:^2.2.1, yaml@npm:^2.8.1": version: 2.8.1 resolution: "yaml@npm:2.8.1" bin: @@ -14198,10 +13964,3 @@ __metadata: checksum: 207df586996c3b604fa85903f81cc54676f1f372613a0c7247f0d24b1ca781905685075d06955211c4d5d4f629d7d5628464f8af0a42d286b7a8ff88e9dadcb8 languageName: node linkType: hard - -"zwitch@npm:^2.0.4": - version: 2.0.4 - resolution: "zwitch@npm:2.0.4" - checksum: f22ec5fc2d5f02c423c93d35cdfa83573a3a3bd98c66b927c368ea4d0e7252a500df2a90a6b45522be536a96a73404393c958e945fdba95e6832c200791702b6 - languageName: node - linkType: hard From 65cb5516c098d612d074ff67c20869aa4caaa2e8 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Fri, 10 Oct 2025 12:40:35 -0700 Subject: [PATCH 13/17] feat: add authentication manager to Iterable class --- src/core/classes/Iterable.ts | 20 +++++++++++-- src/core/classes/IterableAuthManager.ts | 40 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/core/classes/IterableAuthManager.ts diff --git a/src/core/classes/Iterable.ts b/src/core/classes/Iterable.ts index 550137cb0..211151771 100644 --- a/src/core/classes/Iterable.ts +++ b/src/core/classes/Iterable.ts @@ -23,6 +23,7 @@ import type { IterableCommerceItem } from './IterableCommerceItem'; import { IterableConfig } from './IterableConfig'; import { IterableLogger } from './IterableLogger'; import type { IterableAuthFailure } from '../types/IterableAuthFailure'; +import { IterableAuthManager } from './IterableAuthManager'; const RNEventEmitter = new NativeEventEmitter(RNIterableAPI); @@ -89,6 +90,19 @@ export class Iterable { private static _inAppManager: IterableInAppManager | undefined; + /** + * Authentication manager for the current user. + * + * This property provides access to authentication functionality including + * pausing the authentication retry mechanism. + * + * @example + * ```typescript + * Iterable.authManager.pauseAuthRetries(true); + * ``` + */ + static authManager: IterableAuthManager = new IterableAuthManager(); + /** * Initializes the Iterable React Native SDK in your app's Javascript or Typescript code. * @@ -1029,7 +1043,7 @@ export class Iterable { // If type AuthReponse, authToken will be parsed looking for `authToken` within promised object. Two additional listeners will be registered for success and failure callbacks sent by native bridge layer. // Else it will be looked for as a String. if (typeof promiseResult === typeof new IterableAuthResponse()) { - RNIterableAPI.passAlongAuthToken( + Iterable.authManager.passAlongAuthToken( (promiseResult as IterableAuthResponse).authToken ); @@ -1056,9 +1070,9 @@ export class Iterable { }, 1000); // Use unref() to prevent the timeout from keeping the process alive timeoutId.unref(); - } else if (typeof promiseResult === typeof '') { + } else if (typeof promiseResult === 'string') { //If promise only returns string - RNIterableAPI.passAlongAuthToken(promiseResult as string); + Iterable.authManager.passAlongAuthToken(promiseResult as string); } else { Iterable?.logger?.log( 'Unexpected promise returned. Auth token expects promise of String or AuthResponse type.' diff --git a/src/core/classes/IterableAuthManager.ts b/src/core/classes/IterableAuthManager.ts new file mode 100644 index 000000000..6ad93f689 --- /dev/null +++ b/src/core/classes/IterableAuthManager.ts @@ -0,0 +1,40 @@ +import RNIterableAPI from '../../api'; +import { IterableAuthResponse } from './IterableAuthResponse'; + +/** + * Manages the authentication for the Iterable SDK. + * + * @example + * ```typescript + * const config = new IterableConfig(); + * const logger = new IterableLogger(config); + * const authManager = new IterableAuthManager(logger); + * ``` + */ +export class IterableAuthManager { + /** + * Pause the authentication retry mechanism. + * + * @param pauseRetry - Whether to pause the authentication retry mechanism + * + * @example + * ```typescript + * const authManager = new IterableAuthManager(); + * authManager.pauseAuthRetries(true); + * ``` + */ + pauseAuthRetries(pauseRetry: boolean) { + return RNIterableAPI.pauseAuthRetries(pauseRetry); + } + + /** + * Pass along an auth token to the SDK. + * + * @param authToken - The auth token to pass along + */ + passAlongAuthToken( + authToken: string | null | undefined + ): Promise { + return RNIterableAPI.passAlongAuthToken(authToken); + } +} From 5bbb5fcc69edd3a16d9a01d90ce19990ffe3153e Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Fri, 10 Oct 2025 12:42:11 -0700 Subject: [PATCH 14/17] refactor: remove pauseAuthRetries method from Iterable class --- src/core/classes/Iterable.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/core/classes/Iterable.ts b/src/core/classes/Iterable.ts index 211151771..a893236b8 100644 --- a/src/core/classes/Iterable.ts +++ b/src/core/classes/Iterable.ts @@ -947,22 +947,6 @@ export class Iterable { ); } - /** - * Pause the authentication retry mechanism. - * - * @param pauseRetry - Whether to pause the authentication retry mechanism - * - * @example - * ```typescript - * Iterable.pauseAuthRetries(true); - * ``` - */ - static pauseAuthRetries(pauseRetry: boolean) { - Iterable?.logger?.log('pauseAuthRetries'); - - RNIterableAPI.pauseAuthRetries(pauseRetry); - } - /** * Sets up event handlers for various Iterable events. * From 92fbff1fda9e6565539a73b75fbc280601141c8f Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Fri, 10 Oct 2025 12:45:29 -0700 Subject: [PATCH 15/17] chore: disable TSDoc syntax rule for IterableRetryBackoff enum --- src/core/enums/IterableRetryBackoff.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/enums/IterableRetryBackoff.ts b/src/core/enums/IterableRetryBackoff.ts index 4afcf9046..526b58eaf 100644 --- a/src/core/enums/IterableRetryBackoff.ts +++ b/src/core/enums/IterableRetryBackoff.ts @@ -1,3 +1,5 @@ +/* eslint-disable tsdoc/syntax */ + /** * The type of backoff to use when retrying a request. */ From e94100f67f038c3c5464fd51ade9f99b6210658c Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Fri, 10 Oct 2025 12:51:18 -0700 Subject: [PATCH 16/17] feat: add pauseAuthRetries method to authentication manager and enhance test coverage --- src/__mocks__/MockRNIterableAPI.ts | 4 +- src/core/classes/Iterable.test.ts | 553 +++++++++++++++++++++-------- 2 files changed, 408 insertions(+), 149 deletions(-) diff --git a/src/__mocks__/MockRNIterableAPI.ts b/src/__mocks__/MockRNIterableAPI.ts index 390263153..1949c15bf 100644 --- a/src/__mocks__/MockRNIterableAPI.ts +++ b/src/__mocks__/MockRNIterableAPI.ts @@ -70,12 +70,14 @@ export class MockRNIterableAPI { static initialize2WithApiKey = jest.fn().mockResolvedValue(true); - static wakeApp = jest.fn() + static wakeApp = jest.fn(); static setInAppShowResponse = jest.fn(); static passAlongAuthToken = jest.fn(); + static pauseAuthRetries = jest.fn(); + static async getInAppMessages(): Promise { return await new Promise((resolve) => { resolve(MockRNIterableAPI.messages); diff --git a/src/core/classes/Iterable.test.ts b/src/core/classes/Iterable.test.ts index 4c044165e..79c47792c 100644 --- a/src/core/classes/Iterable.test.ts +++ b/src/core/classes/Iterable.test.ts @@ -1,8 +1,8 @@ -import { NativeEventEmitter, Platform } from "react-native"; +import { NativeEventEmitter, Platform } from 'react-native'; -import { MockLinking } from "../../__mocks__/MockLinking"; -import { MockRNIterableAPI } from "../../__mocks__/MockRNIterableAPI"; -import { IterableLogger } from ".."; +import { MockLinking } from '../../__mocks__/MockLinking'; +import { MockRNIterableAPI } from '../../__mocks__/MockRNIterableAPI'; +import { IterableLogger } from '..'; // import from the same location that consumers import from import { Iterable, @@ -23,8 +23,8 @@ import { IterableInAppTriggerType, IterableAuthResponse, IterableInAppShowResponse, -} from "../.."; -import { TestHelper } from "../../__tests__/TestHelper"; +} from '../..'; +import { TestHelper } from '../../__tests__/TestHelper'; const getDefaultConfig = () => { const config = new IterableConfig(); @@ -32,7 +32,7 @@ const getDefaultConfig = () => { return config; }; -describe("Iterable", () => { +describe('Iterable', () => { beforeEach(() => { jest.clearAllMocks(); const config = getDefaultConfig(); @@ -55,11 +55,11 @@ describe("Iterable", () => { jest.clearAllTimers(); }); - describe("setEmail", () => { - it("should set the email", async () => { - const result = "user@example.com"; + describe('setEmail', () => { + it('should set the email', async () => { + const result = 'user@example.com'; // GIVEN an email - const email = "user@example.com"; + const email = 'user@example.com'; // WHEN Iterable.setEmail is called with the given email Iterable.setEmail(email); // THEN Iterable.getEmail returns the given email @@ -69,11 +69,11 @@ describe("Iterable", () => { }); }); - describe("setUserId", () => { - it("should set the userId", async () => { - const result = "user1"; + describe('setUserId', () => { + it('should set the userId', async () => { + const result = 'user1'; // GIVEN an userId - const userId = "user1"; + const userId = 'user1'; // WHEN Iterable.setUserId is called with the given userId Iterable.setUserId(userId); // THEN Iterable.getUserId returns the given userId @@ -83,8 +83,8 @@ describe("Iterable", () => { }); }); - describe("disableDeviceForCurrentUser", () => { - it("should disable the device for the current user", () => { + describe('disableDeviceForCurrentUser', () => { + it('should disable the device for the current user', () => { // GIVEN no parameters // WHEN Iterable.disableDeviceForCurrentUser is called Iterable.disableDeviceForCurrentUser(); @@ -93,12 +93,12 @@ describe("Iterable", () => { }); }); - describe("getLastPushPayload", () => { - it("should return the last push payload", async () => { - const result = { var1: "val1", var2: true }; + describe('getLastPushPayload', () => { + it('should return the last push payload', async () => { + const result = { var1: 'val1', var2: true }; // GIVEN no parameters // WHEN the lastPushPayload is set - MockRNIterableAPI.lastPushPayload = { var1: "val1", var2: true }; + MockRNIterableAPI.lastPushPayload = { var1: 'val1', var2: true }; // THEN the lastPushPayload is returned when getLastPushPayload is called return await Iterable.getLastPushPayload().then((payload) => { expect(payload).toEqual(result); @@ -106,14 +106,14 @@ describe("Iterable", () => { }); }); - describe("trackPushOpenWithCampaignId", () => { - it("should track the push open with the campaign id", () => { + describe('trackPushOpenWithCampaignId', () => { + it('should track the push open with the campaign id', () => { // GIVEN the following parameters const campaignId = 123; const templateId = 234; - const messageId = "someMessageId"; + const messageId = 'someMessageId'; const appAlreadyRunning = false; - const dataFields = { dataFieldKey: "dataFieldValue" }; + const dataFields = { dataFieldKey: 'dataFieldValue' }; // WHEN Iterable.trackPushOpenWithCampaignId is called Iterable.trackPushOpenWithCampaignId( campaignId, @@ -133,10 +133,10 @@ describe("Iterable", () => { }); }); - describe("updateCart", () => { - it("should call IterableAPI.updateCart with the correct items", () => { + describe('updateCart', () => { + it('should call IterableAPI.updateCart with the correct items', () => { // GIVEN list of items - const items = [new IterableCommerceItem("id1", "Boba Tea", 18, 26)]; + const items = [new IterableCommerceItem('id1', 'Boba Tea', 18, 26)]; // WHEN Iterable.updateCart is called Iterable.updateCart(items); // THEN corresponding function is called on RNIterableAPI @@ -144,12 +144,12 @@ describe("Iterable", () => { }); }); - describe("trackPurchase", () => { - it("should track the purchase", () => { + describe('trackPurchase', () => { + it('should track the purchase', () => { // GIVEN the following parameters const total = 10; - const items = [new IterableCommerceItem("id1", "Boba Tea", 18, 26)]; - const dataFields = { dataFieldKey: "dataFieldValue" }; + const items = [new IterableCommerceItem('id1', 'Boba Tea', 18, 26)]; + const dataFields = { dataFieldKey: 'dataFieldValue' }; // WHEN Iterable.trackPurchase is called Iterable.trackPurchase(total, items, dataFields); // THEN corresponding function is called on RNIterableAPI @@ -160,23 +160,23 @@ describe("Iterable", () => { ); }); - it("should track the purchase when called with optional fields", () => { + it('should track the purchase when called with optional fields', () => { // GIVEN the following parameters const total = 5; const items = [ new IterableCommerceItem( - "id", - "swordfish", + 'id', + 'swordfish', 64, 1, - "SKU", - "description", - "url", - "imageUrl", - ["sword", "shield"] + 'SKU', + 'description', + 'url', + 'imageUrl', + ['sword', 'shield'] ), ]; - const dataFields = { key: "value" }; + const dataFields = { key: 'value' }; // WHEN Iterable.trackPurchase is called Iterable.trackPurchase(total, items, dataFields); // THEN corresponding function is called on RNIterableAPI @@ -188,11 +188,11 @@ describe("Iterable", () => { }); }); - describe("trackEvent", () => { - it("should call IterableAPI.trackEvent with the correct name and dataFields", () => { + describe('trackEvent', () => { + it('should call IterableAPI.trackEvent with the correct name and dataFields', () => { // GIVEN the following parameters - const name = "EventName"; - const dataFields = { DatafieldKey: "DatafieldValue" }; + const name = 'EventName'; + const dataFields = { DatafieldKey: 'DatafieldValue' }; // WHEN Iterable.trackEvent is called Iterable.trackEvent(name, dataFields); // THEN corresponding function is called on RNIterableAPI @@ -200,12 +200,12 @@ describe("Iterable", () => { }); }); - describe("setAttributionInfo", () => { - it("should set the attribution info", async () => { + describe('setAttributionInfo', () => { + it('should set the attribution info', async () => { // GIVEN attribution info const campaignId = 1234; const templateId = 5678; - const messageId = "qwer"; + const messageId = 'qwer'; // WHEN Iterable.setAttributionInfo is called with the given attribution info Iterable.setAttributionInfo( new IterableAttributionInfo(campaignId, templateId, messageId) @@ -219,10 +219,10 @@ describe("Iterable", () => { }); }); - describe("updateUser", () => { - it("should update the user", () => { + describe('updateUser', () => { + it('should update the user', () => { // GIVEN the following parameters - const dataFields = { field: "value1" }; + const dataFields = { field: 'value1' }; // WHEN Iterable.updateUser is called Iterable.updateUser(dataFields, false); // THEN corresponding function is called on RNIterableAPI @@ -230,20 +230,20 @@ describe("Iterable", () => { }); }); - describe("updateEmail", () => { - it("should call IterableAPI.updateEmail with the correct email", () => { + describe('updateEmail', () => { + it('should call IterableAPI.updateEmail with the correct email', () => { // GIVEN the new email - const newEmail = "woo@newemail.com"; + const newEmail = 'woo@newemail.com'; // WHEN Iterable.updateEmail is called Iterable.updateEmail(newEmail); // THEN corresponding function is called on RNIterableAPI expect(MockRNIterableAPI.updateEmail).toBeCalledWith(newEmail, undefined); }); - it("should call IterableAPI.updateEmail with the correct email and token", () => { + it('should call IterableAPI.updateEmail with the correct email and token', () => { // GIVEN the new email and a token - const newEmail = "woo@newemail.com"; - const newToken = "token2"; + const newEmail = 'woo@newemail.com'; + const newToken = 'token2'; // WHEN Iterable.updateEmail is called Iterable.updateEmail(newEmail, newToken); // THEN corresponding function is called on RNITerableAPI @@ -251,8 +251,8 @@ describe("Iterable", () => { }); }); - describe("iterableConfig", () => { - it("should have default values", () => { + describe('iterableConfig', () => { + it('should have default values', () => { // GIVEN no parameters // WHEN config is initialized const config = new IterableConfig(); @@ -291,8 +291,8 @@ describe("Iterable", () => { }); }); - describe("urlHandler", () => { - it("should open the url when canOpenURL returns true and urlHandler returns false", async () => { + describe('urlHandler', () => { + it('should open the url when canOpenURL returns true and urlHandler returns false', async () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners(IterableEventName.handleUrlCalled); @@ -304,7 +304,7 @@ describe("Iterable", () => { return false; }); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN canOpenUrl set to return a promise that resolves to true MockLinking.canOpenURL = jest.fn(async () => { return await new Promise((resolve) => { @@ -312,11 +312,11 @@ describe("Iterable", () => { }); }); MockLinking.openURL.mockReset(); - const expectedUrl = "https://somewhere.com"; - const actionDict = { type: "openUrl" }; + const expectedUrl = 'https://somewhere.com'; + const actionDict = { type: 'openUrl' }; const dict = { url: expectedUrl, - context: { action: actionDict, source: "inApp" }, + context: { action: actionDict, source: 'inApp' }, }; // WHEN handleUrlCalled event is emitted nativeEmitter.emit(IterableEventName.handleUrlCalled, dict); @@ -327,7 +327,7 @@ describe("Iterable", () => { }); }); - it("should not open the url when canOpenURL returns false and urlHandler returns false", async () => { + it('should not open the url when canOpenURL returns false and urlHandler returns false', async () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners(IterableEventName.handleUrlCalled); @@ -339,7 +339,7 @@ describe("Iterable", () => { return false; }); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN canOpenUrl set to return a promise that resolves to false MockLinking.canOpenURL = jest.fn(async () => { return await new Promise((resolve) => { @@ -347,11 +347,11 @@ describe("Iterable", () => { }); }); MockLinking.openURL.mockReset(); - const expectedUrl = "https://somewhere.com"; - const actionDict = { type: "openUrl" }; + const expectedUrl = 'https://somewhere.com'; + const actionDict = { type: 'openUrl' }; const dict = { url: expectedUrl, - context: { action: actionDict, source: "inApp" }, + context: { action: actionDict, source: 'inApp' }, }; // WHEN handleUrlCalled event is emitted nativeEmitter.emit(IterableEventName.handleUrlCalled, dict); @@ -362,7 +362,7 @@ describe("Iterable", () => { }); }); - it("should not open the url when canOpenURL returns true and urlHandler returns true", async () => { + it('should not open the url when canOpenURL returns true and urlHandler returns true', async () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners(IterableEventName.handleUrlCalled); @@ -374,7 +374,7 @@ describe("Iterable", () => { return true; }); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN canOpenUrl set to return a promise that resolves to true MockLinking.canOpenURL = jest.fn(async () => { return await new Promise((resolve) => { @@ -382,11 +382,11 @@ describe("Iterable", () => { }); }); MockLinking.openURL.mockReset(); - const expectedUrl = "https://somewhere.com"; - const actionDict = { type: "openUrl" }; + const expectedUrl = 'https://somewhere.com'; + const actionDict = { type: 'openUrl' }; const dict = { url: expectedUrl, - context: { action: actionDict, source: "inApp" }, + context: { action: actionDict, source: 'inApp' }, }; // WHEN handleUrlCalled event is emitted nativeEmitter.emit(IterableEventName.handleUrlCalled, dict); @@ -398,8 +398,8 @@ describe("Iterable", () => { }); }); - describe("customActionHandler", () => { - it("should be called with the correct action and context", () => { + describe('customActionHandler', () => { + it('should be called with the correct action and context', () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners( @@ -415,10 +415,10 @@ describe("Iterable", () => { } ); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN custom action name and custom action data - const actionName = "zeeActionName"; - const actionData = "zeeActionData"; + const actionName = 'zeeActionName'; + const actionData = 'zeeActionData'; const actionDict = { type: actionName, data: actionData }; const actionSource = IterableActionSource.inApp; const dict = { @@ -440,10 +440,10 @@ describe("Iterable", () => { }); }); - describe("handleAppLink", () => { - it("should call IterableAPI.handleAppLink", () => { + describe('handleAppLink', () => { + it('should call IterableAPI.handleAppLink', () => { // GIVEN a link - const link = "https://somewhere.com/link/something"; + const link = 'https://somewhere.com/link/something'; // WHEN Iterable.handleAppLink is called Iterable.handleAppLink(link); // THEN corresponding function is called on RNITerableAPI @@ -451,8 +451,8 @@ describe("Iterable", () => { }); }); - describe("updateSubscriptions", () => { - it("should call IterableAPI.updateSubscriptions with the correct parameters", () => { + describe('updateSubscriptions', () => { + it('should call IterableAPI.updateSubscriptions with the correct parameters', () => { // GIVEN the following parameters const emailListIds = [1, 2, 3]; const unsubscribedChannelIds = [4, 5, 6]; @@ -481,10 +481,10 @@ describe("Iterable", () => { }); }); - describe("initialize", () => { - it("should call IterableAPI.initializeWithApiKey and save the config", async () => { + describe('initialize', () => { + it('should call IterableAPI.initializeWithApiKey and save the config', async () => { // GIVEN an API key and config - const apiKey = "test-api-key"; + const apiKey = 'test-api-key'; const config = new IterableConfig(); config.logReactNativeSdkCalls = false; config.logLevel = IterableLogLevel.debug; @@ -500,9 +500,9 @@ describe("Iterable", () => { expect(result).toBe(true); }); - it("should give the default config if no config is provided", async () => { + it('should give the default config if no config is provided', async () => { // GIVEN an API key - const apiKey = "test-api-key"; + const apiKey = 'test-api-key'; // WHEN Iterable.initialize is called const result = await Iterable.initialize(apiKey); // THEN corresponding function is called on RNIterableAPI and config is saved @@ -511,13 +511,13 @@ describe("Iterable", () => { }); }); - describe("initialize2", () => { - it("should call IterableAPI.initialize2WithApiKey with an endpoint and save the config", async () => { + describe('initialize2', () => { + it('should call IterableAPI.initialize2WithApiKey with an endpoint and save the config', async () => { // GIVEN an API key, config, and endpoint - const apiKey = "test-api-key"; + const apiKey = 'test-api-key'; const config = new IterableConfig(); config.logReactNativeSdkCalls = false; - const apiEndPoint = "https://api.staging.iterable.com"; + const apiEndPoint = 'https://api.staging.iterable.com'; // WHEN Iterable.initialize2 is called const result = await Iterable.initialize2(apiKey, config, apiEndPoint); // THEN corresponding function is called on RNIterableAPI and config is saved @@ -531,10 +531,10 @@ describe("Iterable", () => { expect(result).toBe(true); }); - it("should give the default config if no config is provided", async () => { + it('should give the default config if no config is provided', async () => { // GIVEN an API key - const apiKey = "test-api-key"; - const apiEndPoint = "https://api.staging.iterable.com"; + const apiKey = 'test-api-key'; + const apiEndPoint = 'https://api.staging.iterable.com'; // WHEN Iterable.initialize is called const result = await Iterable.initialize2(apiKey, undefined, apiEndPoint); // THEN corresponding function is called on RNIterableAPI and config is saved @@ -543,12 +543,12 @@ describe("Iterable", () => { }); }); - describe("wakeApp", () => { - it("should call IterableAPI.wakeApp on Android", () => { + describe('wakeApp', () => { + it('should call IterableAPI.wakeApp on Android', () => { // GIVEN Android platform const originalPlatform = Platform.OS; - Object.defineProperty(Platform, "OS", { - value: "android", + Object.defineProperty(Platform, 'OS', { + value: 'android', writable: true, }); // WHEN Iterable.wakeApp is called @@ -556,17 +556,17 @@ describe("Iterable", () => { // THEN corresponding function is called on RNIterableAPI expect(MockRNIterableAPI.wakeApp).toBeCalled(); // Restore original platform - Object.defineProperty(Platform, "OS", { + Object.defineProperty(Platform, 'OS', { value: originalPlatform, writable: true, }); }); - it("should not call IterableAPI.wakeApp on iOS", () => { + it('should not call IterableAPI.wakeApp on iOS', () => { // GIVEN iOS platform const originalPlatform = Platform.OS; - Object.defineProperty(Platform, "OS", { - value: "ios", + Object.defineProperty(Platform, 'OS', { + value: 'ios', writable: true, }); // WHEN Iterable.wakeApp is called @@ -574,18 +574,18 @@ describe("Iterable", () => { // THEN corresponding function is not called on RNIterableAPI expect(MockRNIterableAPI.wakeApp).not.toBeCalled(); // Restore original platform - Object.defineProperty(Platform, "OS", { + Object.defineProperty(Platform, 'OS', { value: originalPlatform, writable: true, }); }); }); - describe("trackInAppOpen", () => { - it("should call IterableAPI.trackInAppOpen with the correct parameters", () => { + describe('trackInAppOpen', () => { + it('should call IterableAPI.trackInAppOpen with the correct parameters', () => { // GIVEN an in-app message and location const message = new IterableInAppMessage( - "1234", + '1234', 4567, new IterableInAppTrigger(IterableInAppTriggerType.immediate), new Date(), @@ -607,11 +607,11 @@ describe("Iterable", () => { }); }); - describe("trackInAppClick", () => { - it("should call IterableAPI.trackInAppClick with the correct parameters", () => { + describe('trackInAppClick', () => { + it('should call IterableAPI.trackInAppClick with the correct parameters', () => { // GIVEN an in-app message, location, and clicked URL const message = new IterableInAppMessage( - "1234", + '1234', 4567, new IterableInAppTrigger(IterableInAppTriggerType.immediate), new Date(), @@ -623,7 +623,7 @@ describe("Iterable", () => { 0 ); const location = IterableInAppLocation.inApp; - const clickedUrl = "https://www.example.com"; + const clickedUrl = 'https://www.example.com'; // WHEN Iterable.trackInAppClick is called Iterable.trackInAppClick(message, location, clickedUrl); // THEN corresponding function is called on RNIterableAPI @@ -635,11 +635,11 @@ describe("Iterable", () => { }); }); - describe("trackInAppClose", () => { - it("should call IterableAPI.trackInAppClose with the correct parameters", () => { + describe('trackInAppClose', () => { + it('should call IterableAPI.trackInAppClose with the correct parameters', () => { // GIVEN an in-app message, location, and source (no URL) const message = new IterableInAppMessage( - "1234", + '1234', 4567, new IterableInAppTrigger(IterableInAppTriggerType.immediate), new Date(), @@ -663,10 +663,10 @@ describe("Iterable", () => { ); }); - it("should call IterableAPI.trackInAppClose with a clicked URL when provided", () => { + it('should call IterableAPI.trackInAppClose with a clicked URL when provided', () => { // GIVEN an in-app message, location, source, and clicked URL const message = new IterableInAppMessage( - "1234", + '1234', 4567, new IterableInAppTrigger(IterableInAppTriggerType.immediate), new Date(), @@ -679,7 +679,7 @@ describe("Iterable", () => { ); const location = IterableInAppLocation.inApp; const source = IterableInAppCloseSource.back; - const clickedUrl = "https://www.example.com"; + const clickedUrl = 'https://www.example.com'; // WHEN Iterable.trackInAppClose is called Iterable.trackInAppClose(message, location, source, clickedUrl); // THEN corresponding function is called on RNIterableAPI @@ -692,11 +692,11 @@ describe("Iterable", () => { }); }); - describe("inAppConsume", () => { - it("should call IterableAPI.inAppConsume with the correct parameters", () => { + describe('inAppConsume', () => { + it('should call IterableAPI.inAppConsume with the correct parameters', () => { // GIVEN an in-app message, location, and delete source const message = new IterableInAppMessage( - "1234", + '1234', 4567, new IterableInAppTrigger(IterableInAppTriggerType.immediate), new Date(), @@ -720,19 +720,19 @@ describe("Iterable", () => { }); }); - describe("getVersionFromPackageJson", () => { - it("should return the version from the package.json file", () => { + describe('getVersionFromPackageJson', () => { + it('should return the version from the package.json file', () => { // GIVEN no parameters // WHEN Iterable.getVersionFromPackageJson is called const version = Iterable.getVersionFromPackageJson(); // THEN a version string is returned - expect(typeof version).toBe("string"); + expect(typeof version).toBe('string'); expect(version.length).toBeGreaterThan(0); }); }); - describe("setupEventHandlers", () => { - it("should call inAppHandler when handleInAppCalled event is emitted", () => { + describe('setupEventHandlers', () => { + it('should call inAppHandler when handleInAppCalled event is emitted', () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners(IterableEventName.handleInAppCalled); @@ -743,10 +743,10 @@ describe("Iterable", () => { return IterableInAppShowResponse.show; }); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN message dictionary const messageDict = { - messageId: "1234", + messageId: '1234', campaignId: 4567, trigger: { type: 0 }, createdAt: new Date().toISOString(), @@ -768,8 +768,8 @@ describe("Iterable", () => { ); }); - describe("authHandler", () => { - it("should call authHandler when handleAuthCalled event is emitted", async () => { + describe('authHandler', () => { + it('should call authHandler when handleAuthCalled event is emitted', async () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners(IterableEventName.handleAuthCalled); @@ -785,14 +785,14 @@ describe("Iterable", () => { const successCallback = jest.fn(); const failureCallback = jest.fn(); const authResponse = new IterableAuthResponse(); - authResponse.authToken = "test-token"; + authResponse.authToken = 'test-token'; authResponse.successCallback = successCallback; authResponse.failureCallback = failureCallback; config.authHandler = jest.fn(() => { return Promise.resolve(authResponse); }); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN auth handler returns AuthResponse // WHEN handleAuthCalled event is emitted nativeEmitter.emit(IterableEventName.handleAuthCalled); @@ -801,14 +801,14 @@ describe("Iterable", () => { // THEN passAlongAuthToken is called with the token and success callback is called after timeout return await TestHelper.delayed(1100, () => { expect(MockRNIterableAPI.passAlongAuthToken).toBeCalledWith( - "test-token" + 'test-token' ); expect(successCallback).toBeCalled(); expect(failureCallback).not.toBeCalled(); }); }); - it("should call authHandler when handleAuthFailureCalled event is emitted", async () => { + it('should call authHandler when handleAuthFailureCalled event is emitted', async () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners(IterableEventName.handleAuthCalled); @@ -824,7 +824,7 @@ describe("Iterable", () => { const successCallback = jest.fn(); const failureCallback = jest.fn(); const authResponse = new IterableAuthResponse(); - authResponse.authToken = "test-token"; + authResponse.authToken = 'test-token'; authResponse.successCallback = successCallback; authResponse.failureCallback = failureCallback; config.authHandler = jest.fn(() => { @@ -832,7 +832,7 @@ describe("Iterable", () => { return Promise.resolve(authResponse); }); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN auth handler returns AuthResponse // WHEN handleAuthCalled event is emitted nativeEmitter.emit(IterableEventName.handleAuthCalled); @@ -841,14 +841,14 @@ describe("Iterable", () => { // THEN passAlongAuthToken is called with the token and failure callback is called after timeout return await TestHelper.delayed(1100, () => { expect(MockRNIterableAPI.passAlongAuthToken).toBeCalledWith( - "test-token" + 'test-token' ); expect(failureCallback).toBeCalled(); expect(successCallback).not.toBeCalled(); }); }); - it("should call authHandler when handleAuthCalled event is emitted and returns a string token", async () => { + it('should call authHandler when handleAuthCalled event is emitted and returns a string token', async () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners(IterableEventName.handleAuthCalled); @@ -856,22 +856,22 @@ describe("Iterable", () => { const config = new IterableConfig(); config.logReactNativeSdkCalls = false; config.authHandler = jest.fn(() => { - return Promise.resolve("string-token"); + return Promise.resolve('string-token'); }); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN auth handler returns string token // WHEN handleAuthCalled event is emitted nativeEmitter.emit(IterableEventName.handleAuthCalled); // THEN passAlongAuthToken is called with the string token return await TestHelper.delayed(100, () => { expect(MockRNIterableAPI.passAlongAuthToken).toBeCalledWith( - "string-token" + 'string-token' ); }); }); - it("should call authHandler when handleAuthCalled event is emitted and returns an unexpected response", () => { + it('should call authHandler when handleAuthCalled event is emitted and returns an unexpected response', () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners(IterableEventName.handleAuthCalled); @@ -879,12 +879,12 @@ describe("Iterable", () => { const config = new IterableConfig(); config.logReactNativeSdkCalls = false; config.authHandler = jest.fn(() => { - return Promise.resolve({ unexpected: "object" } as unknown as + return Promise.resolve({ unexpected: 'object' } as unknown as | string | IterableAuthResponse); }); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN auth handler returns unexpected response // WHEN handleAuthCalled event is emitted nativeEmitter.emit(IterableEventName.handleAuthCalled); @@ -892,7 +892,7 @@ describe("Iterable", () => { expect(MockRNIterableAPI.passAlongAuthToken).not.toBeCalled(); }); - it("should call authHandler when handleAuthCalled event is emitted and rejects the promise", () => { + it('should call authHandler when handleAuthCalled event is emitted and rejects the promise', () => { // sets up event emitter const nativeEmitter = new NativeEventEmitter(); nativeEmitter.removeAllListeners(IterableEventName.handleAuthCalled); @@ -900,10 +900,10 @@ describe("Iterable", () => { const config = new IterableConfig(); config.logReactNativeSdkCalls = false; config.authHandler = jest.fn(() => { - return Promise.reject(new Error("Auth failed")); + return Promise.reject(new Error('Auth failed')); }); // initialize Iterable object - Iterable.initialize("apiKey", config); + Iterable.initialize('apiKey', config); // GIVEN auth handler rejects promise // WHEN handleAuthCalled event is emitted nativeEmitter.emit(IterableEventName.handleAuthCalled); @@ -912,4 +912,261 @@ describe("Iterable", () => { }); }); }); + + describe('authManager', () => { + describe('pauseAuthRetries', () => { + it('should call RNIterableAPI.pauseAuthRetries with true when pauseRetry is true', () => { + // GIVEN pauseRetry is true + const pauseRetry = true; + + // WHEN pauseAuthRetries is called + Iterable.authManager.pauseAuthRetries(pauseRetry); + + // THEN RNIterableAPI.pauseAuthRetries is called with true + expect(MockRNIterableAPI.pauseAuthRetries).toBeCalledWith(true); + }); + + it('should call RNIterableAPI.pauseAuthRetries with false when pauseRetry is false', () => { + // GIVEN pauseRetry is false + const pauseRetry = false; + + // WHEN pauseAuthRetries is called + Iterable.authManager.pauseAuthRetries(pauseRetry); + + // THEN RNIterableAPI.pauseAuthRetries is called with false + expect(MockRNIterableAPI.pauseAuthRetries).toBeCalledWith(false); + }); + + it('should return the result from RNIterableAPI.pauseAuthRetries', () => { + // GIVEN RNIterableAPI.pauseAuthRetries returns a value + const expectedResult = 'pause-result'; + MockRNIterableAPI.pauseAuthRetries = jest + .fn() + .mockReturnValue(expectedResult); + + // WHEN pauseAuthRetries is called + const result = Iterable.authManager.pauseAuthRetries(true); + + // THEN the result is returned + expect(result).toBe(expectedResult); + }); + }); + + describe('passAlongAuthToken', () => { + it('should call RNIterableAPI.passAlongAuthToken with a valid string token', async () => { + // GIVEN a valid auth token + const authToken = 'valid-jwt-token'; + const expectedResponse = new IterableAuthResponse(); + expectedResponse.authToken = 'new-token'; + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockResolvedValue(expectedResponse); + + // WHEN passAlongAuthToken is called + const result = await Iterable.authManager.passAlongAuthToken(authToken); + + // THEN RNIterableAPI.passAlongAuthToken is called with the token + expect(MockRNIterableAPI.passAlongAuthToken).toBeCalledWith(authToken); + expect(result).toBe(expectedResponse); + }); + + it('should call RNIterableAPI.passAlongAuthToken with null token', async () => { + // GIVEN a null auth token + const authToken = null; + const expectedResponse = 'success'; + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockResolvedValue(expectedResponse); + + // WHEN passAlongAuthToken is called + const result = await Iterable.authManager.passAlongAuthToken(authToken); + + // THEN RNIterableAPI.passAlongAuthToken is called with null + expect(MockRNIterableAPI.passAlongAuthToken).toBeCalledWith(null); + expect(result).toBe(expectedResponse); + }); + + it('should call RNIterableAPI.passAlongAuthToken with undefined token', async () => { + // GIVEN an undefined auth token + const authToken = undefined; + const expectedResponse = undefined; + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockResolvedValue(expectedResponse); + + // WHEN passAlongAuthToken is called + const result = await Iterable.authManager.passAlongAuthToken(authToken); + + // THEN RNIterableAPI.passAlongAuthToken is called with undefined + expect(MockRNIterableAPI.passAlongAuthToken).toBeCalledWith(undefined); + expect(result).toBe(expectedResponse); + }); + + it('should call RNIterableAPI.passAlongAuthToken with empty string token', async () => { + // GIVEN an empty string auth token + const authToken = ''; + const expectedResponse = new IterableAuthResponse(); + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockResolvedValue(expectedResponse); + + // WHEN passAlongAuthToken is called + const result = await Iterable.authManager.passAlongAuthToken(authToken); + + // THEN RNIterableAPI.passAlongAuthToken is called with empty string + expect(MockRNIterableAPI.passAlongAuthToken).toBeCalledWith(''); + expect(result).toBe(expectedResponse); + }); + + it('should return IterableAuthResponse when API returns IterableAuthResponse', async () => { + // GIVEN API returns IterableAuthResponse + const authToken = 'test-token'; + const expectedResponse = new IterableAuthResponse(); + expectedResponse.authToken = 'new-token'; + expectedResponse.successCallback = jest.fn(); + expectedResponse.failureCallback = jest.fn(); + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockResolvedValue(expectedResponse); + + // WHEN passAlongAuthToken is called + const result = await Iterable.authManager.passAlongAuthToken(authToken); + + // THEN the result is the expected IterableAuthResponse + expect(result).toBe(expectedResponse); + expect(result).toBeInstanceOf(IterableAuthResponse); + }); + + it('should return string when API returns string', async () => { + // GIVEN API returns string + const authToken = 'test-token'; + const expectedResponse = 'success-string'; + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockResolvedValue(expectedResponse); + + // WHEN passAlongAuthToken is called + const result = await Iterable.authManager.passAlongAuthToken(authToken); + + // THEN the result is the expected string + expect(result).toBe(expectedResponse); + expect(typeof result).toBe('string'); + }); + + it('should return undefined when API returns undefined', async () => { + // GIVEN API returns undefined + const authToken = 'test-token'; + const expectedResponse = undefined; + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockResolvedValue(expectedResponse); + + // WHEN passAlongAuthToken is called + const result = await Iterable.authManager.passAlongAuthToken(authToken); + + // THEN the result is undefined + expect(result).toBeUndefined(); + }); + + it('should handle API rejection and propagate the error', async () => { + // GIVEN API rejects with an error + const authToken = 'test-token'; + const expectedError = new Error('API Error'); + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockRejectedValue(expectedError); + + // WHEN passAlongAuthToken is called + // THEN the error is propagated + await expect( + Iterable.authManager.passAlongAuthToken(authToken) + ).rejects.toThrow('API Error'); + }); + + it('should handle API rejection with network error', async () => { + // GIVEN API rejects with a network error + const authToken = 'test-token'; + const networkError = new Error('Network request failed'); + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockRejectedValue(networkError); + + // WHEN passAlongAuthToken is called + // THEN the network error is propagated + await expect( + Iterable.authManager.passAlongAuthToken(authToken) + ).rejects.toThrow('Network request failed'); + }); + + it('should handle API rejection with timeout error', async () => { + // GIVEN API rejects with a timeout error + const authToken = 'test-token'; + const timeoutError = new Error('Request timeout'); + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockRejectedValue(timeoutError); + + // WHEN passAlongAuthToken is called + // THEN the timeout error is propagated + await expect( + Iterable.authManager.passAlongAuthToken(authToken) + ).rejects.toThrow('Request timeout'); + }); + }); + + describe('integration', () => { + it('should work with both methods in sequence', async () => { + // GIVEN a sequence of operations + const authToken = 'test-token'; + const expectedResponse = new IterableAuthResponse(); + MockRNIterableAPI.pauseAuthRetries = jest + .fn() + .mockReturnValue('paused'); + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockResolvedValue(expectedResponse); + + // WHEN calling both methods in sequence + const pauseResult = Iterable.authManager.pauseAuthRetries(true); + const tokenResult = + await Iterable.authManager.passAlongAuthToken(authToken); + + // THEN both operations should work correctly + expect(pauseResult).toBe('paused'); + expect(tokenResult).toBe(expectedResponse); + expect(MockRNIterableAPI.pauseAuthRetries).toBeCalledWith(true); + expect(MockRNIterableAPI.passAlongAuthToken).toBeCalledWith(authToken); + }); + + it('should handle rapid successive calls', async () => { + // GIVEN rapid successive calls + const authToken1 = 'token1'; + const authToken2 = 'token2'; + const response1 = new IterableAuthResponse(); + const response2 = 'success'; + MockRNIterableAPI.passAlongAuthToken = jest + .fn() + .mockResolvedValueOnce(response1) + .mockResolvedValueOnce(response2); + + // WHEN making rapid successive calls + const promise1 = Iterable.authManager.passAlongAuthToken(authToken1); + const promise2 = Iterable.authManager.passAlongAuthToken(authToken2); + const [result1, result2] = await Promise.all([promise1, promise2]); + + // THEN both calls should work correctly + expect(result1).toBe(response1); + expect(result2).toBe(response2); + expect(MockRNIterableAPI.passAlongAuthToken).toHaveBeenCalledTimes(2); + expect(MockRNIterableAPI.passAlongAuthToken).toHaveBeenNthCalledWith( + 1, + authToken1 + ); + expect(MockRNIterableAPI.passAlongAuthToken).toHaveBeenNthCalledWith( + 2, + authToken2 + ); + }); + }); + }); }); From 71ac5c4d2826e28e0545bc599d3e6ab58a15d353 Mon Sep 17 00:00:00 2001 From: Loren Posen Date: Mon, 13 Oct 2025 10:20:09 -0700 Subject: [PATCH 17/17] docs: add better comments to IterableAuthManager --- src/core/classes/IterableAuthManager.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/core/classes/IterableAuthManager.ts b/src/core/classes/IterableAuthManager.ts index 6ad93f689..9df15c03a 100644 --- a/src/core/classes/IterableAuthManager.ts +++ b/src/core/classes/IterableAuthManager.ts @@ -6,9 +6,7 @@ import { IterableAuthResponse } from './IterableAuthResponse'; * * @example * ```typescript - * const config = new IterableConfig(); - * const logger = new IterableLogger(config); - * const authManager = new IterableAuthManager(logger); + * const authManager = new IterableAuthManager(); * ``` */ export class IterableAuthManager { @@ -31,6 +29,12 @@ export class IterableAuthManager { * Pass along an auth token to the SDK. * * @param authToken - The auth token to pass along + * + * @example + * ```typescript + * const authManager = new IterableAuthManager(); + * authManager.passAlongAuthToken(MY_AUTH_TOKEN); + * ``` */ passAlongAuthToken( authToken: string | null | undefined