From ad0c99ff0109064a1af3a795f1f27d8d01ca81ff Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 15 Oct 2025 18:17:40 -0700 Subject: [PATCH 1/6] break up log rename log --- package.json | 4 +- .../executors/CustomEventOperationExecutor.ts | 4 +- .../executors/IdentityOperationExecutor.ts | 4 +- .../executors/LoginUserOperationExecutor.ts | 8 +- .../executors/RefreshUserOperationExecutor.ts | 4 +- .../SubscriptionOperationExecutor.ts | 4 +- .../executors/UpdateUserOperationExecutor.ts | 4 +- src/core/modelRepo/OperationModelStore.ts | 10 +-- src/core/operationRepo/OperationRepo.test.ts | 4 +- src/core/operationRepo/OperationRepo.ts | 26 +++--- src/entries/pageSdkInit.test.ts | 4 +- src/entries/pageSdkInit.ts | 8 +- src/entries/pageSdkInit2.test.ts | 4 +- src/onesignal/DebugNamesapce.ts | 4 +- src/onesignal/NotificationsNamespace.test.ts | 8 +- src/onesignal/OneSignal.test.ts | 8 +- src/onesignal/OneSignal.ts | 14 +-- src/onesignal/PushSubscriptionNamespace.ts | 10 +-- src/onesignal/SessionNamespace.ts | 12 +-- src/onesignal/SlidedownNamespace.test.ts | 4 +- src/onesignal/User.ts | 6 +- src/onesignal/UserNamespace.test.ts | 6 +- src/onesignal/userDirector.ts | 4 +- src/page/bell/Bell.ts | 18 ++-- src/page/bell/Message.ts | 4 +- src/page/managers/LoginManager.ts | 6 +- src/page/managers/PromptsManager.ts | 22 ++--- .../slidedownManager/SlidedownManager.test.ts | 6 +- .../slidedownManager/SlidedownManager.ts | 35 ++++---- src/page/managers/tagManager/TagManager.ts | 6 +- src/page/slidedown/ChannelCaptureContainer.ts | 8 +- src/shared/api/base.ts | 6 +- src/shared/api/shared.test.ts | 4 +- src/shared/api/shared.ts | 6 +- src/shared/api/sw.ts | 8 +- src/shared/database/client.ts | 4 +- src/shared/database/config.ts | 4 +- src/shared/helpers/OutcomesHelper.ts | 18 ++-- src/shared/helpers/dismiss.ts | 4 +- src/shared/helpers/dom.ts | 4 +- src/shared/helpers/init.ts | 28 +++--- src/shared/helpers/main.ts | 6 +- src/shared/helpers/pageview.ts | 4 +- src/shared/helpers/service-worker.ts | 20 ++--- src/shared/helpers/subscription.ts | 4 +- src/shared/libraries/Log.ts | 42 --------- src/shared/libraries/log.ts | 43 ++++++++++ src/shared/libraries/workerMessenger/page.ts | 14 +-- src/shared/libraries/workerMessenger/sw.ts | 15 ++-- src/shared/listeners.ts | 14 +-- src/shared/managers/CustomLinkManager.ts | 16 ++-- src/shared/managers/ServiceWorkerManager.ts | 50 ++++++----- src/shared/managers/UpdateManager.ts | 16 ++-- .../sessionManager/SessionManager.test.ts | 4 +- .../managers/sessionManager/SessionManager.ts | 44 +++++----- src/shared/managers/subscription/base.ts | 14 +-- src/shared/managers/subscription/page.ts | 16 ++-- src/shared/services/OneSignalEvent.ts | 6 +- src/shared/utils/utils.ts | 8 +- src/sw/helpers/CancelableTimeout.ts | 6 +- src/sw/helpers/registration.ts | 11 +-- src/sw/serviceWorker/ServiceWorker.test.ts | 8 +- src/sw/serviceWorker/ServiceWorker.ts | 86 +++++++++---------- src/sw/webhooks/sender.ts | 4 +- 64 files changed, 383 insertions(+), 423 deletions(-) delete mode 100644 src/shared/libraries/Log.ts create mode 100644 src/shared/libraries/log.ts diff --git a/package.json b/package.json index 498a9a594..e1ec0303b 100644 --- a/package.json +++ b/package.json @@ -84,12 +84,12 @@ }, { "path": "./build/releases/OneSignalSDK.page.es6.js", - "limit": "45.63 kB", + "limit": "45.51 kB", "gzip": true }, { "path": "./build/releases/OneSignalSDK.sw.js", - "limit": "13.442 kB", + "limit": "13.4 kB", "gzip": true }, { diff --git a/src/core/executors/CustomEventOperationExecutor.ts b/src/core/executors/CustomEventOperationExecutor.ts index e60d33373..c3a082076 100644 --- a/src/core/executors/CustomEventOperationExecutor.ts +++ b/src/core/executors/CustomEventOperationExecutor.ts @@ -7,7 +7,7 @@ import { getResponseStatusType, ResponseStatusType, } from 'src/shared/helpers/network'; -import Log from 'src/shared/libraries/Log'; +import { debug } from 'src/shared/libraries/log'; import { VERSION } from 'src/shared/utils/env'; import { OPERATION_NAME } from '../constants'; import { Operation } from '../operations/Operation'; @@ -34,7 +34,7 @@ export class CustomEventsOperationExecutor implements IOperationExecutor { } async _execute(operations: Operation[]): Promise { - Log._debug( + debug( `CustomEventsOperationExecutor(operations: ${JSON.stringify( operations, )})`, diff --git a/src/core/executors/IdentityOperationExecutor.ts b/src/core/executors/IdentityOperationExecutor.ts index 3025b0199..37d3486dd 100644 --- a/src/core/executors/IdentityOperationExecutor.ts +++ b/src/core/executors/IdentityOperationExecutor.ts @@ -8,7 +8,7 @@ import { getResponseStatusType, ResponseStatusType, } from 'src/shared/helpers/network'; -import Log from 'src/shared/libraries/Log'; +import { debug } from 'src/shared/libraries/log'; import { IdentityConstants, OPERATION_NAME } from '../constants'; import { type IdentityModelStore } from '../modelStores/IdentityModelStore'; import { type NewRecordsState } from '../operationRepo/NewRecordsState'; @@ -40,7 +40,7 @@ export class IdentityOperationExecutor implements IOperationExecutor { } async _execute(operations: Operation[]): Promise { - Log._debug( + debug( `IdentityOperationExecutor(operations: ${JSON.stringify(operations)})`, ); diff --git a/src/core/executors/LoginUserOperationExecutor.ts b/src/core/executors/LoginUserOperationExecutor.ts index 3bf73c761..97cc52245 100644 --- a/src/core/executors/LoginUserOperationExecutor.ts +++ b/src/core/executors/LoginUserOperationExecutor.ts @@ -8,7 +8,7 @@ import { getResponseStatusType, ResponseStatusType, } from 'src/shared/helpers/network'; -import Log from 'src/shared/libraries/Log'; +import { debug, error } from 'src/shared/libraries/log'; import { checkAndTriggerUserChanged } from 'src/shared/listeners'; import { IdentityConstants, OPERATION_NAME } from '../constants'; import { type IPropertiesModelKeys } from '../models/PropertiesModel'; @@ -62,7 +62,7 @@ export class LoginUserOperationExecutor implements IOperationExecutor { } async _execute(operations: Operation[]): Promise { - Log._debug( + debug( `LoginUserOperationExecutor(operation: ${JSON.stringify(operations)})`, ); const startingOp = operations[0]; @@ -122,11 +122,11 @@ export class LoginUserOperationExecutor implements IOperationExecutor { } case ExecutionResult._FailConflict: - Log._debug(`Handling 409 for externalId: ${loginUserOp._externalId}`); + debug(`Handling 409 for externalId: ${loginUserOp._externalId}`); return this._createUser(loginUserOp, operations); case ExecutionResult._FailNoretry: - Log._error( + error( `Recovering from SetAlias failure for externalId: ${loginUserOp._externalId}`, ); return this._createUser(loginUserOp, operations); diff --git a/src/core/executors/RefreshUserOperationExecutor.ts b/src/core/executors/RefreshUserOperationExecutor.ts index 02ea70141..ef20b3167 100644 --- a/src/core/executors/RefreshUserOperationExecutor.ts +++ b/src/core/executors/RefreshUserOperationExecutor.ts @@ -3,7 +3,7 @@ import { ResponseStatusType, } from 'src/shared/helpers/network'; import { isPushSubscriptionType } from 'src/shared/helpers/subscription'; -import Log from 'src/shared/libraries/Log'; +import { debug } from 'src/shared/libraries/log'; import { NotificationType } from 'src/shared/subscriptions/constants'; import { IdentityConstants, OPERATION_NAME } from '../constants'; import { IdentityModel } from '../models/IdentityModel'; @@ -52,7 +52,7 @@ export class RefreshUserOperationExecutor implements IOperationExecutor { } async _execute(operations: Operation[]): Promise { - Log._debug( + debug( `RefreshUserOperationExecutor(operation: ${JSON.stringify(operations)})`, ); diff --git a/src/core/executors/SubscriptionOperationExecutor.ts b/src/core/executors/SubscriptionOperationExecutor.ts index 90aa29e1f..966a94641 100644 --- a/src/core/executors/SubscriptionOperationExecutor.ts +++ b/src/core/executors/SubscriptionOperationExecutor.ts @@ -7,7 +7,7 @@ import { getResponseStatusType, ResponseStatusType, } from 'src/shared/helpers/network'; -import Log from 'src/shared/libraries/Log'; +import { debug } from 'src/shared/libraries/log'; import { IdentityConstants, OPERATION_NAME } from '../constants'; import { type SubscriptionModelStore } from '../modelStores/SubscriptionModelStore'; import { type NewRecordsState } from '../operationRepo/NewRecordsState'; @@ -53,7 +53,7 @@ export class SubscriptionOperationExecutor implements IOperationExecutor { } async _execute(operations: Operation[]): Promise { - Log._debug(`SubscriptionOperationExecutor(operations: ${operations})`); + debug(`SubscriptionOperationExecutor(operations: ${operations})`); const startingOp = operations[0]; if (startingOp instanceof CreateSubscriptionOperation) diff --git a/src/core/executors/UpdateUserOperationExecutor.ts b/src/core/executors/UpdateUserOperationExecutor.ts index a67195532..1b9994927 100644 --- a/src/core/executors/UpdateUserOperationExecutor.ts +++ b/src/core/executors/UpdateUserOperationExecutor.ts @@ -2,7 +2,7 @@ import { getResponseStatusType, ResponseStatusType, } from 'src/shared/helpers/network'; -import Log from 'src/shared/libraries/Log'; +import { debug } from 'src/shared/libraries/log'; import { IdentityConstants, OPERATION_NAME } from '../constants'; import { type IPropertiesModelKeys } from '../models/PropertiesModel'; import { type IdentityModelStore } from '../modelStores/IdentityModelStore'; @@ -78,7 +78,7 @@ export class UpdateUserOperationExecutor implements IOperationExecutor { } async _execute(operations: Operation[]): Promise { - Log._debug(`UpdateUserOperationExecutor(operation: ${operations})`); + debug(`UpdateUserOperationExecutor(operation: ${operations})`); const { appId, onesignalId, propertiesObject, refreshDeviceMetadata } = this._processOperations(operations); diff --git a/src/core/modelRepo/OperationModelStore.ts b/src/core/modelRepo/OperationModelStore.ts index de8a017d9..c50de992c 100644 --- a/src/core/modelRepo/OperationModelStore.ts +++ b/src/core/modelRepo/OperationModelStore.ts @@ -1,5 +1,5 @@ import type { IDBStoreName } from 'src/shared/database/types'; -import Log from 'src/shared/libraries/Log'; +import { error } from 'src/shared/libraries/log'; import { OPERATION_NAME } from '../constants'; import { CreateSubscriptionOperation } from '../operations/CreateSubscriptionOperation'; import { DeleteAliasOperation } from '../operations/DeleteAliasOperation'; @@ -27,7 +27,7 @@ export class OperationModelStore extends ModelStore { _create(jsonObject?: { name?: string } | null): Operation | null { if (jsonObject === null) { - Log._error('null jsonObject sent to OperationModelStore.create'); + error('null jsonObject sent to OperationModelStore.create'); return null; } @@ -96,7 +96,7 @@ export class OperationModelStore extends ModelStore { } { const operationName = object?.name; if (!operationName) { - Log._error("jsonObject must have 'name' attribute"); + error("jsonObject must have 'name' attribute"); return false; } @@ -104,9 +104,7 @@ export class OperationModelStore extends ModelStore { // Must have onesignalId if it is not one of the excluded operations above if (!object.onesignalId && !excluded.has(operationName)) { - Log._error( - `${operationName} jsonObject must have 'onesignalId' attribute`, - ); + error(`${operationName} jsonObject must have 'onesignalId' attribute`); return false; } diff --git a/src/core/operationRepo/OperationRepo.test.ts b/src/core/operationRepo/OperationRepo.test.ts index 1eb071344..437c806f7 100644 --- a/src/core/operationRepo/OperationRepo.test.ts +++ b/src/core/operationRepo/OperationRepo.test.ts @@ -2,7 +2,7 @@ import { APP_ID, ONESIGNAL_ID, SUB_ID } from '__test__/constants'; import { db } from 'src/shared/database/client'; import type { IndexedDBSchema } from 'src/shared/database/types'; import { setConsentRequired } from 'src/shared/helpers/localStorage'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import { SubscriptionType } from 'src/shared/subscriptions/constants'; import { describe, expect, type Mock, vi } from 'vitest'; import { OperationModelStore } from '../modelRepo/OperationModelStore'; @@ -21,7 +21,7 @@ import { import { NewRecordsState } from './NewRecordsState'; import { OperationRepo } from './OperationRepo'; -vi.spyOn(Log, '_error').mockImplementation((msg) => { +vi.spyOn(Log, 'error').mockImplementation((msg) => { if (typeof msg === 'string' && msg.includes('Operation execution failed')) return ''; return msg; diff --git a/src/core/operationRepo/OperationRepo.ts b/src/core/operationRepo/OperationRepo.ts index ce5a5517d..7bf457737 100644 --- a/src/core/operationRepo/OperationRepo.ts +++ b/src/core/operationRepo/OperationRepo.ts @@ -6,7 +6,7 @@ import { } from 'src/core/types/operation'; import { db } from 'src/shared/database/client'; import { delay } from 'src/shared/helpers/general'; -import Log from 'src/shared/libraries/Log'; +import { debug, error } from 'src/shared/libraries/log'; import { type OperationModelStore } from '../modelRepo/OperationModelStore'; import { GroupComparisonType, type Operation } from '../operations/Operation'; import { @@ -80,11 +80,11 @@ export class OperationRepo implements IOperationRepo, IStartableService { public _pause(): void { clearInterval(this._timerID); this._timerID = undefined; - Log._debug('OperationRepo: Paused'); + debug('OperationRepo: Paused'); } public _enqueue(operation: Operation): void { - Log._debug(`OperationRepo.enqueue(operation: ${operation})`); + debug(`OperationRepo.enqueue(operation: ${operation})`); this._internalEnqueue( { @@ -97,7 +97,7 @@ export class OperationRepo implements IOperationRepo, IStartableService { } public async _enqueueAndWait(operation: Operation): Promise { - Log._debug(`OperationRepo.enqueueAndWaitoperation: ${operation})`); + debug(`OperationRepo.enqueueAndWaitoperation: ${operation})`); await new Promise((resolve, reject) => { this._internalEnqueue( @@ -121,7 +121,7 @@ export class OperationRepo implements IOperationRepo, IStartableService { (item) => item.operation._modelId === queueItem.operation._modelId, ); if (hasExisting) { - Log._debug( + debug( `OperationRepo: internalEnqueue - operation.modelId: ${queueItem.operation._modelId} already exists in the queue.`, ); return; @@ -143,7 +143,7 @@ export class OperationRepo implements IOperationRepo, IStartableService { let runningOps = false; this._timerID = setInterval(async () => { - if (runningOps) return Log._debug('Operations in progress'); + if (runningOps) return debug('Operations in progress'); const ops = this._getNextOps(this._executeBucket); @@ -172,7 +172,7 @@ export class OperationRepo implements IOperationRepo, IStartableService { const response = await executor._execute(operations); const idTranslations = response._idTranslations; - Log._debug(`OperationRepo: execute response = ${response._result}`); + debug(`OperationRepo: execute response = ${response._result}`); // Handle ID translations if (idTranslations) { @@ -199,7 +199,7 @@ export class OperationRepo implements IOperationRepo, IStartableService { case ExecutionResult._FailUnauthorized: case ExecutionResult._FailNoretry: case ExecutionResult._FailConflict: - Log._error(`Operation execution failed without retry: ${operations}`); + error(`Operation execution failed without retry: ${operations}`); ops.forEach((op) => { this._operationModelStore._remove(op.operation._modelId); }); @@ -218,7 +218,7 @@ export class OperationRepo implements IOperationRepo, IStartableService { break; case ExecutionResult._FailRetry: - Log._error(`Operation execution failed, retrying: ${operations}`); + error(`Operation execution failed, retrying: ${operations}`); // Add back all operations to front of queue [...ops].reverse().forEach((op) => { removeOpFromDB(op.operation); @@ -231,7 +231,7 @@ export class OperationRepo implements IOperationRepo, IStartableService { break; case ExecutionResult._FailPauseOpRepo: - Log._error(`Operation failed, pausing ops:${operations}`); + error(`Operation failed, pausing ops:${operations}`); this._pause(); ops.forEach((op) => op.resolver?.(false)); [...ops].reverse().forEach((op) => { @@ -263,7 +263,7 @@ export class OperationRepo implements IOperationRepo, IStartableService { await delay(OP_REPO_POST_CREATE_DELAY); } } catch (e) { - Log._error(`Error attempting to execute operation: ${ops}`, e); + error(`Error attempting to execute operation: ${ops}`, e); // On failure remove operations from store ops.forEach((op) => { @@ -277,14 +277,14 @@ export class OperationRepo implements IOperationRepo, IStartableService { retries: number, retryAfterSeconds?: number, ): Promise { - Log._debug(`retryAfterSeconds: ${retryAfterSeconds}`); + debug(`retryAfterSeconds: ${retryAfterSeconds}`); const retryAfterSecondsMs = (retryAfterSeconds || 0) * 1000; const delayForOnRetries = retries * OP_REPO_DEFAULT_FAIL_RETRY_BACKOFF; const delayFor = Math.max(delayForOnRetries, retryAfterSecondsMs); if (delayFor < 1) return; - Log._error(`Operations being delay for: ${delayFor} ms`); + error(`Operations being delay for: ${delayFor} ms`); await delay(delayFor); } diff --git a/src/entries/pageSdkInit.test.ts b/src/entries/pageSdkInit.test.ts index ddd2b3736..cce7bc0cf 100644 --- a/src/entries/pageSdkInit.test.ts +++ b/src/entries/pageSdkInit.test.ts @@ -2,7 +2,7 @@ import { APP_ID } from '__test__/constants'; import { TestEnvironment } from '__test__/support/environment/TestEnvironment'; import { server } from '__test__/support/mocks/server'; import { http, HttpResponse } from 'msw'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; // need to wait for full OperationRepo rework describe('pageSdkInit', () => { @@ -42,7 +42,7 @@ describe('pageSdkInit', () => { }); test('can process deferred items long after page init', async () => { - vi.spyOn(Log, '_error').mockImplementation(() => ''); + vi.spyOn(Log, 'error').mockImplementation(() => ''); await import('./pageSdkInit'); const initSpy = vi.spyOn(window.OneSignal, 'init'); diff --git a/src/entries/pageSdkInit.ts b/src/entries/pageSdkInit.ts index 3ad263e84..1118164e5 100644 --- a/src/entries/pageSdkInit.ts +++ b/src/entries/pageSdkInit.ts @@ -4,7 +4,6 @@ */ import type { OneSignalDeferredLoadedCallback } from 'src/page/models/OneSignalDeferredLoadedCallback'; import OneSignal from '../onesignal/OneSignal'; -import Log from '../shared/libraries/Log'; import { getSdkLoadCount, incrementSdkLoadCount } from '../shared/utils/utils'; /** @@ -12,6 +11,7 @@ import { getSdkLoadCount, incrementSdkLoadCount } from '../shared/utils/utils'; * generate a separate CSS file. */ import './stylesheet.scss'; +import { debug, error, warn } from 'src/shared/libraries/log'; async function processOneSignalDeferredArray( onesignalDeferred: OneSignalDeferredLoadedCallback[], @@ -21,7 +21,7 @@ async function processOneSignalDeferredArray( await OneSignal.push(item); } catch (e) { // Catch and log error here so other elements still run - Log._error(e); + error(e); } } } @@ -29,11 +29,11 @@ async function processOneSignalDeferredArray( function onesignalSdkInit() { incrementSdkLoadCount(); if (getSdkLoadCount() > 1) { - Log._warn( + warn( `OneSignal: The web push SDK is included more than once. For optimal performance, please include our ` + `SDK only once on your page.`, ); - Log._debug( + debug( `OneSignal: Exiting from SDK initialization to prevent double-initialization errors. ` + `Occurred ${getSdkLoadCount()} times.`, ); diff --git a/src/entries/pageSdkInit2.test.ts b/src/entries/pageSdkInit2.test.ts index 5e0aba987..1b4c70e3c 100644 --- a/src/entries/pageSdkInit2.test.ts +++ b/src/entries/pageSdkInit2.test.ts @@ -19,7 +19,7 @@ import { updateIdentityModel, } from '__test__/support/helpers/setup'; import { SubscriptionModel } from 'src/core/models/SubscriptionModel'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import { IDManager } from 'src/shared/managers/IDManager'; describe('pageSdkInit 2', () => { @@ -58,7 +58,7 @@ describe('pageSdkInit 2', () => { response: emailSubModel, }); - const errorSpy = vi.spyOn(Log, '_error').mockImplementation(() => ''); + const errorSpy = vi.spyOn(Log, 'error').mockImplementation(() => ''); // wait for init so it can initialize user namespace otherwise it won't be available for addEmail window.OneSignalDeferred = []; diff --git a/src/onesignal/DebugNamesapce.ts b/src/onesignal/DebugNamesapce.ts index 23a8ad958..9ee49e565 100644 --- a/src/onesignal/DebugNamesapce.ts +++ b/src/onesignal/DebugNamesapce.ts @@ -1,4 +1,4 @@ -import Log from '../shared/libraries/Log'; +import { setLevel } from 'src/shared/libraries/log'; export default class DebugNamespace { /** @@ -6,6 +6,6 @@ export default class DebugNamespace { * @param logLevel - string */ setLogLevel(logLevel: string) { - Log._setLevel(logLevel); + setLevel(logLevel); } } diff --git a/src/onesignal/NotificationsNamespace.test.ts b/src/onesignal/NotificationsNamespace.test.ts index 7ee0fdd1d..cb381b1e2 100644 --- a/src/onesignal/NotificationsNamespace.test.ts +++ b/src/onesignal/NotificationsNamespace.test.ts @@ -18,7 +18,7 @@ import { EmptyArgumentError, WrongTypeArgumentError, } from 'src/shared/errors/common'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import * as utils from 'src/shared/utils/utils'; import NotificationsNamespace from './NotificationsNamespace'; @@ -64,7 +64,7 @@ test('should set the default title', async () => { ); }); -const warnSpy = vi.spyOn(Log, '_warn'); +const warnSpy = vi.spyOn(Log, 'warn'); describe('Consent Required', () => { beforeEach(() => { OneSignal.setConsentRequired(true); @@ -113,8 +113,8 @@ describe('requestPermission', () => { }); test('should expose errors', async () => { - const debugSpy = vi.spyOn(Log, '_debug').mockImplementation(() => ''); - vi.spyOn(Log, '_error').mockImplementation(() => ''); + const debugSpy = vi.spyOn(Log, 'debug').mockImplementation(() => ''); + vi.spyOn(Log, 'error').mockImplementation(() => ''); MockNotification.permission = 'denied'; const notifications = new NotificationsNamespace(); diff --git a/src/onesignal/OneSignal.test.ts b/src/onesignal/OneSignal.test.ts index c13baeb76..d0f7e4307 100644 --- a/src/onesignal/OneSignal.test.ts +++ b/src/onesignal/OneSignal.test.ts @@ -50,7 +50,7 @@ import { setPushToken } from 'src/shared/database/subscription'; import type { SubscriptionSchema } from 'src/shared/database/types'; import { registerForPushNotifications } from 'src/shared/helpers/init'; import * as MainHelper from 'src/shared/helpers/main'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import { IDManager } from 'src/shared/managers/IDManager'; import { SubscriptionManagerPage } from 'src/shared/managers/subscription/page'; @@ -1191,9 +1191,9 @@ Object.defineProperty(global.navigator, 'serviceWorker', { writable: true, }); -vi.spyOn(Log, '_error').mockImplementation(() => ''); -const debugSpy = vi.spyOn(Log, '_debug'); -const warnSpy = vi.spyOn(Log, '_warn'); +vi.spyOn(Log, 'error').mockImplementation(() => ''); +const debugSpy = vi.spyOn(Log, 'debug'); +const warnSpy = vi.spyOn(Log, 'warn'); const getPropertiesItem = async () => (await db.getAll('properties'))[0]; diff --git a/src/onesignal/OneSignal.ts b/src/onesignal/OneSignal.ts index 336ba91b1..a854ac6d9 100644 --- a/src/onesignal/OneSignal.ts +++ b/src/onesignal/OneSignal.ts @@ -40,12 +40,12 @@ import LoginManager from '../page/managers/LoginManager'; import Context from '../page/models/Context'; import type { OneSignalDeferredLoadedCallback } from '../page/models/OneSignalDeferredLoadedCallback'; import Emitter from '../shared/libraries/Emitter'; -import Log from '../shared/libraries/Log'; import DebugNamespace from './DebugNamesapce'; import NotificationsNamespace from './NotificationsNamespace'; import { SessionNamespace } from './SessionNamespace'; import SlidedownNamespace from './SlidedownNamespace'; import UserNamespace from './UserNamespace'; +import { debug, info, warn } from 'src/shared/libraries/log'; export default class OneSignal { static _consentGiven = false; @@ -64,7 +64,7 @@ export default class OneSignal { private static async _initializeConfig(options: AppUserConfig) { const appConfig = await getAppConfig(options); - Log._debug('OneSignal: Final web app config:', appConfig); + debug('OneSignal: Final web app config:', appConfig); // Workaround to temp assign config so that it can be used in context. OneSignal.config = appConfig; @@ -127,7 +127,7 @@ export default class OneSignal { */ static async init(options: AppUserConfig) { logMethodCall('init'); - Log._debug( + debug( `Browser Environment: ${getBrowserName()} ${getBrowserVersion()}`, ); @@ -145,7 +145,7 @@ export default class OneSignal { * support on Chrome/Firefox and don't intend to support Safari but don't * place conditional initialization checks. */ - Log._warn(MissingSafariWebIdError); + warn(MissingSafariWebIdError); return; } @@ -196,7 +196,7 @@ export default class OneSignal { ) await __init(); else { - Log._debug( + debug( 'OneSignal: Waiting for DOMContentLoaded or readyStateChange event before continuing' + ' initialization...', ); @@ -297,11 +297,11 @@ function processItem( } } -Log._info( +info( `OneSignal Web SDK loaded (version ${VERSION}, ${windowEnvString} environment).`, ); -Log._debug( +debug( `Current Page URL: ${ typeof location === 'undefined' ? 'NodeJS' : location.href }`, diff --git a/src/onesignal/PushSubscriptionNamespace.ts b/src/onesignal/PushSubscriptionNamespace.ts index a82459994..d9d53c0a6 100644 --- a/src/onesignal/PushSubscriptionNamespace.ts +++ b/src/onesignal/PushSubscriptionNamespace.ts @@ -7,6 +7,7 @@ import { AppIDMissingError, MalformedArgumentError, } from 'src/shared/errors/common'; +import { error, warn } from 'src/shared/libraries/log'; import { checkAndTriggerSubscriptionChanged, onInternalSubscriptionSet, @@ -14,7 +15,6 @@ import { import { IDManager } from 'src/shared/managers/IDManager'; import type { EventsMap } from 'src/shared/services/types'; import { EventListenerBase } from '../page/userModel/EventListenerBase'; -import Log from '../shared/libraries/Log'; import { isCompleteSubscriptionObject } from '../shared/managers/utils'; import { Subscription } from '../shared/models/Subscription'; import { @@ -35,7 +35,7 @@ export default class PushSubscriptionNamespace extends EventListenerBase { ) { super(); if (!initialize || !subscription) { - Log._warn( + warn( `PushSubscriptionNamespace: skipping initialization. One or more required params are falsy: initialize: ${initialize}, subscription: ${subscription}`, ); return; @@ -53,7 +53,7 @@ export default class PushSubscriptionNamespace extends EventListenerBase { } }) .catch((e) => { - Log._error(e); + error(e); }); OneSignal._emitter.on('change', async (change) => { @@ -133,10 +133,10 @@ export default class PushSubscriptionNamespace extends EventListenerBase { subscriptionFromDb.optedOut = !enabled; await setSubscription(subscriptionFromDb); onInternalSubscriptionSet(subscriptionFromDb.optedOut).catch((e) => { - Log._error(e); + error(e); }); checkAndTriggerSubscriptionChanged().catch((e) => { - Log._error(e); + error(e); }); } } diff --git a/src/onesignal/SessionNamespace.ts b/src/onesignal/SessionNamespace.ts index 0a890d29b..425d0a985 100644 --- a/src/onesignal/SessionNamespace.ts +++ b/src/onesignal/SessionNamespace.ts @@ -1,6 +1,6 @@ import OutcomesHelper from '../shared/helpers/OutcomesHelper'; -import Log from '../shared/libraries/Log'; import { OutcomeAttributionType } from '../shared/models/Outcomes'; +import { error, warn } from 'src/shared/libraries/log'; export class SessionNamespace { async sendOutcome( @@ -9,7 +9,7 @@ export class SessionNamespace { ): Promise { const config = OneSignal.config?.userConfig.outcomes; if (!config) { - Log._error(`Could not send ${outcomeName}. No outcomes config found.`); + error(`Could not send ${outcomeName}. No outcomes config found.`); return; } @@ -23,7 +23,7 @@ export class SessionNamespace { typeof outcomeWeight !== 'undefined' && typeof outcomeWeight !== 'number' ) { - Log._error('Outcome weight can only be a number if present.'); + error('Outcome weight can only be a number if present.'); return; } @@ -43,7 +43,7 @@ export class SessionNamespace { async sendUniqueOutcome(outcomeName: string): Promise { const config = OneSignal.config?.userConfig.outcomes; if (!config) { - Log._error(`Could not send ${outcomeName}. No outcomes config found.`); + error(`Could not send ${outcomeName}. No outcomes config found.`); return; } @@ -60,7 +60,7 @@ export class SessionNamespace { const outcomeAttribution = await outcomesHelper._getAttribution(); if (outcomeAttribution.type === OutcomeAttributionType._NotSupported) { - Log._warn( + warn( 'You are on a free plan. Please upgrade to use this functionality.', ); return; @@ -80,7 +80,7 @@ export class SessionNamespace { newNotifsToAttributeWithOutcome, ) ) { - Log._warn(`'${outcomeName}' was already reported for all notifications.`); + warn(`'${outcomeName}' was already reported for all notifications.`); return; } diff --git a/src/onesignal/SlidedownNamespace.test.ts b/src/onesignal/SlidedownNamespace.test.ts index c308ab7ed..5e1ff3348 100644 --- a/src/onesignal/SlidedownNamespace.test.ts +++ b/src/onesignal/SlidedownNamespace.test.ts @@ -1,8 +1,8 @@ import { TestEnvironment } from '__test__/support/environment/TestEnvironment'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import SlidedownNamespace from './SlidedownNamespace'; -const warnSpy = vi.spyOn(Log, '_warn'); +const warnSpy = vi.spyOn(Log, 'warn'); describe('Consent Required', () => { beforeEach(() => { diff --git a/src/onesignal/User.ts b/src/onesignal/User.ts index 0fa19e4cf..7a2462d01 100644 --- a/src/onesignal/User.ts +++ b/src/onesignal/User.ts @@ -11,7 +11,7 @@ import { } from 'src/shared/errors/common'; import { getAppId } from 'src/shared/helpers/main'; import { isObject, isValidEmail } from 'src/shared/helpers/validators'; -import Log from 'src/shared/libraries/Log'; +import { error } from 'src/shared/libraries/log'; import { IDManager } from 'src/shared/managers/IDManager'; import { NotificationType, @@ -241,12 +241,12 @@ export default class User { const onesignalId = OneSignal._coreDirector._getIdentityModel()._onesignalId; if (IDManager._isLocalId(onesignalId) && !hasLoginOp(onesignalId)) { - Log._error('User must be logged in first.'); + error('User must be logged in first.'); return; } if (!isObjectSerializable(properties)) { - Log._error('Properties must be JSON-serializable'); + error('Properties must be JSON-serializable'); return; } logMethodCall('trackEvent', { name, properties }); diff --git a/src/onesignal/UserNamespace.test.ts b/src/onesignal/UserNamespace.test.ts index 127760115..402808ad6 100644 --- a/src/onesignal/UserNamespace.test.ts +++ b/src/onesignal/UserNamespace.test.ts @@ -3,15 +3,15 @@ import { TestEnvironment } from '__test__/support/environment/TestEnvironment'; import { updateIdentityModel } from '__test__/support/helpers/setup'; import { IdentityConstants } from 'src/core/constants'; import { ModelChangeTags } from 'src/core/types/models'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import { IDManager } from 'src/shared/managers/IDManager'; import type { UserChangeEvent } from '../page/models/UserChangeEvent'; import { Subscription } from '../shared/models/Subscription'; import User from './User'; import UserNamespace from './UserNamespace'; -const errorSpy = vi.spyOn(Log, '_error').mockImplementation(() => ''); -const warnSpy = vi.spyOn(Log, '_warn').mockImplementation(() => ''); +const errorSpy = vi.spyOn(Log, 'error').mockImplementation(() => ''); +const warnSpy = vi.spyOn(Log, 'warn').mockImplementation(() => ''); vi.useFakeTimers(); const setup = () => { diff --git a/src/onesignal/userDirector.ts b/src/onesignal/userDirector.ts index 48366ba17..7e8b9c6ea 100644 --- a/src/onesignal/userDirector.ts +++ b/src/onesignal/userDirector.ts @@ -2,7 +2,7 @@ import { IdentityModel } from 'src/core/models/IdentityModel'; import { PropertiesModel } from 'src/core/models/PropertiesModel'; import { CreateSubscriptionOperation } from 'src/core/operations/CreateSubscriptionOperation'; import { LoginUserOperation } from 'src/core/operations/LoginUserOperation'; -import Log from 'src/shared/libraries/Log'; +import { error } from 'src/shared/libraries/log'; import { IDManager } from 'src/shared/managers/IDManager'; import { getAppId } from '../shared/helpers/main'; @@ -16,7 +16,7 @@ export async function createUserOnServer(): Promise { const hasExternalId = !!identityModel._externalId; if (!hasAnySubscription && !hasExternalId) { - Log._error('No subscriptions or external ID found, skipping user creation'); + error('No subscriptions or external ID found, skipping user creation'); return; } diff --git a/src/page/bell/Bell.ts b/src/page/bell/Bell.ts index 8523edd17..84523821b 100755 --- a/src/page/bell/Bell.ts +++ b/src/page/bell/Bell.ts @@ -7,6 +7,7 @@ import { removeDomElement, } from 'src/shared/helpers/dom'; import { delay, nothing } from 'src/shared/helpers/general'; +import { debug, error, info } from 'src/shared/libraries/log'; import type { BellPosition, BellSize, @@ -14,22 +15,21 @@ import type { } from 'src/shared/prompts/types'; import { wasPromptOfTypeDismissed } from '../../shared/helpers/dismiss'; import { getNotificationIcons } from '../../shared/helpers/main'; -import Log from '../../shared/libraries/Log'; import OneSignalEvent from '../../shared/services/OneSignalEvent'; import { once } from '../../shared/utils/utils'; import { DismissPrompt } from '../models/Dismiss'; import { ResourceLoadState } from '../services/DynamicResourceLoader'; import Badge from './Badge'; import Button from './Button'; -import Dialog from './Dialog'; -import Launcher from './Launcher'; -import Message from './Message'; import { BellState, type BellStateValue, MESSAGE_TIMEOUT, MessageType, } from './constants'; +import Dialog from './Dialog'; +import Launcher from './Launcher'; +import Message from './Message'; const logoSvg = ``; @@ -272,7 +272,7 @@ export default class Bell { this._hovering = false; }) .catch((err) => { - Log._error(err); + error(err); }); }); @@ -407,7 +407,7 @@ export default class Bell { const sdkStylesLoadResult = await OneSignal._context._dynamicResourceLoader._loadSdkStylesheet(); if (sdkStylesLoadResult !== ResourceLoadState._Loaded) { - Log._debug('Not showing notify button because styles failed to load.'); + debug('Not showing notify button because styles failed to load.'); return; } @@ -488,7 +488,7 @@ export default class Bell { this._setCustomColorsIfSpecified(); this._addBadgeShadow(); - Log._info('Showing the notify button.'); + info('Showing the notify button.'); await (isPushEnabled ? this._launcher._inactivate() : nothing()) .then(() => { @@ -543,7 +543,7 @@ export default class Bell { const element = this._launcher._element as HTMLElement; if (!element) { - Log._error('Could not find bell dom element'); + error('Could not find bell dom element'); return; } // Reset styles first @@ -701,7 +701,7 @@ export default class Bell { } }) .catch((e) => { - Log._error(e); + error(e); }); } diff --git a/src/page/bell/Message.ts b/src/page/bell/Message.ts index 9f4b96733..918e435aa 100755 --- a/src/page/bell/Message.ts +++ b/src/page/bell/Message.ts @@ -1,6 +1,6 @@ import { decodeHtmlEntities } from 'src/shared/helpers/dom'; import { delay, nothing } from 'src/shared/helpers/general'; -import Log from 'src/shared/libraries/Log'; +import { debug } from 'src/shared/libraries/log'; import AnimatedElement from './AnimatedElement'; import type Bell from './Bell'; import { BellState } from './constants'; @@ -25,7 +25,7 @@ export default class Message extends AnimatedElement { } _display(type: string, content: string, duration = 0) { - Log._debug(`Calling display(${type}, ${content}, ${duration}).`); + debug(`Calling display(${type}, ${content}, ${duration}).`); return (this._shown ? this._hide() : nothing()) .then(() => { this._content = decodeHtmlEntities(content); diff --git a/src/page/managers/LoginManager.ts b/src/page/managers/LoginManager.ts index 875c185c9..e142e21da 100644 --- a/src/page/managers/LoginManager.ts +++ b/src/page/managers/LoginManager.ts @@ -4,12 +4,12 @@ import { TransferSubscriptionOperation } from 'src/core/operations/TransferSubsc import { ModelChangeTags } from 'src/core/types/models'; import { db } from 'src/shared/database/client'; import { getAppId } from 'src/shared/helpers/main'; +import { debug } from 'src/shared/libraries/log'; import { IDManager } from 'src/shared/managers/IDManager'; import { createUserOnServer, resetUserModels, } from '../../onesignal/userDirector'; -import Log from '../../shared/libraries/Log'; export default class LoginManager { // Other internal classes should await on this if they access users @@ -39,7 +39,7 @@ export default class LoginManager { // if the current externalId is the same as the one we're trying to set, do nothing if (currentExternalId === externalId) { - Log._debug('Login: External ID already set, skipping login'); + debug('Login: External ID already set, skipping login'); return; } @@ -91,7 +91,7 @@ export default class LoginManager { const identityModel = OneSignal._coreDirector._getIdentityModel(); if (!identityModel._externalId) - return Log._debug('Logout: User is not logged in, skipping logout'); + return debug('Logout: User is not logged in, skipping logout'); resetUserModels(); diff --git a/src/page/managers/PromptsManager.ts b/src/page/managers/PromptsManager.ts index 82478c0e7..5e791378c 100644 --- a/src/page/managers/PromptsManager.ts +++ b/src/page/managers/PromptsManager.ts @@ -2,7 +2,7 @@ import type { ContextInterface } from 'src/shared/context/types'; import { delay } from 'src/shared/helpers/general'; import { registerForPushNotifications } from 'src/shared/helpers/init'; import { getLocalPageViewCount } from 'src/shared/helpers/localStorage'; -import Log from 'src/shared/libraries/Log'; +import { debug, error, warn } from 'src/shared/libraries/log'; import { CONFIG_DEFAULTS_SLIDEDOWN_OPTIONS, DelayedPromptType, @@ -139,7 +139,7 @@ export class PromptsManager { ): Promise { logMethodCall('internalShowDelayedPrompt'); if (typeof timeDelaySeconds !== 'number') { - Log._error('internalShowDelayedPrompt: timeDelay not a number'); + error('internalShowDelayedPrompt: timeDelay not a number'); return; } @@ -171,7 +171,7 @@ export class PromptsManager { await this._internalShowSmsAndEmailSlidedown(options); break; default: - Log._error('Invalid Delayed Prompt type'); + error('Invalid Delayed Prompt type'); } } @@ -179,7 +179,7 @@ export class PromptsManager { logMethodCall('internalShowNativePrompt'); if (this._isNativePromptShowing) { - Log._debug('Already showing autoprompt. Abort showing a native prompt.'); + debug('Already showing autoprompt. Abort showing a native prompt.'); return false; } @@ -202,7 +202,7 @@ export class PromptsManager { const sdkStylesLoadResult = await this._context._dynamicResourceLoader._loadSdkStylesheet(); if (sdkStylesLoadResult !== ResourceLoadState._Loaded) { - Log._debug( + debug( 'Not showing slidedown permission message because styles failed to load.', ); return; @@ -274,13 +274,13 @@ export class PromptsManager { if (!slidedownPromptOptions) { if (typeToPullFromConfig !== DelayedPromptType._Push) { - Log._error( + error( `OneSignal: slidedown of type '${typeToPullFromConfig}' couldn't be shown. Check your configuration` + ` on the OneSignal dashboard or your custom code initialization.`, ); return; } else { - Log._warn( + warn( `The OneSignal 'push' slidedown will be shown with default text settings.` + ` To customize, see the OneSignal documentation.`, ); @@ -315,15 +315,11 @@ export class PromptsManager { switch (type) { case DelayedPromptType._Push: case DelayedPromptType._Category: - Log._debug( - 'Setting flag to not show the slidedown to the user again.', - ); + debug('Setting flag to not show the slidedown to the user again.'); markPromptDismissedWithType(DismissPrompt._Push); break; default: - Log._debug( - 'Setting flag to not show the slidedown to the user again.', - ); + debug('Setting flag to not show the slidedown to the user again.'); markPromptDismissedWithType(DismissPrompt._NonPush); break; } diff --git a/src/page/managers/slidedownManager/SlidedownManager.test.ts b/src/page/managers/slidedownManager/SlidedownManager.test.ts index 88163bc6c..d74a16c6b 100644 --- a/src/page/managers/slidedownManager/SlidedownManager.test.ts +++ b/src/page/managers/slidedownManager/SlidedownManager.test.ts @@ -14,12 +14,12 @@ import { import { MockServiceWorker } from '__test__/support/mocks/MockServiceWorker'; import { SlidedownManager } from 'src/page/managers/slidedownManager/SlidedownManager'; import ChannelCaptureContainer from 'src/page/slidedown/ChannelCaptureContainer'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import { SubscriptionManagerPage } from 'src/shared/managers/subscription/page'; import { DelayedPromptType } from 'src/shared/prompts/constants'; import { SubscriptionType } from 'src/shared/subscriptions/constants'; -vi.spyOn(Log, '_error').mockImplementation(() => ''); +vi.spyOn(Log, 'error').mockImplementation(() => ''); describe('Slidedown Types', () => { beforeEach(() => { @@ -184,7 +184,7 @@ describe('Slidedown Types', () => { }); }); -const warnSpy = vi.spyOn(Log, '_warn'); +const warnSpy = vi.spyOn(Log, 'warn'); describe('Consent Required', () => { beforeEach(() => { TestEnvironment.initialize(); diff --git a/src/page/managers/slidedownManager/SlidedownManager.ts b/src/page/managers/slidedownManager/SlidedownManager.ts index 617f4c337..f25a84be4 100644 --- a/src/page/managers/slidedownManager/SlidedownManager.ts +++ b/src/page/managers/slidedownManager/SlidedownManager.ts @@ -12,6 +12,7 @@ import { import { InvalidChannelInputField } from 'src/shared/errors/constants'; import { delay } from 'src/shared/helpers/general'; import { registerForPushNotifications } from 'src/shared/helpers/init'; +import { debug, error, info, warn } from 'src/shared/libraries/log'; import { CONFIG_DEFAULTS_SLIDEDOWN_OPTIONS, DelayedPromptType, @@ -28,7 +29,6 @@ import { markPromptDismissedWithType, wasPromptOfTypeDismissed, } from '../../../shared/helpers/dismiss'; -import Log from '../../../shared/libraries/Log'; import type { PushSubscriptionState } from '../../../shared/models/PushSubscriptionState'; import { DismissPrompt } from '../../models/Dismiss'; import ChannelCaptureContainer from '../../slidedown/ChannelCaptureContainer'; @@ -80,7 +80,7 @@ export class SlidedownManager { return true; } - Log._info(new Error('User is already subscribed')); + info(new Error('User is already subscribed')); return false; } @@ -91,7 +91,7 @@ export class SlidedownManager { } if (permissionDenied) { - Log._info(PermissionBlockedError); + info(PermissionBlockedError); return false; } } else { @@ -105,12 +105,12 @@ export class SlidedownManager { const bothSubscribed = smsSubscribed && emailSubscribed; if (smsSubscribed && slidedownType === DelayedPromptType._Sms) { - Log._info(ExistingChannelError(DelayedPromptType._Sms)); + info(ExistingChannelError(DelayedPromptType._Sms)); return false; } if (emailSubscribed && slidedownType === DelayedPromptType._Email) { - Log._info(ExistingChannelError(DelayedPromptType._Email)); + info(ExistingChannelError(DelayedPromptType._Email)); return false; } @@ -118,7 +118,7 @@ export class SlidedownManager { bothSubscribed && slidedownType === DelayedPromptType._SmsAndEmail ) { - Log._info(ExistingChannelError(DelayedPromptType._SmsAndEmail)); + info(ExistingChannelError(DelayedPromptType._SmsAndEmail)); return false; } } @@ -127,9 +127,7 @@ export class SlidedownManager { } if (wasDismissed && !options.force && !options.isInUpdateMode) { - Log._info( - new Error(`${slidedownType || 'unknown'} was previously dismissed`), - ); + info(new Error(`${slidedownType || 'unknown'} was previously dismissed`)); return false; } @@ -320,10 +318,7 @@ export class SlidedownManager { taggingContainer._mount(categories, tagsForComponent); } catch (e) { - Log._error( - 'OneSignal: Attempted to create tagging container with error', - e, - ); + error('OneSignal: Attempted to create tagging container with error', e); } } @@ -343,7 +338,7 @@ export class SlidedownManager { } } } catch (e) { - Log._error( + error( 'OneSignal: Attempted to create channel capture container with error', e, ); @@ -381,7 +376,7 @@ export class SlidedownManager { break; } } catch (e) { - Log._warn('OneSignal Slidedown failed to update:', e); + warn('OneSignal Slidedown failed to update:', e); // Display update error this._slidedown._removeSaveState(); this._slidedown._setFailureState(); @@ -407,11 +402,11 @@ export class SlidedownManager { switch (slidedownType) { case DelayedPromptType._Push: case DelayedPromptType._Category: - Log._debug('Setting flag to not show the slidedown to the user again.'); + debug('Setting flag to not show the slidedown to the user again.'); markPromptDismissedWithType(DismissPrompt._Push); break; default: - Log._debug('Setting flag to not show the slidedown to the user again.'); + debug('Setting flag to not show the slidedown to the user again.'); markPromptDismissedWithType(DismissPrompt._NonPush); break; } @@ -449,7 +444,7 @@ export class SlidedownManager { return; } } catch (e) { - Log._warn('checkIfSlidedownShouldBeShown returned an error', e); + warn('checkIfSlidedownShouldBeShown returned an error', e); return; } @@ -468,10 +463,10 @@ export class SlidedownManager { this._slidedown = new Slidedown(slidedownPromptOptions); await this._slidedown._create(options.isInUpdateMode); await this._mountAuxiliaryContainers(options); - Log._debug('Showing OneSignal Slidedown'); + debug('Showing OneSignal Slidedown'); Slidedown._triggerSlidedownEvent('slidedownShown'); } catch (e) { - Log._error('There was an error showing the OneSignal Slidedown:', e); + error('There was an error showing the OneSignal Slidedown:', e); this._setIsSlidedownShowing(false); this._slidedown?._close(); } diff --git a/src/page/managers/tagManager/TagManager.ts b/src/page/managers/tagManager/TagManager.ts index 9d6cc8e22..1f28168df 100644 --- a/src/page/managers/tagManager/TagManager.ts +++ b/src/page/managers/tagManager/TagManager.ts @@ -8,8 +8,8 @@ import { getObjectDifference, isTagObjectEmpty, } from 'src/shared/utils/tags'; -import Log from '../../../shared/libraries/Log'; import type { ITagManager } from './types'; +import { info, warn } from 'src/shared/libraries/log'; /** * Manages tags for the TaggingContainer @@ -28,7 +28,7 @@ export default class TagManager implements ITagManager { * @returns Promise resolving TagsObject if successful, {} if no change detected, null if failed */ public async _sendTags(): Promise { - Log._info('Category Slidedown Local Tags:', this._tagsFromTaggingContainer); + info('Category Slidedown Local Tags:', this._tagsFromTaggingContainer); const localTagsConvertedToApi = convertTagsBooleansToApi( this._tagsFromTaggingContainer, @@ -43,7 +43,7 @@ export default class TagManager implements ITagManager { await OneSignal.User.addTags(finalTagsObject); return finalTagsObject; } - Log._warn( + warn( 'OneSignal: no change detected in Category preferences. Skipping tag update.', ); // no change detected, return {} diff --git a/src/page/slidedown/ChannelCaptureContainer.ts b/src/page/slidedown/ChannelCaptureContainer.ts index e0df71469..1041c7b92 100644 --- a/src/page/slidedown/ChannelCaptureContainer.ts +++ b/src/page/slidedown/ChannelCaptureContainer.ts @@ -3,12 +3,12 @@ import { getDomElementOrStub, removeCssClass, } from 'src/shared/helpers/dom'; +import { error } from 'src/shared/libraries/log'; import { DelayedPromptType } from 'src/shared/prompts/constants'; import type { DelayedPromptTypeValue, SlidedownPromptOptions, } from 'src/shared/prompts/types'; -import Log from '../../shared/libraries/Log'; import { CHANNEL_CAPTURE_CONTAINER_CSS_CLASSES, CHANNEL_CAPTURE_CONTAINER_CSS_IDS, @@ -194,7 +194,7 @@ export default class ChannelCaptureContainer { }, ); } else { - Log._error( + error( 'OneSignal: there was a problem initializing International Telephone Input', ); } @@ -385,7 +385,7 @@ export default class ChannelCaptureContainer { ); if (!validationElement || !inputElement) { - Log._error("OneSignal: couldn't find slidedown validation element"); + error("OneSignal: couldn't find slidedown validation element"); return; } @@ -415,7 +415,7 @@ export default class ChannelCaptureContainer { ); if (!validationElement || !inputElement) { - Log._error("OneSignal: couldn't find slidedown validation element"); + error("OneSignal: couldn't find slidedown validation element"); return; } diff --git a/src/shared/api/base.ts b/src/shared/api/base.ts index f05e45b79..c3fedc741 100644 --- a/src/shared/api/base.ts +++ b/src/shared/api/base.ts @@ -3,7 +3,7 @@ import { getOneSignalApiUrl } from '../environment/detect'; import { AppIDMissingError, RetryLimitError } from '../errors/common'; import { delay } from '../helpers/general'; import { isValidUuid } from '../helpers/validators'; -import Log from '../libraries/Log'; +import { error } from '../libraries/log'; import type { APIHeaders } from '../models/APIHeaders'; import { IS_SERVICE_WORKER, VERSION } from '../utils/env'; @@ -124,9 +124,7 @@ async function executeFetch( if (e instanceof Error && e.name === 'TypeError') { // start with 10 seconds, then 20 seconds, then 30 seconds await delay(retry > 3 ? (6 - retry) * RETRY_MS : 3 * RETRY_MS); - Log._error( - `OneSignal: Network timed out while calling ${url}. Retrying...`, - ); + error(`OneSignal: Network timed out while calling ${url}. Retrying...`); return executeFetch(url, contents, retry - 1); } throw new Error(`Failed to execute HTTP call: ${e}`); diff --git a/src/shared/api/shared.test.ts b/src/shared/api/shared.test.ts index df5b279f0..2dc048477 100644 --- a/src/shared/api/shared.test.ts +++ b/src/shared/api/shared.test.ts @@ -1,10 +1,10 @@ import { APP_ID } from '__test__/constants'; import { server } from '__test__/support/mocks/server'; import { http, HttpResponse } from 'msw'; -import Log from '../libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import * as OneSignalApiShared from './shared'; -const LogErrorSpy = vi.spyOn(Log, '_error').mockImplementation(() => ''); +const LogErrorSpy = vi.spyOn(Log, 'error').mockImplementation(() => ''); describe('OneSignalApiShared', () => { test('can send outcome ', async () => { diff --git a/src/shared/api/shared.ts b/src/shared/api/shared.ts index 6943c8729..40e95736c 100644 --- a/src/shared/api/shared.ts +++ b/src/shared/api/shared.ts @@ -1,12 +1,12 @@ -import Log from '../libraries/Log'; import type { OutcomeRequestData } from '../outcomes/types'; import * as OneSignalApiBase from './base'; +import { error, info } from 'src/shared/libraries/log'; export async function sendOutcome(data: OutcomeRequestData): Promise { - Log._info('Outcome payload:', data); + info('Outcome payload:', data); try { await OneSignalApiBase.post('outcomes/measure', data); } catch (e) { - Log._error('sendOutcome', e); + error('sendOutcome', e); } } diff --git a/src/shared/api/sw.ts b/src/shared/api/sw.ts index 9a929d531..c0776575a 100644 --- a/src/shared/api/sw.ts +++ b/src/shared/api/sw.ts @@ -4,7 +4,6 @@ import type { IUpdateUser } from 'src/core/types/api'; import type { ServerAppConfig } from '../config/types'; import { enforceAlias, enforceAppId } from '../context/helpers'; import { getSubscriptionType } from '../environment/detect'; -import Log from '../libraries/Log'; import type { DeliveryPlatformKindValue } from '../models/DeliveryPlatformKind'; import { OutcomeAttributionType, @@ -14,6 +13,7 @@ import type { OutcomeRequestData } from '../outcomes/types'; import { NotificationType } from '../subscriptions/constants'; import * as OneSignalApiBase from './base'; import { sendOutcome } from './shared'; +import { debug } from 'src/shared/libraries/log'; export async function downloadSWServerAppConfig( appId: string, @@ -51,7 +51,7 @@ export async function getUserIdFromSubscriptionIdentifier( } }) .catch((e) => { - Log._debug('Error getting user ID from subscription identifier:', e); + debug('Error getting user ID from subscription identifier:', e); return null; }); } @@ -86,7 +86,7 @@ export async function updateUserSession( updateUserPayload, ); } catch (e) { - Log._debug('Error updating user session:', e); + debug('Error updating user session:', e); } } @@ -138,6 +138,6 @@ export async function sendSessionDuration( await sendOutcome(outcomePayload); } } catch (e) { - Log._debug('Error sending session duration:', e); + debug('Error sending session duration:', e); } } diff --git a/src/shared/database/client.ts b/src/shared/database/client.ts index 48f579801..f3c3270c3 100644 --- a/src/shared/database/client.ts +++ b/src/shared/database/client.ts @@ -1,5 +1,5 @@ import { openDB } from 'idb'; -import Log from '../libraries/Log'; +import { debug } from 'src/shared/libraries/log'; import { ONESIGNAL_SESSION_KEY } from '../session/constants'; import { IS_SERVICE_WORKER } from '../utils/env'; import { DATABASE_NAME, VERSION } from './constants'; @@ -74,7 +74,7 @@ const open = async (version = VERSION) => { } }, blocked() { - Log._debug('IndexedDB: Blocked event'); + debug('IndexedDB: Blocked event'); }, terminated() { // reopen if db was terminated diff --git a/src/shared/database/config.ts b/src/shared/database/config.ts index 084591dba..07c9a1386 100644 --- a/src/shared/database/config.ts +++ b/src/shared/database/config.ts @@ -1,7 +1,7 @@ import { getConsentRequired } from '../helpers/localStorage'; -import Log from '../libraries/Log'; import { db, getIdsValue, getOptionsValue } from './client'; import type { AppState } from './types'; +import { warn } from 'src/shared/libraries/log'; export const getDBAppConfig = async () => { const config: any = {}; @@ -85,7 +85,7 @@ export const isConsentRequiredButNotGiven = () => { const consentGiven = OneSignal._consentGiven; const requiredButNotGiven = consentRequired && !consentGiven; - if (requiredButNotGiven) Log._warn('Consent required but not given'); + if (requiredButNotGiven) warn('Consent required but not given'); return requiredButNotGiven; }; diff --git a/src/shared/helpers/OutcomesHelper.ts b/src/shared/helpers/OutcomesHelper.ts index 1fab43bf5..48dc4e46b 100644 --- a/src/shared/helpers/OutcomesHelper.ts +++ b/src/shared/helpers/OutcomesHelper.ts @@ -4,7 +4,6 @@ import { getAllNotificationClickedForOutcomes, getAllNotificationReceivedForOutcomes, } from '../database/notifications'; -import Log from '../libraries/Log'; import type { OutcomeProps } from '../models/OutcomeProps'; import { type OutcomeAttribution, @@ -14,6 +13,7 @@ import { import type { OutcomesNotificationReceived } from '../models/OutcomesNotificationEvents'; import type { OutcomesConfig } from '../outcomes/types'; import { awaitOneSignalInitAndSupported, logMethodCall } from '../utils/utils'; +import { debug, error, warn } from 'src/shared/libraries/log'; const SEND_OUTCOME = 'sendOutcome'; const SEND_UNIQUE_OUTCOME = 'sendUniqueOutcome'; @@ -66,12 +66,12 @@ export default class OutcomesHelper { logMethodCall(outcomeMethodString, this._outcomeName); if (!this._config) { - Log._debug('Outcomes feature not supported by main application yet.'); + debug('Outcomes feature not supported by main application yet.'); return false; } if (!this._outcomeName) { - Log._error('Outcome name is required'); + error('Outcome name is required'); return false; } @@ -80,7 +80,7 @@ export default class OutcomesHelper { const isSubscribed = await OneSignal._context._subscriptionManager._isPushNotificationsEnabled(); if (!isSubscribed) { - Log._warn('Reporting outcomes is supported only for subscribed users.'); + warn('Reporting outcomes is supported only for subscribed users.'); return false; } return true; @@ -192,7 +192,7 @@ export default class OutcomesHelper { case OutcomeAttributionType._Unattributed: if (this._isUnique) { if (await this._wasSentDuringSession()) { - Log._warn( + warn( `(Unattributed) unique outcome was already sent during this session`, ); return; @@ -206,7 +206,7 @@ export default class OutcomesHelper { ); return; default: - Log._warn( + warn( 'You are on a free plan. Please upgrade to use this functionality.', ); return; @@ -257,7 +257,7 @@ export async function getConfigAttribution( const allReceivedNotification = await getAllNotificationReceivedForOutcomes(); - Log._debug( + debug( `\tFound total of ${allReceivedNotification.length} received notifications`, ); @@ -278,7 +278,7 @@ export async function getConfigAttribution( .filter((notif) => notif.timestamp >= maxTimestamp) .slice(0, max) .map((notif) => notif.notificationId); - Log._debug( + debug( `\tTotal of ${matchingNotificationIds.length} received notifications are within reporting window.`, ); @@ -292,7 +292,7 @@ export async function getConfigAttribution( notificationIdsToDelete.forEach((id) => db.delete('Outcomes.NotificationReceived', id), ); - Log._debug( + debug( `\t${notificationIdsToDelete.length} received notifications will be deleted.`, ); diff --git a/src/shared/helpers/dismiss.ts b/src/shared/helpers/dismiss.ts index 4bf85dccc..dbce4f199 100644 --- a/src/shared/helpers/dismiss.ts +++ b/src/shared/helpers/dismiss.ts @@ -7,7 +7,7 @@ import { DismissTimeKey, } from '../../page/models/Dismiss'; import { windowEnvString } from '../environment/detect'; -import Log from '../libraries/Log'; +import { debug } from 'src/shared/libraries/log'; const DISMISS_TYPE_COUNT_MAP = { [DismissPrompt._Push]: DismissCountKey._PromptDismissCount, @@ -38,7 +38,7 @@ export async function markPromptDismissedWithType(type: DismissPromptValue) { } else if (dismissCount > 2) { dismissDays = 30; } - Log._debug( + debug( `(${windowEnvString} environment) OneSignal: User dismissed the ${type} ` + `notification prompt; reprompt after ${dismissDays} days.`, ); diff --git a/src/shared/helpers/dom.ts b/src/shared/helpers/dom.ts index b1c95534e..ceb1cdb55 100644 --- a/src/shared/helpers/dom.ts +++ b/src/shared/helpers/dom.ts @@ -1,4 +1,4 @@ -import Log from 'src/shared/libraries/Log'; +import { debug } from 'src/shared/libraries/log'; export function addDomElement( targetSelectorOrElement: string | Element, @@ -59,7 +59,7 @@ export function clearDomElementChildren( export function getDomElementOrStub(selector: string): Element { const foundElement = document.querySelector(selector); if (!foundElement) { - Log._debug(`No instance of ${selector} found. Returning stub.`); + debug(`No instance of ${selector} found. Returning stub.`); return document.createElement('div'); } return foundElement; diff --git a/src/shared/helpers/init.ts b/src/shared/helpers/init.ts index 9367fa001..f2fa8b6ba 100755 --- a/src/shared/helpers/init.ts +++ b/src/shared/helpers/init.ts @@ -1,10 +1,10 @@ +import { debug, error, info, warn } from 'src/shared/libraries/log'; import Bell from '../../page/bell/Bell'; import type { AppConfig } from '../config/types'; import type { ContextInterface } from '../context/types'; import { db } from '../database/client'; import { getSubscription, setSubscription } from '../database/subscription'; import type { OptionKey } from '../database/types'; -import Log from '../libraries/Log'; import { CustomLinkManager } from '../managers/CustomLinkManager'; import { SubscriptionStrategyKind } from '../models/SubscriptionStrategyKind'; import { limitStorePut } from '../services/limitStore'; @@ -17,7 +17,7 @@ import { triggerNotificationPermissionChanged } from './permissions'; import { registerForPush } from './subscription'; export async function internalInit() { - Log._debug('Called internalInit()'); + debug('Called internalInit()'); // Always check for an updated service worker await OneSignal._context._serviceWorkerManager._installWorker(); @@ -52,12 +52,10 @@ function postponeSessionInitUntilPageIsInFocus(): void { } async function sessionInit(): Promise { - Log._debug(`Called sessionInit()`); + debug(`Called sessionInit()`); if (OneSignal._sessionInitAlreadyRunning) { - Log._debug( - 'Returning from sessionInit because it has already been called.', - ); + debug('Returning from sessionInit because it has already been called.'); return; } OneSignal._sessionInitAlreadyRunning = true; @@ -169,7 +167,7 @@ async function establishServiceWorkerChannel(): Promise { try { await OneSignal._context._serviceWorkerManager._establishServiceWorkerChannel(); } catch (e) { - Log._error(e); + error(e); } } } @@ -178,15 +176,15 @@ async function establishServiceWorkerChannel(): Promise { export async function processExpiringSubscriptions(): Promise { const context: ContextInterface = OneSignal._context; - Log._debug('Checking subscription expiration...'); + debug('Checking subscription expiration...'); const isSubscriptionExpiring = await context._subscriptionManager._isSubscriptionExpiring(); if (!isSubscriptionExpiring) { - Log._debug('Subscription is not considered expired.'); + debug('Subscription is not considered expired.'); return false; } - Log._debug('Subscription is considered expiring.'); + debug('Subscription is considered expiring.'); const rawPushSubscription = await context._subscriptionManager._subscribe( SubscriptionStrategyKind._SubscribeNew, ); @@ -209,7 +207,7 @@ async function doInitialize(): Promise { try { await Promise.all(promises); } catch (e) { - Log._error(e); + error(e); throw new Error('Unknown init error'); } } @@ -243,7 +241,7 @@ async function showNotifyButton() { ); OneSignal._notifyButton._create(); } else { - Log._debug( + debug( 'Notify button display predicate returned false so not showing the notify button.', ); } @@ -280,7 +278,7 @@ async function installNativePromptPermissionChangedHook() { } catch (e) { // Some browsers (Safari 16.3 and older) have the API navigator.permissions.query, but don't support the // { name: 'notifications' } param and throws. - Log._warn( + warn( `Could not install native notification permission change hook w/ error: ${e}`, ); } @@ -369,11 +367,11 @@ export async function initSaveState(overridingPageTitle?: string) { const pageTitle: string = overridingPageTitle || config.siteName || document.title || 'Notification'; await db.put('Options', { key: 'pageTitle', value: pageTitle }); - Log._info(`OneSignal: Set pageTitle to be '${pageTitle}'.`); + info(`OneSignal: Set pageTitle to be '${pageTitle}'.`); } async function handleAutoResubscribe(isOptedOut: boolean) { - Log._info('handleAutoResubscribe', { + info('handleAutoResubscribe', { autoResubscribe: OneSignal.config?.userConfig.autoResubscribe, isOptedOut, }); diff --git a/src/shared/helpers/main.ts b/src/shared/helpers/main.ts index d90b5f17c..b529f7a7f 100755 --- a/src/shared/helpers/main.ts +++ b/src/shared/helpers/main.ts @@ -2,7 +2,7 @@ import { db, getOptionsValue } from '../database/client'; import { getDBAppConfig } from '../database/config'; import { getOneSignalApiUrl, useSafariLegacyPush } from '../environment/detect'; import { AppIDMissingError, MalformedArgumentError } from '../errors/common'; -import Log from '../libraries/Log'; +import { error } from '../libraries/log'; import type { NotificationIcons } from '../notifications/types'; import { getPlatformNotificationIcon, logMethodCall } from '../utils/utils'; import { triggerNotificationPermissionChanged } from './permissions'; @@ -67,7 +67,7 @@ export async function showLocalNotification( ._getRegistration() .then(async (registration?: ServiceWorkerRegistration | null) => { if (!registration) { - Log._error('Service worker registration not available.'); + error('Service worker registration not available.'); return; } @@ -107,7 +107,7 @@ export async function getNotificationIcons() { const response = await fetch(url); const data = await response.json(); if (data.errors) { - Log._error(`API call ${url}`, 'failed with:', data.errors); + error(`API call ${url}`, 'failed with:', data.errors); throw new Error('Failed to get notification icons.'); } return data as NotificationIcons; diff --git a/src/shared/helpers/pageview.ts b/src/shared/helpers/pageview.ts index a697463d4..f089d5d9a 100644 --- a/src/shared/helpers/pageview.ts +++ b/src/shared/helpers/pageview.ts @@ -1,4 +1,4 @@ -import Log from '../libraries/Log'; +import { debug } from 'src/shared/libraries/log'; import { getLocalPageViewCount, setLocalPageViewCount as setStoragePageViewCount, @@ -71,7 +71,7 @@ export function incrementPageViewCount() { setLocalPageViewCount(newCountAcrossTabs); incrementedPageViewCount = true; - Log._debug(`Incremented page view count: newCountSingleTab: ${newCountSingleTab}, + debug(`Incremented page view count: newCountSingleTab: ${newCountSingleTab}, newCountAccrossTabs: ${newCountAcrossTabs}.`); } diff --git a/src/shared/helpers/service-worker.ts b/src/shared/helpers/service-worker.ts index 3825c5e91..1a38a504c 100755 --- a/src/shared/helpers/service-worker.ts +++ b/src/shared/helpers/service-worker.ts @@ -11,7 +11,6 @@ import { getCurrentSession, } from '../database/client'; import { getAllNotificationClickedForOutcomes } from '../database/notifications'; -import Log from '../libraries/Log'; import type { OutcomesNotificationClicked } from '../models/OutcomesNotificationEvents'; import Path from '../models/Path'; import type { OutcomesConfig } from '../outcomes/types'; @@ -20,6 +19,7 @@ import { initializeNewSession } from '../session/helpers'; import type { Session, SessionOriginValue } from '../session/types'; import { getConfigAttribution } from './OutcomesHelper'; import { getBaseUrl } from './general'; +import { debug, error, warn } from 'src/shared/libraries/log'; export function getServiceWorkerHref( config: ServiceWorkerManagerConfig, @@ -79,12 +79,12 @@ export async function upsertSession( } if (existingSession.status === SessionStatus._Active) { - Log._debug('Session already active', existingSession); + debug('Session already active', existingSession); return; } if (!existingSession.lastDeactivatedTimestamp) { - Log._debug('Session is in invalid state', existingSession); + debug('Session is in invalid state', existingSession); // TODO: possibly recover by re-starting session if deviceId is present? return; } @@ -137,7 +137,7 @@ export async function deactivateSession( const existingSession = await getCurrentSession(); if (!existingSession) { - Log._debug('No active session found. Cannot deactivate.'); + debug('No active session found. Cannot deactivate.'); return undefined; } @@ -165,7 +165,7 @@ export async function deactivateSession( * For anything but active, logging a warning and doing early return. */ if (existingSession.status !== SessionStatus._Active) { - Log._warn( + warn( `Session in invalid state ${existingSession.status}. Cannot deactivate.`, ); return undefined; @@ -222,17 +222,17 @@ async function finalizeSession( sendOnFocusEnabled: boolean, outcomesConfig: OutcomesConfig, ): Promise { - Log._debug( + debug( 'Finalize session', `started: ${new Date(session.startTimestamp)}`, `duration: ${session.accumulatedDuration}s`, ); if (sendOnFocusEnabled) { - Log._debug( + debug( `send on_focus reporting session duration -> ${session.accumulatedDuration}s`, ); const attribution = await getConfigAttribution(outcomesConfig); - Log._debug('send on_focus with attribution', attribution); + debug('send on_focus with attribution', attribution); await sendSessionDuration( appId, onesignalId, @@ -246,7 +246,7 @@ async function finalizeSession( cleanupCurrentSession(), clearStore('Outcomes.NotificationClicked'), ]); - Log._debug( + debug( 'Finalize session finished', `started: ${new Date(session.startTimestamp)}`, ); @@ -268,7 +268,7 @@ const getLastNotificationClickedForOutcomes = async ( try { allClickedNotifications = await getAllNotificationClickedForOutcomes(); } catch (e) { - Log._error('Database.getLastNotificationClickedForOutcomes', e); + error('Database.getLastNotificationClickedForOutcomes', e); } const predicate = (notification: OutcomesNotificationClicked) => notification.appId === appId; diff --git a/src/shared/helpers/subscription.ts b/src/shared/helpers/subscription.ts index 32c3ad38d..291401387 100755 --- a/src/shared/helpers/subscription.ts +++ b/src/shared/helpers/subscription.ts @@ -1,6 +1,6 @@ import { SubscriptionType } from 'src/shared/subscriptions/constants'; import type { SubscriptionTypeValue } from 'src/shared/subscriptions/types'; -import Log from '../libraries/Log'; +import { error } from '../libraries/log'; import { checkAndTriggerSubscriptionChanged } from '../listeners'; import { Subscription } from '../models/Subscription'; import { SubscriptionStrategyKind } from '../models/SubscriptionStrategyKind'; @@ -25,7 +25,7 @@ export async function registerForPush(): Promise { await triggerNotificationPermissionChanged(); await checkAndTriggerSubscriptionChanged(); } catch (e) { - Log._error(e); + error(e); } return subscription; } diff --git a/src/shared/libraries/Log.ts b/src/shared/libraries/Log.ts deleted file mode 100644 index 1849420a6..000000000 --- a/src/shared/libraries/Log.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { IS_SERVICE_WORKER, LOGGING } from '../utils/env'; - -export default class Log { - private static _shouldLog(): boolean { - if (IS_SERVICE_WORKER) - return !!(self as unknown as ServiceWorkerGlobalScope).shouldLog; - try { - /* LocalStorage may not be accessible on browser profiles that restrict 3rd party cookies */ - const level = window.localStorage.getItem('loglevel'); - return level?.toLowerCase() === 'trace'; - } catch (e) { - return false; - } - } - - /** - * Sets the log level for page context. - * Will not do anything in service worker context. - */ - public static _setLevel(level: string) { - if (IS_SERVICE_WORKER) return; - - /* LocalStorage may not be accessible on browser profiles that restrict 3rd party cookies */ - try { - window.localStorage.setItem('loglevel', level); - } catch (e) { - console.error(e); - } - } - - private static _createLogMethod(consoleMethod: keyof Console) { - return (...args: unknown[]): void => { - if (LOGGING || this._shouldLog() || consoleMethod === 'error') { - (console[consoleMethod] as (...args: unknown[]) => void)(...args); - } - }; - } - static _debug = Log._createLogMethod('debug'); - static _info = Log._createLogMethod('info'); - static _warn = Log._createLogMethod('warn'); - static _error = Log._createLogMethod('error'); -} diff --git a/src/shared/libraries/log.ts b/src/shared/libraries/log.ts new file mode 100644 index 000000000..0fd157a72 --- /dev/null +++ b/src/shared/libraries/log.ts @@ -0,0 +1,43 @@ +import { IS_SERVICE_WORKER, LOGGING } from '../utils/env'; + +function shouldLog(): boolean { + if (IS_SERVICE_WORKER) + return !!(self as unknown as ServiceWorkerGlobalScope).shouldLog; + try { + /* LocalStorage may not be accessible on browser profiles that restrict 3rd party cookies */ + const level = window.localStorage.getItem('loglevel'); + return level?.toLowerCase() === 'trace'; + } catch (e) { + return false; + } +} + +/** + * Sets the log level for page context. + * Will not do anything in service worker context. + */ +export function setLevel(level: string) { + if (IS_SERVICE_WORKER) return; + + /* LocalStorage may not be accessible on browser profiles that restrict 3rd party cookies */ + try { + window.localStorage.setItem('loglevel', level); + } catch (e) { + console.error(e); + } +} + +function createLogMethod(consoleMethod: keyof Console) { + return (...args: unknown[]): void => { + if (LOGGING || shouldLog() || consoleMethod === 'error') { + (console[consoleMethod] as (...args: unknown[]) => void)(...args); + } + }; +} + +const debug = createLogMethod('debug'); +const info = createLogMethod('info'); +const warn = createLogMethod('warn'); +const error = createLogMethod('error'); + +export { debug, error, info, warn }; diff --git a/src/shared/libraries/workerMessenger/page.ts b/src/shared/libraries/workerMessenger/page.ts index fb646c96a..1522a7b35 100644 --- a/src/shared/libraries/workerMessenger/page.ts +++ b/src/shared/libraries/workerMessenger/page.ts @@ -1,7 +1,7 @@ import type { ContextInterface } from 'src/shared/context/types'; import { supportsServiceWorkers } from 'src/shared/environment/detect'; +import { debug, error } from 'src/shared/libraries/log'; import { getAvailableServiceWorker } from 'src/sw/helpers/registration'; -import Log from '../Log'; import { WorkerMessengerBase } from './base'; import type { WorkerMessengerCommandValue, @@ -28,7 +28,7 @@ export class WorkerMessengerPage extends WorkerMessengerBase { 'message', this._onPageMessageReceivedFromServiceWorker.bind(this), ); - Log._debug( + debug( `(${location.origin}) [Worker Messenger] Page is now listening for messages.`, ); } @@ -54,7 +54,7 @@ export class WorkerMessengerPage extends WorkerMessengerBase { const listenersToRemove = []; const listenersToCall = []; - Log._debug(`[Worker Messenger] Page received message:`, event.data); + debug(`[Worker Messenger] Page received message:`, event.data); for (const listenerRecord of listenerRecords) { if (listenerRecord.onceListenerOnly) { @@ -78,7 +78,7 @@ export class WorkerMessengerPage extends WorkerMessengerBase { command: WorkerMessengerCommandValue, payload?: WorkerMessengerPayload, ) { - Log._debug( + debug( `[Worker Messenger] [Page -> SW] Unicasting '${command.toString()}' to service worker.`, ); this._directPostMessageToSW(command, payload); @@ -88,14 +88,14 @@ export class WorkerMessengerPage extends WorkerMessengerBase { command: WorkerMessengerCommandValue, payload?: WorkerMessengerPayload, ): Promise { - Log._debug( + debug( `[Worker Messenger] [Page -> SW] Direct command '${command.toString()}' to service worker.`, ); const workerRegistration = await this._context?._serviceWorkerManager._getOneSignalRegistration(); if (!workerRegistration) { - Log._error( + error( '`[Worker Messenger] [Page -> SW] Could not get ServiceWorkerRegistration to postMessage!', ); return; @@ -103,7 +103,7 @@ export class WorkerMessengerPage extends WorkerMessengerBase { const availableWorker = getAvailableServiceWorker(workerRegistration); if (!availableWorker) { - Log._error( + error( '`[Worker Messenger] [Page -> SW] Could not get ServiceWorker to postMessage!', ); return; diff --git a/src/shared/libraries/workerMessenger/sw.ts b/src/shared/libraries/workerMessenger/sw.ts index 0189c604e..b38ebef9c 100644 --- a/src/shared/libraries/workerMessenger/sw.ts +++ b/src/shared/libraries/workerMessenger/sw.ts @@ -1,6 +1,6 @@ import { EmptyArgumentError } from 'src/shared/errors/common'; +import { debug } from 'src/shared/libraries/log'; import type ContextSW from 'src/shared/models/ContextSW'; -import Log from '../Log'; import { WorkerMessengerBase } from './base'; import type { WorkerMessengerCommandValue, @@ -21,9 +21,7 @@ export class WorkerMessengerSW extends WorkerMessengerBase { 'message', this._onWorkerMessageReceivedFromPage.bind(this), ); - Log._debug( - '[Worker Messenger] Service worker is now listening for messages.', - ); + debug('[Worker Messenger] Service worker is now listening for messages.'); } _onWorkerMessageReceivedFromPage(event: ExtendableMessageEvent) { @@ -42,10 +40,7 @@ export class WorkerMessengerSW extends WorkerMessengerBase { const listenersToRemove = []; const listenersToCall = []; - Log._debug( - `[Worker Messenger] Service worker received message:`, - event.data, - ); + debug(`[Worker Messenger] Service worker received message:`, event.data); for (const listenerRecord of listenerRecords) { if (listenerRecord.onceListenerOnly) { @@ -74,7 +69,7 @@ export class WorkerMessengerSW extends WorkerMessengerBase { includeUncontrolled: true, }); for (const client of clients) { - Log._debug( + debug( `[Worker Messenger] [SW -> Page] Broadcasting '${command.toString()}' to window client ${ client.url }.`, @@ -98,7 +93,7 @@ export class WorkerMessengerSW extends WorkerMessengerBase { throw EmptyArgumentError('windowClient'); } - Log._debug( + debug( `[Worker Messenger] [SW -> Page] Unicasting '${command.toString()}' to window client ${ windowClient.url }.`, diff --git a/src/shared/listeners.ts b/src/shared/listeners.ts index f94c66259..f43d81e81 100644 --- a/src/shared/listeners.ts +++ b/src/shared/listeners.ts @@ -5,7 +5,6 @@ import { db, getOptionsValue } from './database/client'; import { getAppState, setAppState } from './database/config'; import { decodeHtmlEntities } from './helpers/dom'; import { getCurrentPushToken, showLocalNotification } from './helpers/main'; -import Log from './libraries/Log'; import { CustomLinkManager } from './managers/CustomLinkManager'; import { UserState } from './models/UserState'; import type { @@ -16,6 +15,7 @@ import { isCategorySlidedownConfigured } from './prompts/helpers'; import { limitStorePut } from './services/limitStore'; import OneSignalEvent from './services/OneSignalEvent'; import { logMethodCall } from './utils/utils'; +import { debug, info } from 'src/shared/libraries/log'; export async function checkAndTriggerSubscriptionChanged() { logMethodCall('checkAndTriggerSubscriptionChanged'); @@ -70,7 +70,7 @@ export async function checkAndTriggerSubscriptionChanged() { optedIn: isOptedIn, }, }; - Log._info('Push Subscription state changed: ', change); + info('Push Subscription state changed: ', change); triggerSubscriptionChanged(change); } @@ -140,7 +140,7 @@ export async function checkAndTriggerUserChanged() { externalId: currentExternalId, }, }; - Log._info('User state changed: ', change); + info('User state changed: ', change); triggerUserChanged(change); } @@ -160,12 +160,12 @@ async function onSubscriptionChanged_evaluateNotifyButtonDisplayPredicate() { ) { const predicateResult = await displayPredicate(); if (predicateResult !== false) { - Log._debug( + debug( 'Showing notify button because display predicate returned true.', ); OneSignal._notifyButton._launcher._show(); } else { - Log._debug( + debug( 'Hiding notify button because display predicate returned false.', ); OneSignal._notifyButton._launcher._hide(); @@ -190,7 +190,7 @@ async function onSubscriptionChanged_showWelcomeNotification( pushSubscriptionId: string | undefined | null, ) { if (OneSignal._doNotShowWelcomeNotification) { - Log._debug( + debug( 'Not showing welcome notification because user has previously subscribed.', ); return; @@ -237,7 +237,7 @@ async function onSubscriptionChanged_showWelcomeNotification( title = decodeHtmlEntities(title); message = decodeHtmlEntities(message); - Log._debug('Sending welcome notification.'); + debug('Sending welcome notification.'); showLocalNotification( title, message, diff --git a/src/shared/managers/CustomLinkManager.ts b/src/shared/managers/CustomLinkManager.ts index 0eb427a6d..503b034d8 100644 --- a/src/shared/managers/CustomLinkManager.ts +++ b/src/shared/managers/CustomLinkManager.ts @@ -1,6 +1,6 @@ +import { debug, error, info } from 'src/shared/libraries/log'; import { ResourceLoadState } from '../../page/services/DynamicResourceLoader'; import { addCssClass } from '../helpers/dom'; -import Log from '../libraries/Log'; import type { AppUserConfigCustomLinkOptions } from '../prompts/types'; import { CUSTOM_LINK_CSS_CLASSES, @@ -23,7 +23,7 @@ export class CustomLinkManager { return; } - Log._info('OneSignal: initializing customlink'); + info('OneSignal: initializing customlink'); const isPushEnabled = await OneSignal._context._subscriptionManager._isPushNotificationsEnabled(); if (!this._config?.unsubscribeEnabled && isPushEnabled) { @@ -46,9 +46,7 @@ export class CustomLinkManager { private async _mountExplanationNode(element: HTMLElement): Promise { if (!this._config?.text) { - Log._error( - "CustomLink: required property 'text' is missing in the config", - ); + error("CustomLink: required property 'text' is missing in the config"); return; } @@ -76,9 +74,7 @@ export class CustomLinkManager { private async _mountSubscriptionNode(element: HTMLElement): Promise { if (!this._config?.text) { - Log._error( - "CustomLink: required property 'text' is missing in the config", - ); + error("CustomLink: required property 'text' is missing in the config"); return; } @@ -113,7 +109,7 @@ export class CustomLinkManager { await this._setTextFromPushStatus(subscribeButton); subscribeButton.addEventListener('click', async () => { - Log._info('CustomLink: subscribe clicked'); + info('CustomLink: subscribe clicked'); await this._handleClick(subscribeButton); }); @@ -129,7 +125,7 @@ export class CustomLinkManager { const sdkStylesLoadResult = await OneSignal._context._dynamicResourceLoader._loadSdkStylesheet(); if (sdkStylesLoadResult !== ResourceLoadState._Loaded) { - Log._debug( + debug( 'Not initializing custom link button because styles failed to load.', ); return false; diff --git a/src/shared/managers/ServiceWorkerManager.ts b/src/shared/managers/ServiceWorkerManager.ts index 2b171e5a4..dabc25e2a 100644 --- a/src/shared/managers/ServiceWorkerManager.ts +++ b/src/shared/managers/ServiceWorkerManager.ts @@ -1,3 +1,4 @@ +import { debug, error, info } from 'src/shared/libraries/log'; import { getAvailableServiceWorker, getSWRegistration, @@ -14,7 +15,6 @@ import { type ServiceWorkerActiveStateValue, type ServiceWorkerManagerConfig, } from '../helpers/service-worker'; -import Log from '../libraries/Log'; import { WorkerMessengerCommand } from '../libraries/workerMessenger/constants'; import { triggerNotificationClick } from '../listeners'; import Path from '../models/Path'; @@ -97,7 +97,7 @@ export class ServiceWorkerManager { ); const importedSw = searchParams.get('othersw'); if (importedSw) { - Log._debug( + debug( "Found a ServiceWorker under Akamai's akam-sw.js?othersw=", importedSw, ); @@ -152,7 +152,7 @@ export class ServiceWorkerManager { // If not and notification permissions are enabled we should install. // This prevents an unnecessary install of the OneSignal worker which saves bandwidth const workerState = await this._getActiveState(); - Log._debug('[shouldInstallWorker] workerState', workerState); + debug('[shouldInstallWorker] workerState', workerState); if ( workerState === ServiceWorkerActiveState._None || workerState === ServiceWorkerActiveState._ThirdParty @@ -163,7 +163,7 @@ export class ServiceWorkerManager { ); const notificationsEnabled = permission === 'granted'; if (notificationsEnabled) { - Log._info( + info( '[shouldInstallWorker] Notification Permissions enabled, will install ServiceWorker', ); } @@ -183,7 +183,7 @@ export class ServiceWorkerManager { // 1. No workerRegistration const workerRegistration = await this._getRegistration(); if (!workerRegistration) { - Log._info( + info( '[changedServiceWorkerParams] workerRegistration not found at scope', this._config.registrationOptions.scope, ); @@ -194,7 +194,7 @@ export class ServiceWorkerManager { const existingSwScope = new URL(workerRegistration.scope).pathname; const configuredSwScope = this._config.registrationOptions.scope; if (existingSwScope != configuredSwScope) { - Log._info('[changedServiceWorkerParams] ServiceWorker scope changing', { + info('[changedServiceWorkerParams] ServiceWorker scope changing', { a_old: existingSwScope, b_new: configuredSwScope, }); @@ -214,7 +214,7 @@ export class ServiceWorkerManager { } // 3.2 If the new serviceWorkerHref (page-env SDK version as query param) is different than existing worker URL if (serviceWorkerHref !== availableWorker.scriptURL) { - Log._info('[changedServiceWorkerParams] ServiceWorker href changing:', { + info('[changedServiceWorkerParams] ServiceWorker href changing:', { a_old: availableWorker?.scriptURL, b_new: serviceWorkerHref, }); @@ -230,39 +230,39 @@ export class ServiceWorkerManager { * file. */ private async _workerNeedsUpdate(): Promise { - Log._info('[Service Worker Update] Checking service worker version...'); + info('[Service Worker Update] Checking service worker version...'); let workerVersion: string; try { workerVersion = await timeoutPromise(this._getWorkerVersion(), 2_000); } catch (e) { - Log._info( + info( '[Service Worker Update] Worker did not reply to version query; assuming older version and updating.', ); return true; } if (workerVersion !== VERSION) { - Log._info( + info( `[Service Worker Update] Updating service worker from ${workerVersion} --> ${VERSION}.`, ); return true; } - Log._info( + info( `[Service Worker Update] Service worker version is current at ${workerVersion} (no update required).`, ); return false; } public async _establishServiceWorkerChannel() { - Log._debug('establishServiceWorkerChannel'); + debug('establishServiceWorkerChannel'); const workerMessenger = this._context._workerMessenger; workerMessenger._off(); workerMessenger._on( WorkerMessengerCommand._NotificationWillDisplay, async (event: NotificationForegroundWillDisplayEventSerializable) => { - Log._debug( + debug( location.origin, 'Received notification display event from service worker.', ); @@ -300,7 +300,7 @@ export class ServiceWorkerManager { addListenerForNotificationOpened() returns no results even though a notification was just clicked. */ - Log._debug( + debug( 'notification.clicked event received, but no event listeners; storing event in IndexedDb for later retrieval.', ); } else { @@ -383,13 +383,11 @@ export class ServiceWorkerManager { return this._getOneSignalRegistration(); } - Log._info('Installing worker...'); + info('Installing worker...'); const workerState = await this._getActiveState(); if (workerState === ServiceWorkerActiveState._ThirdParty) { - Log._info( - `[Service Worker Installation] 3rd party service worker detected.`, - ); + info(`[Service Worker Installation] 3rd party service worker detected.`); } const workerHref = getServiceWorkerHref( @@ -399,7 +397,7 @@ export class ServiceWorkerManager { ); const scope = `${getBaseUrl()}${this._config.registrationOptions.scope}`; - Log._info( + info( `[Service Worker Installation] Installing service worker ${workerHref} ${scope}.`, ); @@ -409,19 +407,19 @@ export class ServiceWorkerManager { scope, type: import.meta.env.MODE === 'development' ? 'module' : undefined, }); - } catch (error) { - Log._error( - `[Service Worker Installation] Installing service worker failed ${error}`, + } catch (e) { + error( + `[Service Worker Installation] Installing service worker failed ${e}`, ); registration = await this._fallbackToUserModelBetaWorker(); } - Log._debug( + debug( `[Service Worker Installation] Service worker installed. Waiting for activation`, ); await waitUntilActive(registration); - Log._debug(`[Service Worker Installation] Service worker active`); + debug(`[Service Worker Installation] Service worker active`); await this._establishServiceWorkerChannel(); return registration; @@ -443,7 +441,7 @@ export class ServiceWorkerManager { const scope = `${getBaseUrl()}${this._config.registrationOptions.scope}`; - Log._info( + info( `[Service Worker Installation] Attempting to install v16 Beta Worker ${workerHref} ${scope}.`, ); @@ -460,7 +458,7 @@ export class ServiceWorkerManager { OneSignalSDK.sw.js & OneSignalSDKWorker.js. `; - Log._error(DEPRECATION_ERROR); + error(DEPRECATION_ERROR); return registration; } catch (error) { const response = await fetch(workerHref); diff --git a/src/shared/managers/UpdateManager.ts b/src/shared/managers/UpdateManager.ts index 200f3fcb4..d08c262c7 100644 --- a/src/shared/managers/UpdateManager.ts +++ b/src/shared/managers/UpdateManager.ts @@ -1,7 +1,7 @@ import User from 'src/onesignal/User'; import type { ContextInterface } from 'src/shared/context/types'; import { getPageViewCount, isFirstPageView } from 'src/shared/helpers/pageview'; -import Log from 'src/shared/libraries/Log'; +import { debug, error, warn } from 'src/shared/libraries/log'; import { isCompleteSubscriptionObject } from 'src/shared/managers/utils'; import { SessionOrigin } from 'src/shared/session/constants'; import { NotificationType } from 'src/shared/subscriptions/constants'; @@ -21,7 +21,7 @@ export class UpdateManager { public async _sendPushDeviceRecordUpdate(): Promise { if (!User._singletonInstance?.onesignalId) { - Log._debug( + debug( 'Not sending the update because user is not registered with OneSignal (no onesignal_id)', ); return; @@ -45,7 +45,7 @@ export class UpdateManager { const existingUser = await this._context._subscriptionManager._isAlreadyRegisteredWithOneSignal(); if (!existingUser) { - Log._debug( + debug( 'Not sending the on session because user is not registered with OneSignal (no device id)', ); return; @@ -71,9 +71,7 @@ export class UpdateManager { this._onSessionSent = true; } catch (e) { if (e instanceof Error) { - Log._error( - `Failed to update user session. Error "${e.message}" ${e.stack}`, - ); + error(`Failed to update user session. Error "${e.message}" ${e.stack}`); } } } @@ -108,7 +106,7 @@ export class UpdateManager { await sendOutcome(outcomeRequestData); return; } - Log._warn( + warn( `Send outcome aborted because pushSubscriptionModel is not available.`, ); } @@ -143,7 +141,7 @@ export class UpdateManager { await sendOutcome(outcomeRequestData); return; } - Log._warn( + warn( `Send outcome aborted because pushSubscriptionModel is not available.`, ); } @@ -175,7 +173,7 @@ export class UpdateManager { await sendOutcome(outcomeRequestData); return; } - Log._warn( + warn( `Send outcome aborted because pushSubscriptionModel is not available.`, ); } diff --git a/src/shared/managers/sessionManager/SessionManager.test.ts b/src/shared/managers/sessionManager/SessionManager.test.ts index ed9c03b20..093269f84 100644 --- a/src/shared/managers/sessionManager/SessionManager.test.ts +++ b/src/shared/managers/sessionManager/SessionManager.test.ts @@ -2,11 +2,11 @@ import { EXTERNAL_ID } from '__test__/constants'; import { TestEnvironment } from '__test__/support/environment/TestEnvironment'; import { setAddAliasResponse } from '__test__/support/helpers/requests'; import LoginManager from 'src/page/managers/LoginManager'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import { SessionOrigin } from 'src/shared/session/constants'; import { SessionManager } from './SessionManager'; -vi.spyOn(Log, '_error').mockImplementation(() => ''); +vi.spyOn(Log, 'error').mockImplementation(() => ''); describe('SessionManager', () => { describe('Switching Users', () => { diff --git a/src/shared/managers/sessionManager/SessionManager.ts b/src/shared/managers/sessionManager/SessionManager.ts index 7dbc61362..1873761c5 100644 --- a/src/shared/managers/sessionManager/SessionManager.ts +++ b/src/shared/managers/sessionManager/SessionManager.ts @@ -8,6 +8,7 @@ import { supportsServiceWorkers, } from 'src/shared/environment/detect'; import { isFirstPageView } from 'src/shared/helpers/pageview'; +import { debug, error, warn } from 'src/shared/libraries/log'; import { SessionOrigin } from 'src/shared/session/constants'; import type { SessionOriginValue, @@ -17,7 +18,6 @@ import { NotificationType } from 'src/shared/subscriptions/constants'; import User from '../../../onesignal/User'; import LoginManager from '../../../page/managers/LoginManager'; import { getAppId } from '../../helpers/main'; -import Log from '../../libraries/Log'; import { WorkerMessengerCommand } from '../../libraries/workerMessenger/constants'; import { isCompleteSubscriptionObject } from '../utils'; import type { ISessionManager } from './types'; @@ -46,7 +46,7 @@ export class SessionManager implements ISessionManager { outcomesConfig: this._context._appConfig.userConfig.outcomes!, }; if (supportsServiceWorkers()) { - Log._debug('Notify SW to upsert session'); + debug('Notify SW to upsert session'); await this._context._workerMessenger._unicast( WorkerMessengerCommand._SessionUpsert, payload, @@ -54,7 +54,7 @@ export class SessionManager implements ISessionManager { } else { // http w/o our iframe // we probably shouldn't even be here - Log._debug('Notify upsert: do nothing'); + debug('Notify upsert: do nothing'); } } @@ -74,7 +74,7 @@ export class SessionManager implements ISessionManager { outcomesConfig: this._context._appConfig.userConfig.outcomes!, }; if (supportsServiceWorkers()) { - Log._debug('Notify SW to deactivate session'); + debug('Notify SW to deactivate session'); await this._context._workerMessenger._unicast( WorkerMessengerCommand._SessionDeactivate, payload, @@ -82,7 +82,7 @@ export class SessionManager implements ISessionManager { } else { // http w/o our iframe // we probably shouldn't even be here - Log._debug('Notify deactivate: do nothing'); + debug('Notify deactivate: do nothing'); } } @@ -126,7 +126,7 @@ export class SessionManager implements ISessionManager { if (visibilityState === 'visible') { this._setupOnFocusAndOnBlurForSession(); - Log._debug( + debug( 'handleVisibilityChange', 'visible', `hasFocus: ${document.hasFocus()}`, @@ -143,7 +143,7 @@ export class SessionManager implements ISessionManager { } if (visibilityState === 'hidden') { - Log._debug('handleVisibilityChange', 'hidden'); + debug('handleVisibilityChange', 'hidden'); if ( OneSignal._cache.focusHandler && OneSignal._cache.isFocusEventSetup @@ -173,9 +173,9 @@ export class SessionManager implements ISessionManager { } // it should never be anything else at this point - Log._warn('Unhandled visibility state happened', visibilityState); + warn('Unhandled visibility state happened', visibilityState); } catch (e) { - Log._error('Error handling visibility change:', e); + error('Error handling visibility change:', e); } } @@ -202,20 +202,20 @@ export class SessionManager implements ISessionManager { outcomesConfig: this._context._appConfig.userConfig.outcomes!, }; - Log._debug('Notify SW to deactivate session (beforeunload)'); + debug('Notify SW to deactivate session (beforeunload)'); this._context._workerMessenger._directPostMessageToSW( WorkerMessengerCommand._SessionDeactivate, payload, ); } catch (e) { - Log._error('Error handling onbeforeunload:', e); + error('Error handling onbeforeunload:', e); } } async _handleOnFocus(e: Event): Promise { await LoginManager._switchingUsersPromise; - Log._debug('handleOnFocus', e); + debug('handleOnFocus', e); if (!User._singletonInstance?.onesignalId) { return; } @@ -238,14 +238,14 @@ export class SessionManager implements ISessionManager { SessionOrigin._Focus, ); } catch (e) { - Log._error('Error handling focus:', e); + error('Error handling focus:', e); } } async _handleOnBlur(e: Event): Promise { await LoginManager._switchingUsersPromise; - Log._debug('handleOnBlur', e); + debug('handleOnBlur', e); if (!User._singletonInstance?.onesignalId) { return; } @@ -268,7 +268,7 @@ export class SessionManager implements ISessionManager { SessionOrigin._Blur, ); } catch (e) { - Log._error('Error handling blur:', e); + error('Error handling blur:', e); } } @@ -296,9 +296,7 @@ export class SessionManager implements ISessionManager { _setupSessionEventListeners(): void { // Only want these events if it's using subscription workaround if (!supportsServiceWorkers()) { - Log._debug( - 'Not setting session event listeners. No service worker possible.', - ); + debug('Not setting session event listeners. No service worker possible.'); return; } @@ -333,7 +331,7 @@ export class SessionManager implements ISessionManager { } _setupOnFocusAndOnBlurForSession(): void { - Log._debug('setupOnFocusAndOnBlurForSession'); + debug('setupOnFocusAndOnBlurForSession'); if (!OneSignal._cache.focusHandler) { OneSignal._cache.focusHandler = this._handleOnFocus.bind(this); @@ -364,7 +362,7 @@ export class SessionManager implements ISessionManager { const onesignalId = identityModel._onesignalId; if (!onesignalId) { - Log._debug( + debug( 'Not sending the on session because user is not registered with OneSignal (no onesignal id)', ); return; @@ -408,13 +406,11 @@ export class SessionManager implements ISessionManager { ); this._onSessionSent = true; } catch (e) { - Log._debug('Error updating user session:', e); + debug('Error updating user session:', e); } } catch (e) { if (e instanceof Error) { - Log._error( - `Failed to update user session. Error "${e.message}" ${e.stack}`, - ); + error(`Failed to update user session. Error "${e.message}" ${e.stack}`); } } } diff --git a/src/shared/managers/subscription/base.ts b/src/shared/managers/subscription/base.ts index cfc769018..5579b36c4 100644 --- a/src/shared/managers/subscription/base.ts +++ b/src/shared/managers/subscription/base.ts @@ -5,7 +5,6 @@ import { import type { NotificationTypeValue } from 'src/shared/subscriptions/types'; import type { ContextInterface, ContextSWInterface } from '../../context/types'; import { useSafariLegacyPush } from '../../environment/detect'; -import Log from '../../libraries/Log'; import { RawPushSubscription } from '../../models/RawPushSubscription'; import type { Subscription } from '../../models/Subscription'; import { @@ -19,6 +18,7 @@ import { getBrowserName } from '../../useragent/detect'; import { base64ToUint8Array } from '../../utils/encode'; import { IS_SERVICE_WORKER } from '../../utils/env'; import { DEFAULT_DEVICE_ID } from './constants'; +import { debug, warn } from 'src/shared/libraries/log'; export interface SubscriptionManagerConfig { safariWebId?: string; @@ -147,11 +147,11 @@ export class SubscriptionManagerBase< if (!existingPushSubscription) break; if (existingPushSubscription.options) { - Log._debug( + debug( "[Subscription Manager] An existing push subscription exists and it's options is not null.", ); } else { - Log._debug( + debug( '[Subscription Manager] An existing push subscription exists and options is null. ' + 'Unsubscribing from push first now.', ); @@ -266,7 +266,7 @@ export class SubscriptionManagerBase< userVisibleOnly: true, applicationServerKey: applicationServerKey, }; - Log._debug( + debug( '[Subscription Manager] Subscribing to web push with these options:', subscriptionOptions, ); @@ -283,7 +283,7 @@ export class SubscriptionManagerBase< // In Chrome, e.message contains will be the following in this case for reference; // Registration failed - A subscription with a different applicationServerKey (or gcm_sender_id) already exists; // to change the applicationServerKey, unsubscribe then resubscribe. - Log._warn( + warn( "[Subscription Manager] Couldn't re-subscribe due to applicationServerKey changing, " + 'unsubscribe and attempting to subscribe with new key.', e, @@ -300,11 +300,11 @@ export class SubscriptionManagerBase< private static async _doPushUnsubscribe( pushSubscription: PushSubscription, ): Promise { - Log._debug( + debug( '[Subscription Manager] Unsubscribing existing push subscription.', ); const result = await pushSubscription.unsubscribe(); - Log._debug( + debug( `[Subscription Manager] Unsubscribing existing push subscription result: ${result}`, ); return result; diff --git a/src/shared/managers/subscription/page.ts b/src/shared/managers/subscription/page.ts index 1b793ce35..f952fef94 100644 --- a/src/shared/managers/subscription/page.ts +++ b/src/shared/managers/subscription/page.ts @@ -18,7 +18,7 @@ import { } from 'src/shared/helpers/pageview'; import { triggerNotificationPermissionChanged } from 'src/shared/helpers/permissions'; import { ServiceWorkerActiveState } from 'src/shared/helpers/service-worker'; -import Log from 'src/shared/libraries/Log'; +import { debug, error, info } from 'src/shared/libraries/log'; import { isCompleteSubscriptionObject } from 'src/shared/managers/utils'; import type { PushSubscriptionState } from 'src/shared/models/PushSubscriptionState'; import { RawPushSubscription } from 'src/shared/models/RawPushSubscription'; @@ -97,7 +97,7 @@ export class SubscriptionManagerPage extends SubscriptionManagerBase { const pushModel = await OneSignal._coreDirector._getPushSubscriptionModel(); if (!pushModel) { - Log._info('No Push Subscription yet to update notification_types.'); + info('No Push Subscription yet to update notification_types.'); return; } @@ -260,12 +260,12 @@ export class SubscriptionManagerPage extends SubscriptionManagerBase { } export function logMethodCall(methodName: string, ...args: any[]) { - return Log._debug(`Called ${methodName}(${args.map(stringify).join(', ')})`); + return debug(`Called ${methodName}(${args.map(stringify).join(', ')})`); } export function once( @@ -27,10 +27,10 @@ export function once( manualDestroy = false, ) { if (!event) { - Log._error('Cannot call on() with no event: ', event); + error('Cannot call on() with no event: ', event); } if (!task) { - Log._error('Cannot call on() with no task: ', task); + error('Cannot call on() with no task: ', task); } if (typeof targetSelectorOrElement === 'string') { const els = document.querySelectorAll(targetSelectorOrElement); diff --git a/src/sw/helpers/CancelableTimeout.ts b/src/sw/helpers/CancelableTimeout.ts index 2322677ce..68ae54a65 100644 --- a/src/sw/helpers/CancelableTimeout.ts +++ b/src/sw/helpers/CancelableTimeout.ts @@ -1,4 +1,4 @@ -import Log from '../../shared/libraries/Log'; +import { debug, error } from 'src/shared/libraries/log'; export interface CancelableTimeoutPromise { cancel: () => void; @@ -24,13 +24,13 @@ export function cancelableTimeout( await callback(); resolve(); } catch (e) { - Log._error('Failed to execute callback', e); + error('Failed to execute callback', e); reject(); } }, delayInMilliseconds); clearTimeoutHandle = () => { - Log._debug('Cancel called'); + debug('Cancel called'); self.clearTimeout(timerId); if (!startedExecution) { resolve(); diff --git a/src/sw/helpers/registration.ts b/src/sw/helpers/registration.ts index ce258cd2e..7d5c46c1c 100644 --- a/src/sw/helpers/registration.ts +++ b/src/sw/helpers/registration.ts @@ -1,4 +1,4 @@ -import Log from '../../shared/libraries/Log'; +import { debug, warn } from 'src/shared/libraries/log'; // Get the service worker based on a relative scope. // A relative scope is required as a domain can have none to many service workers installed. @@ -11,7 +11,7 @@ export async function getSWRegistration( return await navigator.serviceWorker.getRegistration(url); } catch (e) { // This could be null in an HTTP context or error if the user doesn't accept cookies - Log._warn( + warn( '[Service Worker Status] Error Checking service worker registration', scope, e, @@ -28,7 +28,7 @@ export function getAvailableServiceWorker( registration.active || registration.installing || registration.waiting; // This never be null unless ServiceWorkerRegistration is pointing to a worker that is completely gone. if (!availableWorker) { - Log._warn('Could not find an available ServiceWorker instance!'); + warn('Could not find an available ServiceWorker instance!'); } return availableWorker; } @@ -45,10 +45,7 @@ export function waitUntilActive( const inactiveWorker = registration.installing || registration.waiting; if (inactiveWorker) { inactiveWorker.addEventListener('statechange', () => { - Log._debug( - 'OneSignal Service Worker state changed:', - inactiveWorker.state, - ); + debug('OneSignal Service Worker state changed:', inactiveWorker.state); if (registration.active) { resolve(); } diff --git a/src/sw/serviceWorker/ServiceWorker.test.ts b/src/sw/serviceWorker/ServiceWorker.test.ts index f2d1c7329..4631db05d 100644 --- a/src/sw/serviceWorker/ServiceWorker.test.ts +++ b/src/sw/serviceWorker/ServiceWorker.test.ts @@ -14,7 +14,7 @@ import { putNotificationClickedForOutcomes, } from 'src/shared/database/notifications'; import { getSubscription } from 'src/shared/database/subscription'; -import Log from 'src/shared/libraries/Log'; +import * as Log from 'src/shared/libraries/log'; import { WorkerMessengerCommand } from 'src/shared/libraries/workerMessenger/constants'; import { DEFAULT_DEVICE_ID } from 'src/shared/managers/subscription/constants'; import { SubscriptionManagerSW } from 'src/shared/managers/subscription/sw'; @@ -57,7 +57,7 @@ run(); vi.useFakeTimers(); vi.setSystemTime('2025-01-01T00:08:00.000Z'); -vi.spyOn(Log, '_debug').mockImplementation(() => {}); +vi.spyOn(Log, 'debug').mockImplementation(() => {}); const subscribeCall = vi.spyOn(SubscriptionManagerSW.prototype, '_subscribe'); @@ -529,7 +529,7 @@ describe('ServiceWorker', () => { }); await dispatchEvent(event); - expect(Log._debug).toHaveBeenCalledWith( + expect(Log.debug).toHaveBeenCalledWith( 'No active session found. Cannot deactivate.', ); }); @@ -686,7 +686,7 @@ describe('ServiceWorker', () => { }); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const logDebugSpy = vi.spyOn(Log, '_debug'); +const logDebugSpy = vi.spyOn(Log, 'debug'); // -- one signal api base mock // @ts-expect-error - for mocking diff --git a/src/sw/serviceWorker/ServiceWorker.ts b/src/sw/serviceWorker/ServiceWorker.ts index 1ac0110cd..3916c204e 100755 --- a/src/sw/serviceWorker/ServiceWorker.ts +++ b/src/sw/serviceWorker/ServiceWorker.ts @@ -26,7 +26,7 @@ import { deactivateSession, upsertSession, } from 'src/shared/helpers/service-worker'; -import Log from 'src/shared/libraries/Log'; +import { debug, error, info, warn } from 'src/shared/libraries/log'; import { WorkerMessengerCommand } from 'src/shared/libraries/workerMessenger/constants'; import { WorkerMessengerSW } from 'src/shared/libraries/workerMessenger/sw'; import type { WorkerMessengerMessage } from 'src/shared/libraries/workerMessenger/types'; @@ -106,14 +106,14 @@ export function run() { switch (data?.command) { case WorkerMessengerCommand._SessionUpsert: - Log._debug('[Service Worker] Received SessionUpsert', payload); + debug('[Service Worker] Received SessionUpsert', payload); debounceRefreshSession( event, payload as UpsertOrDeactivateSessionPayload, ); break; case WorkerMessengerCommand._SessionDeactivate: - Log._debug('[Service Worker] Received SessionDeactivate', payload); + debug('[Service Worker] Received SessionDeactivate', payload); debounceRefreshSession( event, payload as UpsertOrDeactivateSessionPayload, @@ -136,7 +136,7 @@ export function run() { Also see: https://github.com/w3c/ServiceWorker/issues/1156 */ - Log._debug('Setting up message listeners.'); + debug('Setting up message listeners.'); // delay for setting up test mocks like global.ServiceWorkerGlobalScope setTimeout(() => { @@ -163,14 +163,14 @@ export async function getAppId(): Promise { function setupMessageListeners() { workerMessenger._on(WorkerMessengerCommand._WorkerVersion, () => { - Log._debug('[Service Worker] Received worker version message.'); + debug('[Service Worker] Received worker version message.'); workerMessenger._broadcast(WorkerMessengerCommand._WorkerVersion, VERSION); }); workerMessenger._on( WorkerMessengerCommand._Subscribe, async (appConfigBundle: AppConfig) => { const appConfig = appConfigBundle; - Log._debug('[Service Worker] Received subscribe message.'); + debug('[Service Worker] Received subscribe message.'); const context = new ContextSW(appConfig); const rawSubscription = await context._subscriptionManager._subscribe( SubscriptionStrategyKind._ResubscribeExisting, @@ -189,7 +189,7 @@ function setupMessageListeners() { WorkerMessengerCommand._SubscribeNew, async (appConfigBundle: AppConfig) => { const appConfig = appConfigBundle; - Log._debug('[Service Worker] Received subscribe new message.'); + debug('[Service Worker] Received subscribe new message.'); const context = new ContextSW(appConfig); const rawSubscription = await context._subscriptionManager._subscribe( SubscriptionStrategyKind._SubscribeNew, @@ -209,10 +209,7 @@ function setupMessageListeners() { workerMessenger._on( WorkerMessengerCommand._AreYouVisibleResponse, async (payload: PageVisibilityResponse) => { - Log._debug( - '[Service Worker] Received response for AreYouVisible', - payload, - ); + debug('[Service Worker] Received response for AreYouVisible', payload); const timestamp = payload.timestamp; if (self.clientsStatus?.timestamp !== timestamp) { @@ -243,10 +240,7 @@ function setupMessageListeners() { * notifications. */ function onPushReceived(event: PushEvent): void { - Log._debug( - `Called onPushReceived(${JSON.stringify(event, null, 4)}):`, - event, - ); + debug(`Called onPushReceived(${JSON.stringify(event, null, 4)}):`, event); event.waitUntil( parseOrFetchNotifications(event) @@ -257,7 +251,7 @@ function onPushReceived(event: PushEvent): void { const appId = await getAppId(); for (const rawNotification of rawNotificationsArray) { - Log._debug('Raw Notification from OneSignal:', rawNotification); + debug('Raw Notification from OneSignal:', rawNotification); const notification = toOSNotification(rawNotification); notificationReceivedPromises.push( @@ -278,14 +272,14 @@ function onPushReceived(event: PushEvent): void { WorkerMessengerCommand._NotificationWillDisplay, event, ) - .catch((e) => Log._error(e)); + .catch((e) => error(e)); const pushSubscriptionId = await getPushSubscriptionId(); notificationWillDisplay(notif, pushSubscriptionId); return displayNotification(notif) .then(() => sendConfirmedDelivery(notif)) - .catch((e) => Log._error(e)); + .catch((e) => error(e)); }).bind(null, notification), ); } @@ -297,7 +291,7 @@ function onPushReceived(event: PushEvent): void { }, Promise.resolve()); }) .catch((e) => { - Log._debug('Failed to display a notification:', e); + debug('Failed to display a notification:', e); }), ); } @@ -345,7 +339,7 @@ async function sendConfirmedDelivery( device_type: getDeviceType(), }; - Log._debug( + debug( `Called sendConfirmedDelivery(${JSON.stringify(notification, null, 4)})`, ); @@ -402,7 +396,7 @@ async function refreshSession( event: ExtendableMessageEvent, options: UpsertOrDeactivateSessionPayload, ): Promise { - Log._debug('[Service Worker] refreshSession'); + debug('[Service Worker] refreshSession'); /** * getWindowClients -> check for the first focused * unfortunately, not enough for safari, it always returns false for focused state of a client @@ -420,7 +414,7 @@ async function refreshSession( const hasAnyActiveSessions: boolean = windowClients.some( (w) => (w as WindowClient).focused, ); - Log._debug('[Service Worker] hasAnyActiveSessions', hasAnyActiveSessions); + debug('[Service Worker] hasAnyActiveSessions', hasAnyActiveSessions); await updateSessionBasedOnHasActive(event, hasAnyActiveSessions, options); } } @@ -444,7 +438,7 @@ async function checkIfAnyClientsFocusedAndUpdateSession( c.postMessage({ command: WorkerMessengerCommand._AreYouVisible, payload }); }); const updateOnHasActive = async () => { - Log._debug('updateSessionBasedOnHasActive', self.clientsStatus); + debug('updateSessionBasedOnHasActive', self.clientsStatus); await updateSessionBasedOnHasActive( event, self.clientsStatus!.hasAnyActiveSessions, @@ -461,7 +455,7 @@ function debounceRefreshSession( event: ExtendableMessageEvent, options: UpsertOrDeactivateSessionPayload, ) { - Log._debug('[Service Worker] debounceRefreshSession', options); + debug('[Service Worker] debounceRefreshSession', options); if (self.cancel) { self.cancel(); @@ -508,7 +502,7 @@ function ensureImageResourceHttps(imageUrl?: string) { const replacedImageUrl = parsedImageUrl.host + parsedImageUrl.pathname; return `https://i0.wp.com/${replacedImageUrl}`; } catch (e) { - Log._error('ensureImageResourceHttps: ', e); + error('ensureImageResourceHttps: ', e); } } return undefined; @@ -556,7 +550,7 @@ function requiresMacOS15ChromiumAfterDisplayWorkaround(): boolean { * @param notification A structured notification object. */ async function displayNotification(notification: IMutableOSNotification) { - Log._debug( + debug( `Called displayNotification(${JSON.stringify(notification, null, 4)}):`, notification, ); @@ -667,7 +661,7 @@ function shouldOpenNotificationUrl(url: string) { * Supported on: Chrome 50+ only */ async function onNotificationClosed(event: NotificationEvent) { - Log._debug( + debug( `Called onNotificationClosed(${JSON.stringify(event, null, 4)}):`, event, ); @@ -675,7 +669,7 @@ async function onNotificationClosed(event: NotificationEvent) { workerMessenger ._broadcast(WorkerMessengerCommand._NotificationDismissed, notification) - .catch((e) => Log._error(e)); + .catch((e) => error(e)); const pushSubscriptionId = await getPushSubscriptionId(); notificationDismissed(notification, pushSubscriptionId); @@ -718,7 +712,7 @@ async function getNotificationUrlToOpen( * dismissed by clicking the 'X' icon. See the notification close event for the dismissal event. */ async function onNotificationClicked(event: NotificationEvent) { - Log._debug( + debug( `Called onNotificationClicked(${JSON.stringify(event, null, 4)}):`, event, ); @@ -758,7 +752,7 @@ async function onNotificationClicked(event: NotificationEvent) { timestamp: new Date().getTime(), }; - Log._info('NotificationClicked', notificationClickEvent); + info('NotificationClicked', notificationClickEvent); const saveNotificationClickedPromise = (async (notificationClickEvent) => { try { const existingSession = await getCurrentSession(); @@ -776,7 +770,7 @@ async function onNotificationClicked(event: NotificationEvent) { await db.put('Sessions', existingSession); } } catch (e) { - Log._error('Failed to save clicked notification.', e); + error('Failed to save clicked notification.', e); } })(notificationClickEvent); @@ -804,14 +798,14 @@ async function onNotificationClicked(event: NotificationEvent) { try { clientOrigin = new URL(clientUrl).origin; } catch (e) { - Log._error(`Failed to get the HTTP site's actual origin:`, e); + error(`Failed to get the HTTP site's actual origin:`, e); } let launchOrigin = null; try { // Check if the launchUrl is valid; it can be null launchOrigin = new URL(launchUrl).origin; } catch (e) { - Log._error(`Failed parse launchUrl:`, e); + error(`Failed parse launchUrl:`, e); } if ( @@ -832,7 +826,7 @@ async function onNotificationClicked(event: NotificationEvent) { try { if (client instanceof WindowClient) await client.focus(); } catch (e) { - Log._error('Failed to focus:', client, e); + error('Failed to focus:', client, e); } } else { /* @@ -843,22 +837,22 @@ async function onNotificationClicked(event: NotificationEvent) { */ if (client instanceof WindowClient && client.navigate) { try { - Log._debug( + debug( 'Client is standard HTTPS site. Attempting to focus() client.', ); if (client instanceof WindowClient) await client.focus(); } catch (e) { - Log._error('Failed to focus:', client, e); + error('Failed to focus:', client, e); } try { if (notificationOpensLink) { - Log._debug(`Redirecting HTTPS site to (${launchUrl}).`); + debug(`Redirecting HTTPS site to (${launchUrl}).`); await client.navigate(launchUrl); } else { - Log._debug('Not navigating because link is special.'); + debug('Not navigating because link is special.'); } } catch (e) { - Log._error('Failed to navigate:', client, launchUrl, e); + error('Failed to navigate:', client, launchUrl, e); } } else { // If client.navigate() isn't available, we have no other option but to open a new tab to the URL. @@ -927,11 +921,11 @@ async function sendConvertedAPIRequests( * @param url May not be well-formed. */ async function openUrl(url: string): Promise { - Log._debug('Opening notification URL:', url); + debug('Opening notification URL:', url); try { return await self.clients.openWindow(url); } catch (e) { - Log._warn(`Failed to open the URL '${url}':`, e); + warn(`Failed to open the URL '${url}':`, e); return null; } } @@ -941,12 +935,12 @@ async function openUrl(url: string): Promise { * @param event */ function onServiceWorkerActivated(event: ExtendableEvent) { - Log._info(`OneSignal Service Worker activated (version ${VERSION})`); + info(`OneSignal Service Worker activated (version ${VERSION})`); event.waitUntil(self.clients.claim()); } async function onPushSubscriptionChange(event: SubscriptionChangeEvent) { - Log._debug( + debug( `Called onPushSubscriptionChange(${JSON.stringify(event, null, 4)}):`, event, ); @@ -1071,14 +1065,14 @@ function isValidPushPayload(rawData: PushMessageData) { if (isValidPayload(payload)) { return true; } else { - Log._debug( + debug( 'isValidPushPayload: Valid JSON but missing notification UUID:', payload, ); return false; } } catch (e) { - Log._debug('isValidPushPayload: Parsing to JSON failed with:', e); + debug('isValidPushPayload: Parsing to JSON failed with:', e); return false; } } @@ -1098,7 +1092,7 @@ function parseOrFetchNotifications( const isValidPayload = isValidPushPayload(event.data); if (isValidPayload) { - Log._debug('Received a valid encrypted push payload.'); + debug('Received a valid encrypted push payload.'); const payload: OSMinifiedNotificationPayload = event.data.json(); return Promise.resolve([payload]); } diff --git a/src/sw/webhooks/sender.ts b/src/sw/webhooks/sender.ts index b192a5209..6e8026fd7 100644 --- a/src/sw/webhooks/sender.ts +++ b/src/sw/webhooks/sender.ts @@ -1,6 +1,6 @@ import { getOptionsValue } from 'src/shared/database/client'; import type { OptionKey } from 'src/shared/database/types'; -import Log from 'src/shared/libraries/Log'; +import { debug } from 'src/shared/libraries/log'; import type { IOSWebhookEventPayload } from '../serviceWorker/types'; export async function send(payload: IOSWebhookEventPayload): Promise { @@ -24,7 +24,7 @@ export async function send(payload: IOSWebhookEventPayload): Promise { 'Content-Type': 'application/json', }; } - Log._debug( + debug( `Executing ${payload.event} webhook ${ isServerCorsEnabled ? 'with' : 'without' } CORS POST ${webhookTargetUrl}`, From 292391047763368228af4b63947a13ad29f52e31 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Wed, 15 Oct 2025 18:34:25 -0700 Subject: [PATCH 2/6] more clean up of types usage move DeliveryPlatformKindValue rename files remove "removeLegacySubscriptionOptions" logic --- package-lock.json | 230 +++++++++--------- package.json | 8 +- src/core/types/api.ts | 6 +- src/onesignal/OneSignal.ts | 9 +- src/shared/api/base.ts | 2 +- src/shared/api/sw.ts | 4 +- .../constants.ts} | 3 - src/shared/environment/detect.ts | 6 +- src/shared/environment/types.ts | 4 + src/shared/helpers/localStorage.ts | 11 - src/shared/helpers/service-worker.ts | 4 +- src/shared/managers/SubscriptionManager.ts | 13 - .../page.test.ts} | 6 +- src/shared/models/APIHeaders.ts | 4 - .../{CancelableTimeout.ts => timeout.ts} | 0 src/sw/serviceWorker/ServiceWorker.test.ts | 2 +- src/sw/serviceWorker/ServiceWorker.ts | 4 +- 17 files changed, 140 insertions(+), 176 deletions(-) rename src/shared/{models/DeliveryPlatformKind.ts => environment/constants.ts} (55%) create mode 100644 src/shared/environment/types.ts delete mode 100644 src/shared/managers/SubscriptionManager.ts rename src/shared/managers/{SubscriptionManager.test.ts => subscription/page.test.ts} (97%) delete mode 100644 src/shared/models/APIHeaders.ts rename src/sw/helpers/{CancelableTimeout.ts => timeout.ts} (100%) diff --git a/package-lock.json b/package-lock.json index 87fb36629..21354adb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ }, "devDependencies": { "@size-limit/file": "^11.2.0", - "@types/body-parser": "*", + "@types/body-parser": "latest", "@types/express": "^4.17.17", "@types/intl-tel-input": "^18.1.4", "@types/jsdom": "^21.1.7", @@ -23,7 +23,7 @@ "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^5.36.1", "@typescript-eslint/parser": "^5.36.1", - "@vitest/coverage-v8": "4.0.0-beta.10", + "@vitest/coverage-v8": "4.0.2", "concurrently": "^9.2.0", "deepmerge": "^4.2.2", "eslint": "^8.23.0", @@ -38,11 +38,11 @@ "terser": "^5.43.1", "type-fest": "^4.41.0", "typescript": "^5.9.3", - "vite": "^7.1.10", + "vite": "^7.1.12", "vite-bundle-analyzer": "^1.2.3", "vite-plugin-mkcert": "^1.17.9", "vite-tsconfig-paths": "^5.1.4", - "vitest": "4.0.0-beta.10" + "vitest": "4.0.2" } }, "node_modules/@asamuzakjp/css-color": { @@ -1286,6 +1286,13 @@ "size-limit": "11.2.0" } }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/body-parser": { "version": "1.19.6", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", @@ -1298,13 +1305,14 @@ } }, "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { - "@types/deep-eql": "*" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, "node_modules/@types/connect": { @@ -1714,30 +1722,30 @@ "license": "ISC" }, "node_modules/@vitest/coverage-v8": { - "version": "4.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.0-beta.10.tgz", - "integrity": "sha512-euKtmmJPQBAzOQkS60sj9CwKHLxbVIAudybGY2Ah9yzsrZ8LL91loElv7lLd3u3OgYZWjASMDxIS0h4GriYxFA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.2.tgz", + "integrity": "sha512-daQs7CNoq4KKJ+3mgnxwbX8NLkT3nNxK/ZARdWyy/VtNwe0LoKIHgXFvj0hCKXclgfHaihpqbv1UHkQOgyEZng==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.0.0-beta.10", - "ast-v8-to-istanbul": "^0.3.4", - "debug": "^4.4.1", + "@vitest/utils": "4.0.2", + "ast-v8-to-istanbul": "^0.3.5", + "debug": "^4.4.3", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.2.0", "magicast": "^0.3.5", "std-env": "^3.9.0", - "tinyrainbow": "^2.0.0" + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.0.0-beta.10", - "vitest": "4.0.0-beta.10" + "@vitest/browser": "4.0.2", + "vitest": "4.0.2" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -1746,32 +1754,33 @@ } }, "node_modules/@vitest/expect": { - "version": "4.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.0-beta.10.tgz", - "integrity": "sha512-03GDRo1imUrqG2ASfC+smzjl81MX5Q8+HDiYrSm0ULs5FJoKOiz4tN62/9BNFzflmsveTp5KCjuN80i18gCDng==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.2.tgz", + "integrity": "sha512-izQY+ABWqL2Vyr5+LNo3m16nLLTAzLn8em6i5uxqsrWRhdgzdN5JIHrpFVGBAYRGDAbtwE+yD4Heu8gsBSWTVQ==", "dev": true, "license": "MIT", "dependencies": { + "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.0-beta.10", - "@vitest/utils": "4.0.0-beta.10", + "@vitest/spy": "4.0.2", + "@vitest/utils": "4.0.2", "chai": "^6.0.1", - "tinyrainbow": "^2.0.0" + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { - "version": "4.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.0-beta.10.tgz", - "integrity": "sha512-xjMA9qPCx2WnwX/72UyF1L8cJR6w/OD+HgTLpwcV6RhwFRk3ipdDTLBbTTngnyuaFh/IVXn04zJ7DKdPx1kV3A==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.2.tgz", + "integrity": "sha512-oiny+oBSGU9vHMA1DPdO+t1GVidCRuA4lKSG6rbo5SrCiTCGl7bTCyTaUkwxDpUkiSxEVneeXW4LJ4fg3H56dw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.0-beta.10", + "@vitest/spy": "4.0.2", "estree-walker": "^3.0.3", - "magic-string": "^0.30.18" + "magic-string": "^0.30.19" }, "funding": { "url": "https://opencollective.com/vitest" @@ -1790,42 +1799,41 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.0-beta.10.tgz", - "integrity": "sha512-WHQcKjG+LPfeu4R74gjJqUgrH7y0Gj2oWyQ4rscf8u3nKQS9z+D3lxyrYdwysmX5952ayHBI0x4GJ5MXmM6LCA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.2.tgz", + "integrity": "sha512-PhrSiljryCz5nUDhHla5ihXYy2iRCBob+rNqlu34dA+KZIllVR39rUGny5R3kLgDgw3r8GW1ptOo64WbieMkeQ==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^2.0.0" + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "4.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.0-beta.10.tgz", - "integrity": "sha512-bHJcMmhS3x9nFhwapm6DNuTbZMQSGEgYyKFm8GNZ35ixpYuCcmRDaA+rm8VwebraoSjkphVrwfdJ/dspaN6Gxw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.2.tgz", + "integrity": "sha512-mPS5T/ZDuO6J5rsQiA76CFmlHtos7dnCvL14I1Oo8SbcjIhJd6kirFmekovfYLRygdF0gJe6SA5asCKIWKw1tw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.0-beta.10", - "pathe": "^2.0.3", - "strip-literal": "^3.0.0" + "@vitest/utils": "4.0.2", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "4.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.0-beta.10.tgz", - "integrity": "sha512-yHpiggeAt9Fg082/5M8FGhgqp2Pv3nVeOHPZTirl9GbULEiBQiSO6pIkDZRh5gPGyKGbjXj/F/9h07BmtvOXtg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.2.tgz", + "integrity": "sha512-NibujZAh+fTQlpGdP8J2pZcsPg7EPjiLUOUq9In++4p35vc9xIFMkXfQDbBSpijqZPe6i2hEKrUCbKu70/sPzw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.0-beta.10", - "magic-string": "^0.30.18", + "@vitest/pretty-format": "4.0.2", + "magic-string": "^0.30.19", "pathe": "^2.0.3" }, "funding": { @@ -1833,9 +1841,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.0-beta.10.tgz", - "integrity": "sha512-dz6qAHX+PqMOCq5Hq6nht2L8v9hszdzZM8x2KM9xGC8WESKBJwIdTqPVqLn+DyVzFMtRSAzeujXixDGeDFsrkQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.2.tgz", + "integrity": "sha512-KrTWRXFPYrbhD0iUXeoA8BMXl81nvemj5D8sc7NbTlRvCeUWo36JheOWtAUCafcNi0G72ycAdsvWQVSOxy/3TA==", "dev": true, "license": "MIT", "funding": { @@ -1843,15 +1851,14 @@ } }, "node_modules/@vitest/utils": { - "version": "4.0.0-beta.10", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.0-beta.10.tgz", - "integrity": "sha512-jKjXM3KR2FUIoU6QOZsFtJG9cNAwszmVg2WWsY/jlD6jhw1ngqoesxUwp3xbbSTeKh/Ii1P1qTaufa5g0oboMA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.2.tgz", + "integrity": "sha512-H9jFzZb/5B5Qh7ajPUWMJ8UYGxQ4EQTaNLSm3icXs/oXkzQ1jqfcWDEJ4U3LkFPZOd6QW8M2MYjz32poW+KKqg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.0-beta.10", - "loupe": "^3.2.1", - "tinyrainbow": "^2.0.0" + "@vitest/pretty-format": "4.0.2", + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" @@ -1979,6 +1986,16 @@ "node": ">=8" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/ast-v8-to-istanbul": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.5.tgz", @@ -2091,9 +2108,9 @@ } }, "node_modules/chai": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.0.1.tgz", - "integrity": "sha512-/JOoU2//6p5vCXh00FpNgtlw0LjvhGttaWc+y7wpW9yjBm3ys0dI8tSKZxIOgNruz5J0RleccatSIC3uxEZP0g==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.0.tgz", + "integrity": "sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA==", "dev": true, "license": "MIT", "engines": { @@ -3858,13 +3875,6 @@ "node": ">=8" } }, - "node_modules/loupe": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", - "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -3873,9 +3883,9 @@ "license": "ISC" }, "node_modules/magic-string": { - "version": "0.30.18", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", - "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", "dev": true, "license": "MIT", "dependencies": { @@ -5087,9 +5097,9 @@ } }, "node_modules/std-env": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", - "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, "license": "MIT" }, @@ -5141,19 +5151,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-literal": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", - "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^9.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -5315,20 +5312,10 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tinypool": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.0.0.tgz", - "integrity": "sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.0.0 || >=22.0.0" - } - }, "node_modules/tinyrainbow": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", "dev": true, "license": "MIT", "engines": { @@ -5530,9 +5517,9 @@ "license": "MIT" }, "node_modules/vite": { - "version": "7.1.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.11.tgz", - "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", + "version": "7.1.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz", + "integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==", "dev": true, "license": "MIT", "dependencies": { @@ -5684,39 +5671,38 @@ } }, "node_modules/vitest": { - "version": "4.0.0-beta.10", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.0-beta.10.tgz", - "integrity": "sha512-lVVa/PjrRMCkFHd7J95UkqNEL+MkLuJoZBoS5B7Y9tqSpOzupVTAgck9HzO5ezxn2SpvIyO0e5o7uBRFW/MZVQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.2.tgz", + "integrity": "sha512-SXrA2ZzOPulX479d8W13RqKSmvHb9Bfg71eW7Fbs6ZjUFcCCXyt/OzFCkNyiUE8mFlPHa4ZVUGw0ky+5ndKnrg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.0.0-beta.10", - "@vitest/mocker": "4.0.0-beta.10", - "@vitest/pretty-format": "^4.0.0-beta.10", - "@vitest/runner": "4.0.0-beta.10", - "@vitest/snapshot": "4.0.0-beta.10", - "@vitest/spy": "4.0.0-beta.10", - "@vitest/utils": "4.0.0-beta.10", - "debug": "^4.4.1", + "@vitest/expect": "4.0.2", + "@vitest/mocker": "4.0.2", + "@vitest/pretty-format": "4.0.2", + "@vitest/runner": "4.0.2", + "@vitest/snapshot": "4.0.2", + "@vitest/spy": "4.0.2", + "@vitest/utils": "4.0.2", + "debug": "^4.4.3", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", - "magic-string": "^0.30.18", + "magic-string": "^0.30.19", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.14", - "tinypool": "^2.0.0", - "tinyrainbow": "^2.0.0", - "vite": "^6.0.0 || ^7.0.0-0", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -5724,9 +5710,11 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "4.0.0-beta.10", - "@vitest/ui": "4.0.0-beta.10", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.2", + "@vitest/browser-preview": "4.0.2", + "@vitest/browser-webdriverio": "4.0.2", + "@vitest/ui": "4.0.2", "happy-dom": "*", "jsdom": "*" }, @@ -5740,7 +5728,13 @@ "@types/node": { "optional": true }, - "@vitest/browser": { + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { "optional": true }, "@vitest/ui": { diff --git a/package.json b/package.json index e1ec0303b..4bc5e148f 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^5.36.1", "@typescript-eslint/parser": "^5.36.1", - "@vitest/coverage-v8": "4.0.0-beta.10", + "@vitest/coverage-v8": "4.0.2", "concurrently": "^9.2.0", "deepmerge": "^4.2.2", "eslint": "^8.23.0", @@ -70,11 +70,11 @@ "terser": "^5.43.1", "type-fest": "^4.41.0", "typescript": "^5.9.3", - "vite": "^7.1.10", + "vite": "^7.1.12", "vite-bundle-analyzer": "^1.2.3", "vite-plugin-mkcert": "^1.17.9", "vite-tsconfig-paths": "^5.1.4", - "vitest": "4.0.0-beta.10" + "vitest": "4.0.2" }, "size-limit": [ { @@ -84,7 +84,7 @@ }, { "path": "./build/releases/OneSignalSDK.page.es6.js", - "limit": "45.51 kB", + "limit": "45.485 kB", "gzip": true }, { diff --git a/src/core/types/api.ts b/src/core/types/api.ts index 1a869847e..4618fc8f8 100644 --- a/src/core/types/api.ts +++ b/src/core/types/api.ts @@ -1,11 +1,15 @@ import type { SetRequired } from 'type-fest'; -import type { APIHeaders } from 'src/shared/models/APIHeaders'; import type { NotificationTypeValue, SubscriptionTypeValue, } from 'src/shared/subscriptions/types'; +export interface APIHeaders { + Authorization?: string; + [key: string]: any; +} + export interface RequestMetadata { appId: string; subscriptionId?: string; diff --git a/src/onesignal/OneSignal.ts b/src/onesignal/OneSignal.ts index a854ac6d9..22c12406d 100644 --- a/src/onesignal/OneSignal.ts +++ b/src/onesignal/OneSignal.ts @@ -22,10 +22,10 @@ import { } from 'src/shared/helpers/init'; import { getConsentRequired, - removeLegacySubscriptionOptions, setConsentRequired as setStorageConsentRequired, } from 'src/shared/helpers/localStorage'; import { checkAndTriggerNotificationPermissionChanged } from 'src/shared/helpers/main'; +import { debug, info, warn } from 'src/shared/libraries/log'; import { _onSubscriptionChanged, checkAndTriggerSubscriptionChanged, @@ -45,7 +45,6 @@ import NotificationsNamespace from './NotificationsNamespace'; import { SessionNamespace } from './SessionNamespace'; import SlidedownNamespace from './SlidedownNamespace'; import UserNamespace from './UserNamespace'; -import { debug, info, warn } from 'src/shared/libraries/log'; export default class OneSignal { static _consentGiven = false; @@ -127,11 +126,7 @@ export default class OneSignal { */ static async init(options: AppUserConfig) { logMethodCall('init'); - debug( - `Browser Environment: ${getBrowserName()} ${getBrowserVersion()}`, - ); - - removeLegacySubscriptionOptions(); + debug(`Browser Environment: ${getBrowserName()} ${getBrowserVersion()}`); errorIfInitAlreadyCalled(); await OneSignal._initializeConfig(options); diff --git a/src/shared/api/base.ts b/src/shared/api/base.ts index c3fedc741..8a1a8b910 100644 --- a/src/shared/api/base.ts +++ b/src/shared/api/base.ts @@ -1,10 +1,10 @@ import { RETRY_MS } from 'src/core/operationRepo/constants'; +import type { APIHeaders } from 'src/core/types/api'; import { getOneSignalApiUrl } from '../environment/detect'; import { AppIDMissingError, RetryLimitError } from '../errors/common'; import { delay } from '../helpers/general'; import { isValidUuid } from '../helpers/validators'; import { error } from '../libraries/log'; -import type { APIHeaders } from '../models/APIHeaders'; import { IS_SERVICE_WORKER, VERSION } from '../utils/env'; type SupportedMethods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; diff --git a/src/shared/api/sw.ts b/src/shared/api/sw.ts index c0776575a..e325659b9 100644 --- a/src/shared/api/sw.ts +++ b/src/shared/api/sw.ts @@ -1,10 +1,11 @@ import { IdentityConstants } from 'src/core/constants'; import { updateUserByAlias } from 'src/core/requests/api'; import type { IUpdateUser } from 'src/core/types/api'; +import { debug } from 'src/shared/libraries/log'; import type { ServerAppConfig } from '../config/types'; import { enforceAlias, enforceAppId } from '../context/helpers'; import { getSubscriptionType } from '../environment/detect'; -import type { DeliveryPlatformKindValue } from '../models/DeliveryPlatformKind'; +import type { DeliveryPlatformKindValue } from '../environment/types'; import { OutcomeAttributionType, type OutcomeAttribution, @@ -13,7 +14,6 @@ import type { OutcomeRequestData } from '../outcomes/types'; import { NotificationType } from '../subscriptions/constants'; import * as OneSignalApiBase from './base'; import { sendOutcome } from './shared'; -import { debug } from 'src/shared/libraries/log'; export async function downloadSWServerAppConfig( appId: string, diff --git a/src/shared/models/DeliveryPlatformKind.ts b/src/shared/environment/constants.ts similarity index 55% rename from src/shared/models/DeliveryPlatformKind.ts rename to src/shared/environment/constants.ts index ef92e37d7..dcc5511d0 100644 --- a/src/shared/models/DeliveryPlatformKind.ts +++ b/src/shared/environment/constants.ts @@ -5,6 +5,3 @@ export const DeliveryPlatformKind = { _Email: 11, _SafariVapid: 17, } as const; - -export type DeliveryPlatformKindValue = - (typeof DeliveryPlatformKind)[keyof typeof DeliveryPlatformKind]; diff --git a/src/shared/environment/detect.ts b/src/shared/environment/detect.ts index da7a252df..e356c24d9 100644 --- a/src/shared/environment/detect.ts +++ b/src/shared/environment/detect.ts @@ -1,12 +1,10 @@ -import { - DeliveryPlatformKind, - type DeliveryPlatformKindValue, -} from '../models/DeliveryPlatformKind'; import { SubscriptionType } from '../subscriptions/constants'; import type { SubscriptionTypeValue } from '../subscriptions/types'; import { Browser } from '../useragent/constants'; import { getBrowserName, getBrowserVersion } from '../useragent/detect'; import { API_ORIGIN, API_TYPE, IS_SERVICE_WORKER } from '../utils/env'; +import { DeliveryPlatformKind } from './constants'; +import type { DeliveryPlatformKindValue } from './types'; export const isBrowser = () => typeof window !== 'undefined'; diff --git a/src/shared/environment/types.ts b/src/shared/environment/types.ts new file mode 100644 index 000000000..8cc4a4f29 --- /dev/null +++ b/src/shared/environment/types.ts @@ -0,0 +1,4 @@ +import { DeliveryPlatformKind } from './constants'; + +export type DeliveryPlatformKindValue = + (typeof DeliveryPlatformKind)[keyof typeof DeliveryPlatformKind]; diff --git a/src/shared/helpers/localStorage.ts b/src/shared/helpers/localStorage.ts index d4bb32278..319c18d17 100644 --- a/src/shared/helpers/localStorage.ts +++ b/src/shared/helpers/localStorage.ts @@ -1,17 +1,6 @@ -const IS_OPTED_OUT = 'isOptedOut'; -const IS_PUSH_NOTIFICATIONS_ENABLED = 'isPushNotificationsEnabled'; const PAGE_VIEWS = 'os_pageViews'; const REQUIRES_PRIVACY_CONSENT = 'requiresPrivacyConsent'; -/** - * Used in OneSignal initialization to dedupe local storage subscription options already being saved to IndexedDB. - * We will eventually be able to remove this function. - */ -export function removeLegacySubscriptionOptions(): void { - localStorage.removeItem(IS_OPTED_OUT); - localStorage.removeItem(IS_PUSH_NOTIFICATIONS_ENABLED); -} - export function setConsentRequired(value: boolean): void { localStorage.setItem(REQUIRES_PRIVACY_CONSENT, value.toString()); } diff --git a/src/shared/helpers/service-worker.ts b/src/shared/helpers/service-worker.ts index 1a38a504c..7036f1e39 100755 --- a/src/shared/helpers/service-worker.ts +++ b/src/shared/helpers/service-worker.ts @@ -1,7 +1,8 @@ +import { debug, error, warn } from 'src/shared/libraries/log'; import { cancelableTimeout, type CancelableTimeoutPromise, -} from '../../sw/helpers/CancelableTimeout'; +} from '../../sw/helpers/timeout'; import { sendSessionDuration, updateUserSession } from '../api/sw'; import { encodeHashAsUriComponent } from '../context/helpers'; import { @@ -19,7 +20,6 @@ import { initializeNewSession } from '../session/helpers'; import type { Session, SessionOriginValue } from '../session/types'; import { getConfigAttribution } from './OutcomesHelper'; import { getBaseUrl } from './general'; -import { debug, error, warn } from 'src/shared/libraries/log'; export function getServiceWorkerHref( config: ServiceWorkerManagerConfig, diff --git a/src/shared/managers/SubscriptionManager.ts b/src/shared/managers/SubscriptionManager.ts deleted file mode 100644 index 8bcb177f5..000000000 --- a/src/shared/managers/SubscriptionManager.ts +++ /dev/null @@ -1,13 +0,0 @@ -export interface SubscriptionManagerConfig { - safariWebId?: string; - appId: string; - /** - * The VAPID public key to use for Chrome-like browsers, including Opera and Yandex browser. - */ - vapidPublicKey?: string; - /** - * A globally shared VAPID public key to use for the Firefox browser, which does not use - * VAPID for authentication but for application identification and uses a single - */ - onesignalVapidPublicKey?: string; -} diff --git a/src/shared/managers/SubscriptionManager.test.ts b/src/shared/managers/subscription/page.test.ts similarity index 97% rename from src/shared/managers/SubscriptionManager.test.ts rename to src/shared/managers/subscription/page.test.ts index 3e0ba3bf1..040c372f9 100644 --- a/src/shared/managers/SubscriptionManager.test.ts +++ b/src/shared/managers/subscription/page.test.ts @@ -17,12 +17,12 @@ import { mockPushSubscription, MockServiceWorker, } from '__test__/support/mocks/MockServiceWorker'; -import { setPushToken } from '../database/subscription'; -import { IDManager } from './IDManager'; +import { setPushToken } from '../../database/subscription'; +import { IDManager } from '../IDManager'; import { SubscriptionManagerPage, updatePushSubscriptionModelWithRawSubscription, -} from './subscription/page'; +} from './page'; describe('SubscriptionManager', () => { beforeEach(() => { diff --git a/src/shared/models/APIHeaders.ts b/src/shared/models/APIHeaders.ts deleted file mode 100644 index 64b47971c..000000000 --- a/src/shared/models/APIHeaders.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface APIHeaders { - Authorization?: string; - [key: string]: any; -} diff --git a/src/sw/helpers/CancelableTimeout.ts b/src/sw/helpers/timeout.ts similarity index 100% rename from src/sw/helpers/CancelableTimeout.ts rename to src/sw/helpers/timeout.ts diff --git a/src/sw/serviceWorker/ServiceWorker.test.ts b/src/sw/serviceWorker/ServiceWorker.test.ts index 4631db05d..23c13f2c0 100644 --- a/src/sw/serviceWorker/ServiceWorker.test.ts +++ b/src/sw/serviceWorker/ServiceWorker.test.ts @@ -14,11 +14,11 @@ import { putNotificationClickedForOutcomes, } from 'src/shared/database/notifications'; import { getSubscription } from 'src/shared/database/subscription'; +import { DeliveryPlatformKind } from 'src/shared/environment/constants'; import * as Log from 'src/shared/libraries/log'; import { WorkerMessengerCommand } from 'src/shared/libraries/workerMessenger/constants'; import { DEFAULT_DEVICE_ID } from 'src/shared/managers/subscription/constants'; import { SubscriptionManagerSW } from 'src/shared/managers/subscription/sw'; -import { DeliveryPlatformKind } from 'src/shared/models/DeliveryPlatformKind'; import { RawPushSubscription } from 'src/shared/models/RawPushSubscription'; import { SubscriptionStrategyKind } from 'src/shared/models/SubscriptionStrategyKind'; import { diff --git a/src/sw/serviceWorker/ServiceWorker.ts b/src/sw/serviceWorker/ServiceWorker.ts index 3916c204e..ff8c33804 100755 --- a/src/sw/serviceWorker/ServiceWorker.ts +++ b/src/sw/serviceWorker/ServiceWorker.ts @@ -21,6 +21,7 @@ import { setSubscription, } from 'src/shared/database/subscription'; import { getDeviceType } from 'src/shared/environment/detect'; +import type { DeliveryPlatformKindValue } from 'src/shared/environment/types'; import { delay } from 'src/shared/helpers/general'; import { deactivateSession, @@ -31,7 +32,6 @@ import { WorkerMessengerCommand } from 'src/shared/libraries/workerMessenger/con import { WorkerMessengerSW } from 'src/shared/libraries/workerMessenger/sw'; import type { WorkerMessengerMessage } from 'src/shared/libraries/workerMessenger/types'; import ContextSW from 'src/shared/models/ContextSW'; -import type { DeliveryPlatformKindValue } from 'src/shared/models/DeliveryPlatformKind'; import { RawPushSubscription } from 'src/shared/models/RawPushSubscription'; import { SubscriptionStrategyKind } from 'src/shared/models/SubscriptionStrategyKind'; import type { @@ -51,12 +51,12 @@ import type { NotificationTypeValue } from 'src/shared/subscriptions/types'; import { Browser } from 'src/shared/useragent/constants'; import { getBrowserName } from 'src/shared/useragent/detect'; import { VERSION } from 'src/shared/utils/env'; -import { cancelableTimeout } from '../helpers/CancelableTimeout'; import { isValidPayload, toNativeNotificationAction, toOSNotification, } from '../helpers/notifications'; +import { cancelableTimeout } from '../helpers/timeout'; import { notificationClick, notificationDismissed, From 614833022044850d3134227f9be5fafc6d4aeb23 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Fri, 24 Oct 2025 11:52:55 -0700 Subject: [PATCH 3/6] change subscription to interface --- package.json | 4 +- src/onesignal/PushSubscriptionNamespace.ts | 4 +- src/onesignal/UserNamespace.test.ts | 12 +++--- src/onesignal/UserNamespace.ts | 4 +- src/shared/database/subscription.ts | 6 +-- src/shared/helpers/subscription.ts | 10 +++-- src/shared/listeners.ts | 10 ++--- src/shared/managers/subscription/base.ts | 14 +++---- src/shared/models/Subscription.ts | 45 ---------------------- src/shared/subscriptions/types.ts | 24 ++++++++++++ src/sw/serviceWorker/ServiceWorker.ts | 4 +- 11 files changed, 57 insertions(+), 80 deletions(-) delete mode 100755 src/shared/models/Subscription.ts diff --git a/package.json b/package.json index 4bc5e148f..c3d4acfdd 100644 --- a/package.json +++ b/package.json @@ -84,12 +84,12 @@ }, { "path": "./build/releases/OneSignalSDK.page.es6.js", - "limit": "45.485 kB", + "limit": "45.393 kB", "gzip": true }, { "path": "./build/releases/OneSignalSDK.sw.js", - "limit": "13.4 kB", + "limit": "13.302 kB", "gzip": true }, { diff --git a/src/onesignal/PushSubscriptionNamespace.ts b/src/onesignal/PushSubscriptionNamespace.ts index d9d53c0a6..28cd83bef 100644 --- a/src/onesignal/PushSubscriptionNamespace.ts +++ b/src/onesignal/PushSubscriptionNamespace.ts @@ -14,9 +14,9 @@ import { } from 'src/shared/listeners'; import { IDManager } from 'src/shared/managers/IDManager'; import type { EventsMap } from 'src/shared/services/types'; +import type { UserSubscription } from 'src/shared/subscriptions/types'; import { EventListenerBase } from '../page/userModel/EventListenerBase'; import { isCompleteSubscriptionObject } from '../shared/managers/utils'; -import { Subscription } from '../shared/models/Subscription'; import { awaitOneSignalInitAndSupported, logMethodCall, @@ -30,7 +30,7 @@ export default class PushSubscriptionNamespace extends EventListenerBase { constructor( initialize: boolean, - subscription?: Subscription, + subscription?: UserSubscription, permission?: NotificationPermission, ) { super(); diff --git a/src/onesignal/UserNamespace.test.ts b/src/onesignal/UserNamespace.test.ts index 402808ad6..eac7f451d 100644 --- a/src/onesignal/UserNamespace.test.ts +++ b/src/onesignal/UserNamespace.test.ts @@ -5,8 +5,8 @@ import { IdentityConstants } from 'src/core/constants'; import { ModelChangeTags } from 'src/core/types/models'; import * as Log from 'src/shared/libraries/log'; import { IDManager } from 'src/shared/managers/IDManager'; +import type { UserSubscription } from 'src/shared/subscriptions/types'; import type { UserChangeEvent } from '../page/models/UserChangeEvent'; -import { Subscription } from '../shared/models/Subscription'; import User from './User'; import UserNamespace from './UserNamespace'; @@ -438,11 +438,11 @@ describe('Initialization', () => { }); test('should use provided subscription and permission when initializing', () => { - const subscription = new Subscription(); - subscription.deviceId = 'device-123'; - subscription.subscriptionToken = PUSH_TOKEN; - subscription.optedOut = false; - subscription.createdAt = Date.now(); + const subscription: UserSubscription = { + deviceId: 'device-123', + subscriptionToken: PUSH_TOKEN, + optedOut: false, + }; const permission: NotificationPermission = 'granted'; diff --git a/src/onesignal/UserNamespace.ts b/src/onesignal/UserNamespace.ts index 2145f5c8d..a7354e9df 100644 --- a/src/onesignal/UserNamespace.ts +++ b/src/onesignal/UserNamespace.ts @@ -1,8 +1,8 @@ import type { UserEventsMap } from 'src/shared/services/types'; +import type { UserSubscription } from 'src/shared/subscriptions/types'; import type { UserChangeEvent } from '../page/models/UserChangeEvent'; import { EventListenerBase } from '../page/userModel/EventListenerBase'; import Emitter from '../shared/libraries/Emitter'; -import { Subscription } from '../shared/models/Subscription'; import PushSubscriptionNamespace from './PushSubscriptionNamespace'; import User from './User'; @@ -15,7 +15,7 @@ export default class UserNamespace extends EventListenerBase { constructor( initialize: boolean, - subscription?: Subscription, + subscription?: UserSubscription, permission?: NotificationPermission, ) { super(); diff --git a/src/shared/database/subscription.ts b/src/shared/database/subscription.ts index 744a44d71..f5574652b 100644 --- a/src/shared/database/subscription.ts +++ b/src/shared/database/subscription.ts @@ -1,4 +1,4 @@ -import { Subscription } from '../models/Subscription'; +import type { UserSubscription } from '../subscriptions/types'; import { db, getOptionsValue } from './client'; export const getPushId = async () => { @@ -16,7 +16,7 @@ export const setPushToken = async (pushToken: string | undefined) => { }; export const getSubscription = async () => { - const subscription = new Subscription(); + const subscription: UserSubscription = {}; subscription.deviceId = (await db.get('Ids', 'userId'))?.id; subscription.subscriptionToken = (await db.get('Ids', 'registrationId'))?.id; @@ -44,7 +44,7 @@ export const getSubscription = async () => { return subscription; }; -export const setSubscription = async (subscription: Subscription) => { +export const setSubscription = async (subscription: UserSubscription) => { if (subscription.deviceId) { await db.put('Ids', { type: 'userId', diff --git a/src/shared/helpers/subscription.ts b/src/shared/helpers/subscription.ts index 291401387..0a7d307a2 100755 --- a/src/shared/helpers/subscription.ts +++ b/src/shared/helpers/subscription.ts @@ -1,16 +1,18 @@ import { SubscriptionType } from 'src/shared/subscriptions/constants'; -import type { SubscriptionTypeValue } from 'src/shared/subscriptions/types'; +import type { + SubscriptionTypeValue, + UserSubscription, +} from 'src/shared/subscriptions/types'; import { error } from '../libraries/log'; import { checkAndTriggerSubscriptionChanged } from '../listeners'; -import { Subscription } from '../models/Subscription'; import { SubscriptionStrategyKind } from '../models/SubscriptionStrategyKind'; import { IS_SERVICE_WORKER } from '../utils/env'; import { incrementPageViewCount } from './pageview'; import { triggerNotificationPermissionChanged } from './permissions'; -export async function registerForPush(): Promise { +export async function registerForPush(): Promise { const context = OneSignal._context; - let subscription: Subscription | null = null; + let subscription: UserSubscription | null = null; if (IS_SERVICE_WORKER) throw new Error('Unsupported environment'); try { diff --git a/src/shared/listeners.ts b/src/shared/listeners.ts index f43d81e81..607ea5b8a 100644 --- a/src/shared/listeners.ts +++ b/src/shared/listeners.ts @@ -1,6 +1,7 @@ import UserNamespace from 'src/onesignal/UserNamespace'; import type { SubscriptionChangeEvent } from 'src/page/models/SubscriptionChangeEvent'; import type { UserChangeEvent } from 'src/page/models/UserChangeEvent'; +import { debug, info } from 'src/shared/libraries/log'; import { db, getOptionsValue } from './database/client'; import { getAppState, setAppState } from './database/config'; import { decodeHtmlEntities } from './helpers/dom'; @@ -15,7 +16,6 @@ import { isCategorySlidedownConfigured } from './prompts/helpers'; import { limitStorePut } from './services/limitStore'; import OneSignalEvent from './services/OneSignalEvent'; import { logMethodCall } from './utils/utils'; -import { debug, info } from 'src/shared/libraries/log'; export async function checkAndTriggerSubscriptionChanged() { logMethodCall('checkAndTriggerSubscriptionChanged'); @@ -160,14 +160,10 @@ async function onSubscriptionChanged_evaluateNotifyButtonDisplayPredicate() { ) { const predicateResult = await displayPredicate(); if (predicateResult !== false) { - debug( - 'Showing notify button because display predicate returned true.', - ); + debug('Showing notify button because display predicate returned true.'); OneSignal._notifyButton._launcher._show(); } else { - debug( - 'Hiding notify button because display predicate returned false.', - ); + debug('Hiding notify button because display predicate returned false.'); OneSignal._notifyButton._launcher._hide(); } } diff --git a/src/shared/managers/subscription/base.ts b/src/shared/managers/subscription/base.ts index 5579b36c4..d612724ec 100644 --- a/src/shared/managers/subscription/base.ts +++ b/src/shared/managers/subscription/base.ts @@ -2,11 +2,14 @@ import { getSubscription, setSubscription, } from 'src/shared/database/subscription'; -import type { NotificationTypeValue } from 'src/shared/subscriptions/types'; +import { debug, warn } from 'src/shared/libraries/log'; +import type { + NotificationTypeValue, + UserSubscription, +} from 'src/shared/subscriptions/types'; import type { ContextInterface, ContextSWInterface } from '../../context/types'; import { useSafariLegacyPush } from '../../environment/detect'; import { RawPushSubscription } from '../../models/RawPushSubscription'; -import type { Subscription } from '../../models/Subscription'; import { SubscriptionStrategyKind, type SubscriptionStrategyKindValue, @@ -18,7 +21,6 @@ import { getBrowserName } from '../../useragent/detect'; import { base64ToUint8Array } from '../../utils/encode'; import { IS_SERVICE_WORKER } from '../../utils/env'; import { DEFAULT_DEVICE_ID } from './constants'; -import { debug, warn } from 'src/shared/libraries/log'; export interface SubscriptionManagerConfig { safariWebId?: string; @@ -65,7 +67,7 @@ export class SubscriptionManagerBase< pushSubscription: RawPushSubscription | undefined, // eslint-disable-next-line @typescript-eslint/no-unused-vars _subscriptionState?: NotificationTypeValue | null, - ): Promise { + ): Promise { /* This may be called after the RawPushSubscription has been serialized across a postMessage frame. This means it will only have object properties and none of the functions. We have to @@ -300,9 +302,7 @@ export class SubscriptionManagerBase< private static async _doPushUnsubscribe( pushSubscription: PushSubscription, ): Promise { - debug( - '[Subscription Manager] Unsubscribing existing push subscription.', - ); + debug('[Subscription Manager] Unsubscribing existing push subscription.'); const result = await pushSubscription.unsubscribe(); debug( `[Subscription Manager] Unsubscribing existing push subscription result: ${result}`, diff --git a/src/shared/models/Subscription.ts b/src/shared/models/Subscription.ts deleted file mode 100755 index f8dcdc5b8..000000000 --- a/src/shared/models/Subscription.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { Serializable } from '../../page/models/Serializable'; - -export class Subscription implements Serializable { - /** - * The OneSignal subscription id. - */ - deviceId: string | null | undefined; - /** - * The GCM/FCM registration token, as a stringified URL, or the Safari device token. - */ - subscriptionToken: string | null | undefined; - /** - * Whether the user is opted out of notifications, set by setSubscription(). - */ - optedOut: boolean | undefined; - /** - * A UTC timestamp of when this subscription was created. This value is not modified when a - * subscription is merely refreshed, only when a subscription is created anew. - */ - createdAt: number | null | undefined; - /** - * This property is stored on the native PushSubscription object. - */ - expirationTime: number | null | undefined; - - _serialize() { - return { - deviceId: this.deviceId, - subscriptionToken: this.subscriptionToken, - optedOut: this.optedOut, - createdAt: this.createdAt, - expirationTime: this.expirationTime, - }; - } - - static _deserialize(bundle: any): Subscription { - const subscription = new Subscription(); - subscription.deviceId = bundle.deviceId; - subscription.subscriptionToken = bundle.subscriptionToken; - subscription.optedOut = bundle.optedOut; - subscription.createdAt = bundle.createdAt; - subscription.expirationTime = bundle.expirationTime; - return subscription; - } -} diff --git a/src/shared/subscriptions/types.ts b/src/shared/subscriptions/types.ts index d680e9ec4..8cd8c952f 100644 --- a/src/shared/subscriptions/types.ts +++ b/src/shared/subscriptions/types.ts @@ -12,3 +12,27 @@ export type SubscriptionTypeValue = export type NotificationTypeValue = (typeof NotificationType)[keyof typeof NotificationType]; + +export interface UserSubscription { + /** + * The OneSignal subscription id. + */ + deviceId?: string | null; + /** + * The GCM/FCM registration token, as a stringified URL, or the Safari device token. + */ + subscriptionToken?: string | null; + /** + * Whether the user is opted out of notifications, set by setSubscription(). + */ + optedOut?: boolean; + /** + * A UTC timestamp of when this subscription was created. This value is not modified when a + * subscription is merely refreshed, only when a subscription is created anew. + */ + createdAt?: number | null; + /** + * This property is stored on the native PushSubscription object. + */ + expirationTime?: number | null; +} diff --git a/src/sw/serviceWorker/ServiceWorker.ts b/src/sw/serviceWorker/ServiceWorker.ts index ff8c33804..a9f1562d1 100755 --- a/src/sw/serviceWorker/ServiceWorker.ts +++ b/src/sw/serviceWorker/ServiceWorker.ts @@ -181,7 +181,7 @@ function setupMessageListeners() { ); workerMessenger._broadcast( WorkerMessengerCommand._Subscribe, - subscription._serialize(), + subscription, ); }, ); @@ -201,7 +201,7 @@ function setupMessageListeners() { workerMessenger._broadcast( WorkerMessengerCommand._SubscribeNew, - subscription._serialize(), + subscription, ); }, ); From 4d43c14e5562677c4235c465a3d49db531c67c09 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Fri, 24 Oct 2025 10:38:05 -0700 Subject: [PATCH 4/6] add more prefix usages --- .../environment/TestEnvironmentHelpers.ts | 6 +-- __test__/support/helpers/setup.ts | 4 +- package.json | 2 +- src/core/CoreModuleDirector.ts | 10 ++-- .../executors/IdentityOperationExecutor.ts | 8 +-- .../executors/LoginUserOperationExecutor.ts | 24 ++++----- .../RefreshUserOperationExecutor.test.ts | 12 ++--- .../executors/RefreshUserOperationExecutor.ts | 16 +++--- .../SubscriptionOperationExecutor.test.ts | 6 +-- .../SubscriptionOperationExecutor.ts | 32 +++++------ .../executors/UpdateUserOperationExecutor.ts | 6 +-- .../SubscriptionModelStoreListener.ts | 24 ++++----- src/core/modelRepo/RebuildUserService.ts | 8 +-- .../modelStores/SubscriptionModelStore.ts | 8 +-- src/core/models/Model.test.ts | 8 +-- src/core/models/SubscriptionModel.ts | 42 +++++++-------- src/core/operations/BaseAliasOperation.ts | 6 +-- .../BaseFullSubscriptionOperation.ts | 54 +++++++++---------- src/core/operations/BaseTagOperation.ts | 6 +-- src/core/operations/DeleteAliasOperation.ts | 2 +- src/core/operations/SetAliasOperation.ts | 8 +-- src/core/operations/SetPropertyOperation.ts | 6 +-- src/entries/pageSdkInit2.test.ts | 6 +-- src/onesignal/OneSignal.test.ts | 4 +- src/onesignal/PushSubscriptionNamespace.ts | 2 +- src/onesignal/User.ts | 6 +-- src/onesignal/UserNamespace.test.ts | 10 ++-- src/onesignal/userDirector.ts | 2 +- src/page/managers/LoginManager.ts | 2 +- src/shared/listeners.ts | 2 +- src/shared/managers/UpdateManager.ts | 6 +-- .../managers/sessionManager/SessionManager.ts | 4 +- src/shared/managers/subscription/page.test.ts | 8 +-- src/shared/managers/subscription/page.ts | 4 +- src/shared/managers/utils.ts | 8 +-- 35 files changed, 181 insertions(+), 181 deletions(-) diff --git a/__test__/support/environment/TestEnvironmentHelpers.ts b/__test__/support/environment/TestEnvironmentHelpers.ts index 7eab1af75..b482b4a86 100644 --- a/__test__/support/environment/TestEnvironmentHelpers.ts +++ b/__test__/support/environment/TestEnvironmentHelpers.ts @@ -87,12 +87,12 @@ export const setupSubModelStore = async ({ onesignalId, }); if (web_auth) { - pushModel.web_auth = web_auth; + pushModel._web_auth = web_auth; } if (web_p256) { - pushModel.web_p256 = web_p256; + pushModel._web_p256 = web_p256; } - await setPushToken(pushModel.token); + await setPushToken(pushModel._token); OneSignal._coreDirector._subscriptionModelStore._replaceAll( [pushModel], ModelChangeTags._NoPropogate, diff --git a/__test__/support/helpers/setup.ts b/__test__/support/helpers/setup.ts index cdb3d24a5..290197cba 100644 --- a/__test__/support/helpers/setup.ts +++ b/__test__/support/helpers/setup.ts @@ -124,8 +124,8 @@ export const setupSubscriptionModel = async ( token: string | undefined, ) => { const subscriptionModel = new SubscriptionModel(); - subscriptionModel.id = id || ''; - subscriptionModel.token = token || ''; + subscriptionModel._id = id || ''; + subscriptionModel._token = token || ''; OneSignal._coreDirector._subscriptionModelStore._replaceAll( [subscriptionModel], ModelChangeTags._NoPropogate, diff --git a/package.json b/package.json index c3d4acfdd..b33eb7691 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ }, { "path": "./build/releases/OneSignalSDK.page.es6.js", - "limit": "45.393 kB", + "limit": "45.364 kB", "gzip": true }, { diff --git a/src/core/CoreModuleDirector.ts b/src/core/CoreModuleDirector.ts index 20fb5b125..63c5c849a 100644 --- a/src/core/CoreModuleDirector.ts +++ b/src/core/CoreModuleDirector.ts @@ -64,7 +64,7 @@ export class CoreModuleDirector { model._initializeFromJson( new FuturePushSubscriptionRecord(rawPushSubscription)._serialize(), ); - model.id = IDManager._createLocalId(); + model._id = IDManager._createLocalId(); // we enqueue a login operation w/ a create subscription operation the first time we generate/save a push subscription model this._core._subscriptionModelStore._add(model, ModelChangeTags._Hydrate); @@ -83,7 +83,7 @@ export class CoreModuleDirector { public _getEmailSubscriptionModels(): SubscriptionModel[] { logMethodCall('CoreModuleDirector.getEmailSubscriptionModels'); const subscriptions = this._core._subscriptionModelStore._list(); - return subscriptions.filter((s) => s.type === SubscriptionType._Email); + return subscriptions.filter((s) => s._type === SubscriptionType._Email); } public async _hasEmail(): Promise { @@ -94,7 +94,7 @@ export class CoreModuleDirector { public _getSmsSubscriptionModels(): SubscriptionModel[] { logMethodCall('CoreModuleDirector.getSmsSubscriptionModels'); const subscriptions = this._core._subscriptionModelStore._list(); - return subscriptions.filter((s) => s.type === SubscriptionType._SMS); + return subscriptions.filter((s) => s._type === SubscriptionType._SMS); } public async _hasSms(): Promise { @@ -108,7 +108,7 @@ export class CoreModuleDirector { public _getAllPushSubscriptionModels(): SubscriptionModel[] { logMethodCall('CoreModuleDirector.getAllPushSubscriptionModels'); const subscriptions = this._core._subscriptionModelStore._list(); - return subscriptions.filter((s) => isPushSubscriptionType(s.type)); + return subscriptions.filter((s) => isPushSubscriptionType(s._type)); } async _getPushSubscriptionModelByCurrentToken(): Promise< @@ -205,6 +205,6 @@ export class CoreModuleDirector { return undefined; } - return subscriptions.find((subscription) => subscription.token === token); + return subscriptions.find((subscription) => subscription._token === token); } } diff --git a/src/core/executors/IdentityOperationExecutor.ts b/src/core/executors/IdentityOperationExecutor.ts index 37d3486dd..f8919eceb 100644 --- a/src/core/executors/IdentityOperationExecutor.ts +++ b/src/core/executors/IdentityOperationExecutor.ts @@ -82,7 +82,7 @@ export class IdentityOperationExecutor implements IOperationExecutor { label: IdentityConstants._OneSignalID, id: lastOperation._onesignalId, }, - { [lastOperation.label]: lastOperation.value }, + { [lastOperation._label]: lastOperation._value }, ) : deleteAlias( { appId: lastOperation._appId }, @@ -90,7 +90,7 @@ export class IdentityOperationExecutor implements IOperationExecutor { label: IdentityConstants._OneSignalID, id: lastOperation._onesignalId, }, - lastOperation.label, + lastOperation._label, ); const { ok, status, retryAfterSeconds } = await request; @@ -100,8 +100,8 @@ export class IdentityOperationExecutor implements IOperationExecutor { lastOperation._onesignalId ) { this._identityModelStore._model._setProperty( - lastOperation.label, - isSetAlias ? lastOperation.value : undefined, + lastOperation._label, + isSetAlias ? lastOperation._value : undefined, ModelChangeTags._Hydrate, ); } diff --git a/src/core/executors/LoginUserOperationExecutor.ts b/src/core/executors/LoginUserOperationExecutor.ts index 97cc52245..c75335b67 100644 --- a/src/core/executors/LoginUserOperationExecutor.ts +++ b/src/core/executors/LoginUserOperationExecutor.ts @@ -282,15 +282,15 @@ export class LoginUserOperationExecutor implements IOperationExecutor { return { ...currentSubs, [subscriptionId]: { - enabled: operation.enabled, - device_model: operation.device_model, - device_os: operation.device_os, - notification_types: operation.notification_types, - sdk: operation.sdk, - token: operation.token, - type: operation.type, - web_auth: operation.web_auth, - web_p256: operation.web_p256, + enabled: operation._enabled, + device_model: operation._device_model, + device_os: operation._device_os, + notification_types: operation._notification_types, + sdk: operation._sdk, + token: operation._token, + type: operation._type, + web_auth: operation._web_auth, + web_p256: operation._web_p256, }, }; } @@ -303,9 +303,9 @@ export class LoginUserOperationExecutor implements IOperationExecutor { ...currentSubs, [subscriptionId]: { ...currentSubs[subscriptionId], - enabled: operation.enabled, - notification_types: operation.notification_types, - token: operation.token, + enabled: operation._enabled, + notification_types: operation._notification_types, + token: operation._token, }, }; } diff --git a/src/core/executors/RefreshUserOperationExecutor.test.ts b/src/core/executors/RefreshUserOperationExecutor.test.ts index 29d193d55..84ba3699f 100644 --- a/src/core/executors/RefreshUserOperationExecutor.test.ts +++ b/src/core/executors/RefreshUserOperationExecutor.test.ts @@ -178,9 +178,9 @@ describe('RefreshUserOperationExecutor', () => { test('should preserve cached push subscription when updating models', async () => { // Set up a push subscription in the store const pushSubModel = new SubscriptionModel(); - pushSubModel.id = SUB_ID_2; - pushSubModel.type = SubscriptionType._ChromePush; - pushSubModel.token = PUSH_TOKEN; + pushSubModel._id = SUB_ID_2; + pushSubModel._type = SubscriptionType._ChromePush; + pushSubModel._token = PUSH_TOKEN; pushSubModel._notification_types = NotificationType._Subscribed; subscriptionModelStore._add(pushSubModel, ModelChangeTags._NoPropogate); @@ -209,11 +209,11 @@ describe('RefreshUserOperationExecutor', () => { // Find the push subscription const pushSub = subscriptions.find( - (sub: SubscriptionModel) => sub.type === SubscriptionType._ChromePush, + (sub: SubscriptionModel) => sub._type === SubscriptionType._ChromePush, ); expect(pushSub).toBeDefined(); - expect(pushSub?.id).toBe(SUB_ID_2); - expect(pushSub?.token).toBe(PUSH_TOKEN); + expect(pushSub?._id).toBe(SUB_ID_2); + expect(pushSub?._token).toBe(PUSH_TOKEN); }); test('should handle network errors', async () => { diff --git a/src/core/executors/RefreshUserOperationExecutor.ts b/src/core/executors/RefreshUserOperationExecutor.ts index ef20b3167..efb205de7 100644 --- a/src/core/executors/RefreshUserOperationExecutor.ts +++ b/src/core/executors/RefreshUserOperationExecutor.ts @@ -100,21 +100,21 @@ export class RefreshUserOperationExecutor implements IOperationExecutor { for (const sub of subscriptions) { const model = new SubscriptionModel(); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - model.id = sub.id!; - model.token = sub.token ?? ''; + model._id = sub.id!; + model._token = sub.token ?? ''; model._notification_types = sub.notification_types ?? NotificationType._Subscribed; - model.type = sub.type; - model.enabled = + model._type = sub.type; + model._enabled = model._notification_types !== NotificationType._UserOptedOut; - model.sdk = sub.sdk; - model.device_os = sub.device_os; - model.device_model = sub.device_model; + model._sdk = sub.sdk; + model._device_os = sub.device_os; + model._device_model = sub.device_model; model._onesignalId = op._onesignalId; // We only add a non-push subscriptions. For push, the device is the source of truth // so we don't want to cache these subscriptions from the backend. - if (!isPushSubscriptionType(model.type)) { + if (!isPushSubscriptionType(model._type)) { subscriptionModels.push(model); } } diff --git a/src/core/executors/SubscriptionOperationExecutor.test.ts b/src/core/executors/SubscriptionOperationExecutor.test.ts index d8606cf6e..f9278c4b1 100644 --- a/src/core/executors/SubscriptionOperationExecutor.test.ts +++ b/src/core/executors/SubscriptionOperationExecutor.test.ts @@ -288,7 +288,7 @@ describe('SubscriptionOperationExecutor', () => { // Missing error with rebuild ops subscriptionsModelStore._add(pushSubscription, ModelChangeTags._Hydrate); - await setPushToken(pushSubscription.token); + await setPushToken(pushSubscription._token); const res6 = await executor._execute([createOp]); @@ -299,8 +299,8 @@ describe('SubscriptionOperationExecutor', () => { onesignalId: ONESIGNAL_ID, enabled: true, notification_types: NotificationType._Subscribed, - subscriptionId: pushSubscription.id, - token: pushSubscription.token, + subscriptionId: pushSubscription._id, + token: pushSubscription._token, type: SubscriptionType._ChromePush, }), new RefreshUserOperation(APP_ID, ONESIGNAL_ID), diff --git a/src/core/executors/SubscriptionOperationExecutor.ts b/src/core/executors/SubscriptionOperationExecutor.ts index 966a94641..0e307f47a 100644 --- a/src/core/executors/SubscriptionOperationExecutor.ts +++ b/src/core/executors/SubscriptionOperationExecutor.ts @@ -92,15 +92,15 @@ export class SubscriptionOperationExecutor implements IOperationExecutor { const lastUpdateOperation = [...operations] .reverse() .find((op) => op instanceof UpdateSubscriptionOperation); - const enabled = lastUpdateOperation?.enabled ?? createOperation.enabled; - const token = lastUpdateOperation?.token ?? createOperation.token; + const enabled = lastUpdateOperation?._enabled ?? createOperation._enabled; + const token = lastUpdateOperation?._token ?? createOperation._token; const notification_types = - lastUpdateOperation?.notification_types ?? - createOperation.notification_types; + lastUpdateOperation?._notification_types ?? + createOperation._notification_types; const subscription = { - sdk: createOperation.sdk, - type: createOperation.type, + sdk: createOperation._sdk, + type: createOperation._type, enabled, token, notification_types, @@ -209,12 +209,12 @@ export class SubscriptionOperationExecutor implements IOperationExecutor { ] as UpdateSubscriptionOperation; const subscription = { - type: lastOp.type, - enabled: lastOp.enabled, - token: lastOp.token, - notification_types: lastOp.notification_types, - web_auth: lastOp.web_auth, - web_p256: lastOp.web_p256, + type: lastOp._type, + enabled: lastOp._enabled, + token: lastOp._token, + notification_types: lastOp._notification_types, + web_auth: lastOp._web_auth, + web_p256: lastOp._web_p256, }; const response = await updateSubscriptionById( @@ -254,12 +254,12 @@ export class SubscriptionOperationExecutor implements IOperationExecutor { _operations: [ new CreateSubscriptionOperation({ appId: lastOp._appId, - enabled: lastOp.enabled, - notification_types: lastOp.notification_types, + enabled: lastOp._enabled, + notification_types: lastOp._notification_types, onesignalId: lastOp._onesignalId, subscriptionId: lastOp._subscriptionId, - token: lastOp.token, - type: lastOp.type, + token: lastOp._token, + type: lastOp._type, }), ], }; diff --git a/src/core/executors/UpdateUserOperationExecutor.ts b/src/core/executors/UpdateUserOperationExecutor.ts index 1b9994927..525d2d59a 100644 --- a/src/core/executors/UpdateUserOperationExecutor.ts +++ b/src/core/executors/UpdateUserOperationExecutor.ts @@ -108,9 +108,9 @@ export class UpdateUserOperationExecutor implements IOperationExecutor { for (const operation of operations) { if (operation instanceof SetPropertyOperation) { // removing empty string tags from operation.value to save space in IndexedDB and local memory. - let value = operation.value; + let value = operation._value; if (isTagProperty(operation)) { - value = { ...operation.value }; + value = { ...operation._value }; for (const key in value) if (value[key] === '') delete value[key]; } @@ -186,7 +186,7 @@ function createPropertiesFromOperation( if (allowedKeys.includes(propertyKey as IPropertiesModelKeys)) { return { ...properties, - [propertyKey]: operation.value, + [propertyKey]: operation._value, }; } return { ...properties }; diff --git a/src/core/listeners/SubscriptionModelStoreListener.ts b/src/core/listeners/SubscriptionModelStoreListener.ts index 3b840a11d..32ba9e597 100644 --- a/src/core/listeners/SubscriptionModelStoreListener.ts +++ b/src/core/listeners/SubscriptionModelStoreListener.ts @@ -33,10 +33,10 @@ export class SubscriptionModelStoreListener extends ModelStoreListener } _getBySubscriptionId(subscriptionId: string): SubscriptionModel | undefined { - return super._list().find((m) => m.id === subscriptionId); + return super._list().find((m) => m._id === subscriptionId); } override _replaceAll( @@ -31,11 +31,11 @@ export class SubscriptionModelStore extends SimpleModelStore // When hydrating, preserve properties from existing PUSH subscription for (const model of models) { - if (isPushSubscriptionType(model.type)) { + if (isPushSubscriptionType(model._type)) { const existingPushModel = this._get(model._modelId); if (existingPushModel) { - model.sdk = existingPushModel.sdk; - model.device_os = existingPushModel.device_os; + model._sdk = existingPushModel._sdk; + model._device_os = existingPushModel._device_os; } break; // Only modify the first PUSH subscription model } diff --git a/src/core/models/Model.test.ts b/src/core/models/Model.test.ts index 1e8a920b5..6ca027cdf 100644 --- a/src/core/models/Model.test.ts +++ b/src/core/models/Model.test.ts @@ -5,9 +5,9 @@ import { SubscriptionType } from 'src/shared/subscriptions/constants'; test('Set function updates data', async () => { const newSub = generateNewSubscription(); - expect(newSub.enabled).toBe(undefined); + expect(newSub._enabled).toBe(undefined); newSub._setProperty('enabled', true); - expect(newSub.enabled).toBe(true); + expect(newSub._enabled).toBe(true); }); test('Set function broadcasts update event', async () => { @@ -22,9 +22,9 @@ test('Set function broadcasts update event', async () => { test('Hydrate function updates data', async () => { const newSub = generateNewSubscription(); - expect(newSub.type).toBe(SubscriptionType._Email); + expect(newSub._type).toBe(SubscriptionType._Email); newSub._setProperty('type', SubscriptionType._ChromePush); - expect(newSub.type).toBe(SubscriptionType._ChromePush); + expect(newSub._type).toBe(SubscriptionType._ChromePush); }); test('Encode function returns encoded model', async () => { diff --git a/src/core/models/SubscriptionModel.ts b/src/core/models/SubscriptionModel.ts index e14da1556..c2ad5bcb6 100644 --- a/src/core/models/SubscriptionModel.ts +++ b/src/core/models/SubscriptionModel.ts @@ -28,9 +28,9 @@ type ISubscriptionModel = Pick< export class SubscriptionModel extends Model { constructor() { super(); - this.sdk = VERSION; - this.device_model = getDeviceModel(); - this.device_os = getDeviceOS(); + this._sdk = VERSION; + this._device_model = getDeviceModel(); + this._device_os = getDeviceOS(); } /** @@ -46,32 +46,32 @@ export class SubscriptionModel extends Model { /** * The subscription ID. */ - get id(): string { + get _id(): string { return this._getProperty('id'); } - set id(value: string) { + set _id(value: string) { this._setProperty('id', value); } - get enabled(): boolean | undefined { + get _enabled(): boolean | undefined { return this._getProperty('enabled'); } - set enabled(value: boolean) { + set _enabled(value: boolean) { this._setProperty('enabled', value); } - get type(): SubscriptionTypeValue { + get _type(): SubscriptionTypeValue { return this._getProperty('type'); } - set type(value: SubscriptionTypeValue) { + set _type(value: SubscriptionTypeValue) { this._setProperty('type', value); } // Android SDK refers to this as address - get token(): string { + get _token(): string { return this._getProperty('token'); } - set token(value: string) { + set _token(value: string) { this._setProperty('token', value); } @@ -83,38 +83,38 @@ export class SubscriptionModel extends Model { this._setProperty('notification_types', value); } - get sdk(): string | undefined { + get _sdk(): string | undefined { return this._getProperty('sdk'); } - set sdk(value: string | undefined) { + set _sdk(value: string | undefined) { this._setProperty('sdk', value); } - get device_model(): string | undefined { + get _device_model(): string | undefined { return this._getProperty('device_model'); } - set device_model(value: string | undefined) { + set _device_model(value: string | undefined) { this._setProperty('device_model', value); } - get device_os(): string | undefined { + get _device_os(): string | undefined { return this._getProperty('device_os'); } - set device_os(value: string | undefined) { + set _device_os(value: string | undefined) { this._setProperty('device_os', value); } - get web_auth(): string | undefined { + get _web_auth(): string | undefined { return this._getProperty('web_auth'); } - set web_auth(value: string | undefined) { + set _web_auth(value: string | undefined) { this._setProperty('web_auth', value); } - get web_p256(): string | undefined { + get _web_p256(): string | undefined { return this._getProperty('web_p256'); } - set web_p256(value: string | undefined) { + set _web_p256(value: string | undefined) { this._setProperty('web_p256', value); } } diff --git a/src/core/operations/BaseAliasOperation.ts b/src/core/operations/BaseAliasOperation.ts index 55b1bc41e..40c52257b 100644 --- a/src/core/operations/BaseAliasOperation.ts +++ b/src/core/operations/BaseAliasOperation.ts @@ -19,14 +19,14 @@ export abstract class BaseAliasOperation< ) { super(operationName, appId, onesignalId); if (label) { - this.label = label; + this._label = label; } } - get label(): string { + get _label(): string { return this._getProperty('label'); } - protected set label(value: string | undefined) { + protected set _label(value: string | undefined) { this._setProperty('label', value); } } diff --git a/src/core/operations/BaseFullSubscriptionOperation.ts b/src/core/operations/BaseFullSubscriptionOperation.ts index 193129ca7..9d9e9b3ce 100644 --- a/src/core/operations/BaseFullSubscriptionOperation.ts +++ b/src/core/operations/BaseFullSubscriptionOperation.ts @@ -29,106 +29,106 @@ export abstract class BaseFullSubscriptionOperation extends BaseSubscriptionOper super(operationName, appId, onesignalId); if (subscription) { - this.sdk = VERSION; - this.device_model = getDeviceModel(); - this.device_os = getDeviceOS(); - this.enabled = subscription.enabled; - this.notification_types = subscription.notification_types; + this._sdk = VERSION; + this._device_model = getDeviceModel(); + this._device_os = getDeviceOS(); + this._enabled = subscription.enabled; + this._notification_types = subscription.notification_types; this._subscriptionId = subscription.subscriptionId; - this.token = subscription.token; - this.type = subscription.type; - this.web_auth = subscription.web_auth; - this.web_p256 = subscription.web_p256; + this._token = subscription.token; + this._type = subscription.type; + this._web_auth = subscription.web_auth; + this._web_p256 = subscription.web_p256; } } /** * The type of subscription. */ - public get type(): SubscriptionTypeValue { + public get _type(): SubscriptionTypeValue { return this._getProperty('type'); } - protected set type(value: SubscriptionTypeValue) { + protected set _type(value: SubscriptionTypeValue) { this._setProperty('type', value); } /** * The token for the subscription. */ - public get token(): string { + public get _token(): string { return this._getProperty('token'); } - protected set token(value: string) { + protected set _token(value: string) { this._setProperty('token', value); } /** * Whether this subscription is currently enabled. */ - get enabled(): boolean | undefined { + get _enabled(): boolean | undefined { return this._getProperty('enabled'); } - protected set enabled(value: boolean | undefined) { + protected set _enabled(value: boolean | undefined) { this._setProperty('enabled', value); } /** * The notification types this subscription is subscribed to. */ - get notification_types(): NotificationTypeValue | undefined { + get _notification_types(): NotificationTypeValue | undefined { return this._getProperty('notification_types'); } - protected set notification_types(value: NotificationTypeValue | undefined) { + protected set _notification_types(value: NotificationTypeValue | undefined) { this._setProperty('notification_types', value); } /** * The SDK identifier */ - get sdk(): string | undefined { + get _sdk(): string | undefined { return this._getProperty('sdk'); } - protected set sdk(value: string | undefined) { + protected set _sdk(value: string | undefined) { this._setProperty('sdk', value); } /** * The device model */ - get device_model(): string | undefined { + get _device_model(): string | undefined { return this._getProperty('device_model'); } - protected set device_model(value: string | undefined) { + protected set _device_model(value: string | undefined) { this._setProperty('device_model', value); } /** * The device OS version */ - get device_os(): string | undefined { + get _device_os(): string | undefined { return this._getProperty('device_os'); } - protected set device_os(value: string | undefined) { + protected set _device_os(value: string | undefined) { this._setProperty('device_os', value); } /** * Web authentication value */ - get web_auth(): string | undefined { + get _web_auth(): string | undefined { return this._getProperty('web_auth'); } - protected set web_auth(value: string | undefined) { + protected set _web_auth(value: string | undefined) { this._setProperty('web_auth', value); } /** * Web P256 value */ - get web_p256(): string | undefined { + get _web_p256(): string | undefined { return this._getProperty('web_p256'); } - protected set web_p256(value: string | undefined) { + protected set _web_p256(value: string | undefined) { this._setProperty('web_p256', value); } } diff --git a/src/core/operations/BaseTagOperation.ts b/src/core/operations/BaseTagOperation.ts index 03cf87605..01216cdae 100644 --- a/src/core/operations/BaseTagOperation.ts +++ b/src/core/operations/BaseTagOperation.ts @@ -18,16 +18,16 @@ export abstract class BaseTagOperation< key?: string, ) { super(operationName, appId, onesignalId); - if (key) this.key = key; + if (key) this._key = key; } /** * The tag key. */ - get key(): string { + get _key(): string { return this._getProperty('key'); } - protected set key(value: string) { + protected set _key(value: string) { this._setProperty('key', value); } diff --git a/src/core/operations/DeleteAliasOperation.ts b/src/core/operations/DeleteAliasOperation.ts index c2575e446..b6c2db2c7 100644 --- a/src/core/operations/DeleteAliasOperation.ts +++ b/src/core/operations/DeleteAliasOperation.ts @@ -12,7 +12,7 @@ export class DeleteAliasOperation extends BaseAliasOperation { } override get _modifyComparisonKey(): string { - return `${this._appId}.User.${this._onesignalId}.Alias.${this.label}`; + return `${this._appId}.User.${this._onesignalId}.Alias.${this._label}`; } override get _groupComparisonType(): GroupComparisonValue { diff --git a/src/core/operations/SetAliasOperation.ts b/src/core/operations/SetAliasOperation.ts index d74fadc23..e16bee946 100644 --- a/src/core/operations/SetAliasOperation.ts +++ b/src/core/operations/SetAliasOperation.ts @@ -17,17 +17,17 @@ export class SetAliasOperation extends BaseAliasOperation { value?: string, ) { super(OPERATION_NAME._SetAlias, appId, onesignalId, label); - if (value) this.value = value; + if (value) this._value = value; } - get value(): string { + get _value(): string { return this._getProperty('value'); } - private set value(value: string) { + private set _value(value: string) { this._setProperty('value', value); } override get _modifyComparisonKey(): string { - return `${this._appId}.User.${this._onesignalId}.Identity.${this.label}`; + return `${this._appId}.User.${this._onesignalId}.Identity.${this._label}`; } } diff --git a/src/core/operations/SetPropertyOperation.ts b/src/core/operations/SetPropertyOperation.ts index f9d42d344..8b4c35001 100644 --- a/src/core/operations/SetPropertyOperation.ts +++ b/src/core/operations/SetPropertyOperation.ts @@ -33,7 +33,7 @@ export class SetPropertyOperation< super(OPERATION_NAME._SetProperty, appId, onesignalId); if (property && value) { this._property = property; - this.value = value; + this._value = value; } } @@ -50,10 +50,10 @@ export class SetPropertyOperation< /** * The value of that property to update it to. */ - get value() { + get _value() { return this._getProperty('value') as PropertyValue[P]; } - private set value(_value) { + private set _value(_value) { this._setProperty('value', _value); } diff --git a/src/entries/pageSdkInit2.test.ts b/src/entries/pageSdkInit2.test.ts index 1b4c70e3c..3934dfaee 100644 --- a/src/entries/pageSdkInit2.test.ts +++ b/src/entries/pageSdkInit2.test.ts @@ -48,7 +48,7 @@ describe('pageSdkInit 2', () => { { ...subModel.toJSON(), }, - emailSubModel, + emailSubModel.toJSON(), ], }); setCreateUserResponse({ @@ -107,10 +107,10 @@ describe('pageSdkInit 2', () => { expect(subscriptions).toEqual([ { ...shared, - id: subModel.id, + id: subModel._id, modelId: subModel._modelId, onesignalId: ONESIGNAL_ID, - token: subModel.token, + token: subModel._token, type: 'ChromePush', }, { diff --git a/src/onesignal/OneSignal.test.ts b/src/onesignal/OneSignal.test.ts index d0f7e4307..dd9a392af 100644 --- a/src/onesignal/OneSignal.test.ts +++ b/src/onesignal/OneSignal.test.ts @@ -831,11 +831,11 @@ describe('OneSignal - No Consent Required', () => { expect(subscriptions).toEqual([ { ...BASE_SUB, - id: pushSub.id, + id: pushSub._id, modelId: expect.any(String), modelName: 'subscriptions', onesignalId: ONESIGNAL_ID, - token: pushSub.token, + token: pushSub._token, type: 'ChromePush', }, ]); diff --git a/src/onesignal/PushSubscriptionNamespace.ts b/src/onesignal/PushSubscriptionNamespace.ts index 28cd83bef..bd844ad7d 100644 --- a/src/onesignal/PushSubscriptionNamespace.ts +++ b/src/onesignal/PushSubscriptionNamespace.ts @@ -49,7 +49,7 @@ export default class PushSubscriptionNamespace extends EventListenerBase { ._getPushSubscriptionModel() .then((pushModel) => { if (isCompleteSubscriptionObject(pushModel)) { - this._id = pushModel.id; + this._id = pushModel._id; } }) .catch((e) => { diff --git a/src/onesignal/User.ts b/src/onesignal/User.ts index 7a2462d01..057aac9b0 100644 --- a/src/onesignal/User.ts +++ b/src/onesignal/User.ts @@ -150,7 +150,7 @@ export default class User { OneSignal._coreDirector._getEmailSubscriptionModels(); emailSubscriptions.forEach((model) => { - if (model.token === email) { + if (model._token === email) { OneSignal._coreDirector._removeSubscriptionModel(model._modelId); } }); @@ -165,7 +165,7 @@ export default class User { const smsSubscriptions = OneSignal._coreDirector._getSmsSubscriptionModels(); smsSubscriptions.forEach((model) => { - if (model.token === smsNumber) { + if (model._token === smsNumber) { OneSignal._coreDirector._removeSubscriptionModel(model._modelId); } }); @@ -275,7 +275,7 @@ function addSubscriptionToModels({ }): void { const hasSubscription = OneSignal._coreDirector._subscriptionModelStore ._list() - .find((model) => model.token === token && model.type === type); + .find((model) => model._token === token && model._type === type); if (hasSubscription) return; const identityModel = OneSignal._coreDirector._getIdentityModel(); diff --git a/src/onesignal/UserNamespace.test.ts b/src/onesignal/UserNamespace.test.ts index eac7f451d..b4623cfb2 100644 --- a/src/onesignal/UserNamespace.test.ts +++ b/src/onesignal/UserNamespace.test.ts @@ -193,7 +193,7 @@ describe('Email Management', () => { const getEmailSubscription = (email: string) => { const subscriptionModels = OneSignal._coreDirector._getEmailSubscriptionModels(); - return subscriptionModels.find((model) => model.token === email); + return subscriptionModels.find((model) => model._token === email); }; test('can add an email subscription', async () => { @@ -211,7 +211,7 @@ describe('Email Management', () => { expect(addSubscriptionSpy).toHaveBeenCalled(); const subscription = getEmailSubscription(email); expect(subscription).toBeDefined(); - expect(subscription?.token).toBe(email); + expect(subscription?._token).toBe(email); }); test('should remove an email subscription', async () => { @@ -242,7 +242,7 @@ describe('SMS Management', () => { const getSmsSubscription = (smsNumber: string) => { const subscriptionModels = OneSignal._coreDirector._getSmsSubscriptionModels(); - return subscriptionModels.find((model) => model.token === smsNumber); + return subscriptionModels.find((model) => model._token === smsNumber); }; test('should add an SMS subscription', async () => { @@ -261,7 +261,7 @@ describe('SMS Management', () => { expect(addSubscriptionSpy).toHaveBeenCalled(); const subscription = getSmsSubscription(smsNumber); expect(subscription).toBeDefined(); - expect(subscription?.token).toBe(smsNumber); + expect(subscription?._token).toBe(smsNumber); }); test('should remove an SMS subscription', async () => { @@ -286,7 +286,7 @@ describe('SMS Management', () => { expect(removeSubscriptionSpy).toHaveBeenCalled(); subscription = getSmsSubscription(smsNumber); expect(subscription).toBeUndefined(); - expect(subscription?.token).toBe(undefined); + expect(subscription?._token).toBe(undefined); }); }); diff --git a/src/onesignal/userDirector.ts b/src/onesignal/userDirector.ts index 7e8b9c6ea..f394ae0ff 100644 --- a/src/onesignal/userDirector.ts +++ b/src/onesignal/userDirector.ts @@ -36,7 +36,7 @@ export async function createUserOnServer(): Promise { ...subData, appId, onesignalId: identityModel._onesignalId, - subscriptionId: pushOp.id!, + subscriptionId: pushOp._id!, }), ); } else { diff --git a/src/page/managers/LoginManager.ts b/src/page/managers/LoginManager.ts index e142e21da..1065066be 100644 --- a/src/page/managers/LoginManager.ts +++ b/src/page/managers/LoginManager.ts @@ -63,7 +63,7 @@ export default class LoginManager { new TransferSubscriptionOperation( appId, newIdentityOneSignalId, - pushOp.id, + pushOp._id, ), ); } diff --git a/src/shared/listeners.ts b/src/shared/listeners.ts index 607ea5b8a..3c8d17bf5 100644 --- a/src/shared/listeners.ts +++ b/src/shared/listeners.ts @@ -37,7 +37,7 @@ export async function checkAndTriggerSubscriptionChanged() { const currentPushToken = await getCurrentPushToken(); const pushModel = await OneSignal._coreDirector._getPushSubscriptionModel(); - const pushSubscriptionId = pushModel?.id; + const pushSubscriptionId = pushModel?._id; const didStateChange = isPushEnabled !== lastKnownPushEnabled || diff --git a/src/shared/managers/UpdateManager.ts b/src/shared/managers/UpdateManager.ts index d08c262c7..87e8e5244 100644 --- a/src/shared/managers/UpdateManager.ts +++ b/src/shared/managers/UpdateManager.ts @@ -96,7 +96,7 @@ export class UpdateManager { notification_ids: notificationIds, direct: true, subscription: { - id: pushSubscriptionModel.id, + id: pushSubscriptionModel._id, type: getSubscriptionType(), }, }; @@ -131,7 +131,7 @@ export class UpdateManager { notification_ids: notificationIds, direct: false, subscription: { - id: pushSubscriptionModel.id, + id: pushSubscriptionModel._id, type: getSubscriptionType(), }, }; @@ -163,7 +163,7 @@ export class UpdateManager { id: outcomeName, app_id: appId, subscription: { - id: pushSubscriptionModel.id, + id: pushSubscriptionModel._id, type: getSubscriptionType(), }, }; diff --git a/src/shared/managers/sessionManager/SessionManager.ts b/src/shared/managers/sessionManager/SessionManager.ts index 1873761c5..4c634a13f 100644 --- a/src/shared/managers/sessionManager/SessionManager.ts +++ b/src/shared/managers/sessionManager/SessionManager.ts @@ -106,7 +106,7 @@ export class SessionManager implements ISessionManager { } const { _onesignalId: onesignalId } = identityModel; - const { id: subscriptionId } = pushSubscriptionModel; + const { _id: subscriptionId } = pushSubscriptionModel; return { onesignalId, subscriptionId }; } @@ -379,7 +379,7 @@ export class SessionManager implements ISessionManager { let subscriptionId; if (isCompleteSubscriptionObject(pushSubscription)) { - subscriptionId = pushSubscription?.id; + subscriptionId = pushSubscription?._id; } try { diff --git a/src/shared/managers/subscription/page.test.ts b/src/shared/managers/subscription/page.test.ts index 040c372f9..482bf4d73 100644 --- a/src/shared/managers/subscription/page.test.ts +++ b/src/shared/managers/subscription/page.test.ts @@ -46,7 +46,7 @@ describe('SubscriptionManager', () => { subModels = await OneSignal._coreDirector._subscriptionModelStore._list(); expect(subModels.length).toBe(1); - const id = subModels[0].id; + const id = subModels[0]._id; expect(IDManager._isLocalId(id)).toBe(true); expect(subModels[0].toJSON()).toEqual({ id, @@ -137,11 +137,11 @@ describe('SubscriptionManager', () => { const updatedPushModel = (await OneSignal._coreDirector._getPushSubscriptionModel())!; - expect(updatedPushModel.token).toBe( + expect(updatedPushModel._token).toBe( rawSubscription.w3cEndpoint?.toString(), ); - expect(updatedPushModel.web_auth).toBe(rawSubscription.w3cAuth); - expect(updatedPushModel.web_p256).toBe(rawSubscription.w3cP256dh); + expect(updatedPushModel._web_auth).toBe(rawSubscription.w3cAuth); + expect(updatedPushModel._web_p256).toBe(rawSubscription.w3cP256dh); await vi.waitUntil(() => updateSubscriptionFn.mock.calls.length > 0); }); diff --git a/src/shared/managers/subscription/page.ts b/src/shared/managers/subscription/page.ts index f952fef94..7436c36df 100644 --- a/src/shared/managers/subscription/page.ts +++ b/src/shared/managers/subscription/page.ts @@ -65,7 +65,7 @@ export const updatePushSubscriptionModelWithRawSubscription = async ( return createUserOnServer(); } // for users with data failed to create a user or user + subscription on the server - if (IDManager._isLocalId(pushModel.id)) { + if (IDManager._isLocalId(pushModel._id)) { return createUserOnServer(); } @@ -102,7 +102,7 @@ export class SubscriptionManagerPage extends SubscriptionManagerBase { diff --git a/src/shared/managers/utils.ts b/src/shared/managers/utils.ts index 359eaca6e..08cfe28dd 100644 --- a/src/shared/managers/utils.ts +++ b/src/shared/managers/utils.ts @@ -1,6 +1,6 @@ export function isCompleteSubscriptionObject(obj?: { - type?: string; - id?: string; -}): obj is { type: string; id: string } { - return obj?.type !== undefined && obj?.id !== undefined; + _type?: string; + _id?: string; +}): obj is { _type: string; _id: string } { + return obj?._type !== undefined && obj?._id !== undefined; } From a7a87221e9105e237f2a22619eb403fc991e3428 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Fri, 24 Oct 2025 10:52:46 -0700 Subject: [PATCH 5/6] add unknown op error --- src/core/executors/CustomEventOperationExecutor.ts | 5 ++--- src/core/executors/IdentityOperationExecutor.ts | 11 +++-------- src/core/executors/LoginUserOperationExecutor.ts | 9 ++++----- src/core/executors/RefreshUserOperationExecutor.ts | 11 +++-------- src/core/executors/SubscriptionOperationExecutor.ts | 3 ++- src/core/executors/UpdateUserOperationExecutor.ts | 3 ++- src/core/modelRepo/OperationModelStore.ts | 3 ++- src/shared/errors/common.ts | 3 +++ 8 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/core/executors/CustomEventOperationExecutor.ts b/src/core/executors/CustomEventOperationExecutor.ts index c3a082076..4447fe221 100644 --- a/src/core/executors/CustomEventOperationExecutor.ts +++ b/src/core/executors/CustomEventOperationExecutor.ts @@ -3,6 +3,7 @@ import { getDeviceOS, getSubscriptionType, } from 'src/shared/environment/detect'; +import { UnknownOpError } from 'src/shared/errors/common'; import { getResponseStatusType, ResponseStatusType, @@ -44,9 +45,7 @@ export class CustomEventsOperationExecutor implements IOperationExecutor { const operation = operations[0]; if (!(operation instanceof TrackCustomEventOperation)) { - throw new Error( - `Unrecognized operation! Expected TrackEventOperation, got: ${operation.constructor.name}`, - ); + throw UnknownOpError(operation); } const response = await sendCustomEvent( diff --git a/src/core/executors/IdentityOperationExecutor.ts b/src/core/executors/IdentityOperationExecutor.ts index f8919eceb..fa9df1de6 100644 --- a/src/core/executors/IdentityOperationExecutor.ts +++ b/src/core/executors/IdentityOperationExecutor.ts @@ -4,6 +4,7 @@ import { type IOperationExecutor, } from 'src/core/types/operation'; import type { IRebuildUserService } from 'src/core/types/user'; +import { UnknownOpError } from 'src/shared/errors/common'; import { getResponseStatusType, ResponseStatusType, @@ -40,9 +41,7 @@ export class IdentityOperationExecutor implements IOperationExecutor { } async _execute(operations: Operation[]): Promise { - debug( - `IdentityOperationExecutor(operations: ${JSON.stringify(operations)})`, - ); + debug(`IdentityOperationExecutor`); const invalidOps = operations.filter( (op) => @@ -51,11 +50,7 @@ export class IdentityOperationExecutor implements IOperationExecutor { ), ); if (invalidOps.length > 0) { - throw new Error( - `Unrecognized operation(s)! Attempted operations:\n${JSON.stringify( - operations, - )}`, - ); + throw UnknownOpError(operations); } const hasSetAlias = operations.some( diff --git a/src/core/executors/LoginUserOperationExecutor.ts b/src/core/executors/LoginUserOperationExecutor.ts index c75335b67..07d2ce4c9 100644 --- a/src/core/executors/LoginUserOperationExecutor.ts +++ b/src/core/executors/LoginUserOperationExecutor.ts @@ -3,6 +3,7 @@ import { ExecutionResult, type IOperationExecutor, } from 'src/core/types/operation'; +import { UnknownOpError } from 'src/shared/errors/common'; import { getTimeZoneId } from 'src/shared/helpers/general'; import { getResponseStatusType, @@ -62,15 +63,13 @@ export class LoginUserOperationExecutor implements IOperationExecutor { } async _execute(operations: Operation[]): Promise { - debug( - `LoginUserOperationExecutor(operation: ${JSON.stringify(operations)})`, - ); + debug(`LoginUserOperationExecutor`); const startingOp = operations[0]; if (startingOp instanceof LoginUserOperation) return this._loginUser(startingOp, operations.slice(1)); - throw new Error(`Unrecognized operation: ${startingOp._name}`); + throw UnknownOpError(startingOp); } private async _loginUser( @@ -163,7 +162,7 @@ export class LoginUserOperationExecutor implements IOperationExecutor { subscriptions, ); } else { - throw new Error(`Unrecognized operation: ${operation._name}`); + throw UnknownOpError(operation); } } diff --git a/src/core/executors/RefreshUserOperationExecutor.ts b/src/core/executors/RefreshUserOperationExecutor.ts index efb205de7..7861da024 100644 --- a/src/core/executors/RefreshUserOperationExecutor.ts +++ b/src/core/executors/RefreshUserOperationExecutor.ts @@ -1,3 +1,4 @@ +import { UnknownOpError } from 'src/shared/errors/common'; import { getResponseStatusType, ResponseStatusType, @@ -52,16 +53,10 @@ export class RefreshUserOperationExecutor implements IOperationExecutor { } async _execute(operations: Operation[]): Promise { - debug( - `RefreshUserOperationExecutor(operation: ${JSON.stringify(operations)})`, - ); + debug(`RefreshUserOperationExecutor`); if (operations.some((op) => !(op instanceof RefreshUserOperation))) - throw new Error( - `Unrecognized operation(s)! Attempted operations:\n${JSON.stringify( - operations, - )}`, - ); + throw UnknownOpError(operations); const startingOp = operations[0]; return this._getUser(startingOp); diff --git a/src/core/executors/SubscriptionOperationExecutor.ts b/src/core/executors/SubscriptionOperationExecutor.ts index 0e307f47a..a787e126d 100644 --- a/src/core/executors/SubscriptionOperationExecutor.ts +++ b/src/core/executors/SubscriptionOperationExecutor.ts @@ -3,6 +3,7 @@ import { type IOperationExecutor, } from 'src/core/types/operation'; import type { IRebuildUserService } from 'src/core/types/user'; +import { UnknownOpError } from 'src/shared/errors/common'; import { getResponseStatusType, ResponseStatusType, @@ -79,7 +80,7 @@ export class SubscriptionOperationExecutor implements IOperationExecutor { ); return this._transferSubscription(startingOp); } - throw new Error(`Unrecognized operation: ${startingOp}`); + throw UnknownOpError(startingOp); } private async _createSubscription( diff --git a/src/core/executors/UpdateUserOperationExecutor.ts b/src/core/executors/UpdateUserOperationExecutor.ts index 525d2d59a..b78b79e57 100644 --- a/src/core/executors/UpdateUserOperationExecutor.ts +++ b/src/core/executors/UpdateUserOperationExecutor.ts @@ -1,3 +1,4 @@ +import { UnknownOpError } from 'src/shared/errors/common'; import { getResponseStatusType, ResponseStatusType, @@ -65,7 +66,7 @@ export class UpdateUserOperationExecutor implements IOperationExecutor { propertiesObject, ); } else { - throw new Error(`Unrecognized operation: ${operation}`); + throw UnknownOpError(operation); } } diff --git a/src/core/modelRepo/OperationModelStore.ts b/src/core/modelRepo/OperationModelStore.ts index c50de992c..94096d1c1 100644 --- a/src/core/modelRepo/OperationModelStore.ts +++ b/src/core/modelRepo/OperationModelStore.ts @@ -1,4 +1,5 @@ import type { IDBStoreName } from 'src/shared/database/types'; +import { UnknownOpError } from 'src/shared/errors/common'; import { error } from 'src/shared/libraries/log'; import { OPERATION_NAME } from '../constants'; import { CreateSubscriptionOperation } from '../operations/CreateSubscriptionOperation'; @@ -71,7 +72,7 @@ export class OperationModelStore extends ModelStore { operation = new TrackCustomEventOperation(); break; default: - throw new Error(`Unrecognized operation: ${operationName}`); + throw UnknownOpError({ _name: operationName }); } // populate the operation with the data diff --git a/src/shared/errors/common.ts b/src/shared/errors/common.ts index 621def530..10ddd6313 100644 --- a/src/shared/errors/common.ts +++ b/src/shared/errors/common.ts @@ -65,3 +65,6 @@ export const WrongTypeArgumentError = (argName: string) => export const ReservedArgumentError = (argName: string) => new Error(`"${argName}" is reserved`); + +export const UnknownOpError = (op: { _name?: string } | { _name?: string }[]) => + new Error(`Unknown op(s):${op}`); From cbe0e82032f2c7ad63db8394741323e9b5938a57 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Fri, 24 Oct 2025 10:59:06 -0700 Subject: [PATCH 6/6] simplify get language code --- package.json | 2 +- .../IdentityOperationExecutor.test.ts | 7 ++-- .../LoginUserOperationExecutor.test.ts | 9 ++--- .../executors/LoginUserOperationExecutor.ts | 36 +++++-------------- .../RefreshUserOperationExecutor.test.ts | 7 ++-- .../SubscriptionOperationExecutor.test.ts | 5 ++- .../UpdateUserOperationExecutor.test.ts | 5 ++- src/onesignal/SessionNamespace.ts | 6 ++-- 8 files changed, 23 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index b33eb7691..1d9a81290 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ }, { "path": "./build/releases/OneSignalSDK.page.es6.js", - "limit": "45.364 kB", + "limit": "45.322 kB", "gzip": true }, { diff --git a/src/core/executors/IdentityOperationExecutor.test.ts b/src/core/executors/IdentityOperationExecutor.test.ts index a7c30f3ca..4e6ffd202 100644 --- a/src/core/executors/IdentityOperationExecutor.test.ts +++ b/src/core/executors/IdentityOperationExecutor.test.ts @@ -9,6 +9,7 @@ import { } from '__test__/support/helpers/requests'; import { updateIdentityModel } from '__test__/support/helpers/setup'; import { ExecutionResult } from 'src/core/types/operation'; +import { UnknownOpError } from 'src/shared/errors/common'; import type { MockInstance } from 'vitest'; import { OPERATION_NAME } from '../constants'; import { RebuildUserService } from '../modelRepo/RebuildUserService'; @@ -82,11 +83,7 @@ describe('IdentityOperationExecutor', () => { // with invalid ops const ops = [setAliasOp, deleteAliasOp, someOp]; const result = executor._execute(ops); - await expect(() => result).rejects.toThrow( - `Unrecognized operation(s)! Attempted operations:\n${JSON.stringify( - ops, - )}`, - ); + await expect(() => result).rejects.toThrow(UnknownOpError(ops)); // with both set and delete alias ops const ops2 = [setAliasOp, deleteAliasOp]; diff --git a/src/core/executors/LoginUserOperationExecutor.test.ts b/src/core/executors/LoginUserOperationExecutor.test.ts index 1d86e948b..170d9c508 100644 --- a/src/core/executors/LoginUserOperationExecutor.test.ts +++ b/src/core/executors/LoginUserOperationExecutor.test.ts @@ -24,6 +24,7 @@ import { updatePropertiesModel, } from '__test__/support/helpers/setup'; import { getPushToken, setPushToken } from 'src/shared/database/subscription'; +import { UnknownOpError } from 'src/shared/errors/common'; import { NotificationType, SubscriptionType, @@ -97,9 +98,7 @@ describe('LoginUserOperationExecutor', () => { // with invalid ops const ops = [someOp]; const result = executor._execute(ops); - await expect(() => result).rejects.toThrow( - `Unrecognized operation: ${someOp._name}`, - ); + await expect(() => result).rejects.toThrow(UnknownOpError(someOp)); }); describe('create user', () => { @@ -124,9 +123,7 @@ describe('LoginUserOperationExecutor', () => { const someOp = new SomeOperation(); const ops2 = [loginOp, transferSubOp, someOp]; const res2 = executor._execute(ops2); - await expect(res2).rejects.toThrow( - `Unrecognized operation: ${someOp._name}`, - ); + await expect(res2).rejects.toThrow(UnknownOpError(someOp)); }); test('can create user if there is no onesignal id or externalId', async () => { diff --git a/src/core/executors/LoginUserOperationExecutor.ts b/src/core/executors/LoginUserOperationExecutor.ts index 07d2ce4c9..5d538ee4f 100644 --- a/src/core/executors/LoginUserOperationExecutor.ts +++ b/src/core/executors/LoginUserOperationExecutor.ts @@ -335,34 +335,16 @@ export class LoginUserOperationExecutor implements IOperationExecutor { } } -const TRADITIONAL_CHINESE_LANGUAGE_TAG = ['tw', 'hant']; const SIMPLIFIED_CHINESE_LANGUAGE_TAG = ['cn', 'hans']; const getLanguage = () => { - let languageTag = navigator.language; - if (languageTag) { - languageTag = languageTag.toLowerCase(); - const languageSubtags = languageTag.split('-'); - if (languageSubtags[0] == 'zh') { - // The language is zh-? - // We must categorize the language as either zh-Hans (simplified) or zh-Hant (traditional); - // OneSignal only supports these two Chinese variants - for (const traditionalSubtag of TRADITIONAL_CHINESE_LANGUAGE_TAG) { - if (languageSubtags.indexOf(traditionalSubtag) !== -1) { - return 'zh-Hant'; - } - } - for (const simpleSubtag of SIMPLIFIED_CHINESE_LANGUAGE_TAG) { - if (languageSubtags.indexOf(simpleSubtag) !== -1) { - return 'zh-Hans'; - } - } - return 'zh-Hant'; // Return Chinese traditional by default - } else { - // Return the language subtag (it can be three characters, so truncate it down to 2 just to be sure) - return languageSubtags[0].substring(0, 2); - } - } else { - return 'en'; - } + const languageTag = navigator.language?.toLowerCase(); + if (!languageTag) return 'en'; + + const [primary, ...subtags] = languageTag.split('-'); + if (primary !== 'zh') return primary.substring(0, 2); + + if (SIMPLIFIED_CHINESE_LANGUAGE_TAG.some((tag) => subtags.includes(tag))) + return 'zh-Hans'; + return 'zh-Hant'; }; diff --git a/src/core/executors/RefreshUserOperationExecutor.test.ts b/src/core/executors/RefreshUserOperationExecutor.test.ts index 84ba3699f..d9bddec2c 100644 --- a/src/core/executors/RefreshUserOperationExecutor.test.ts +++ b/src/core/executors/RefreshUserOperationExecutor.test.ts @@ -15,6 +15,7 @@ import { } from '__test__/support/helpers/requests'; import { updateIdentityModel } from '__test__/support/helpers/setup'; import { setPushToken } from 'src/shared/database/subscription'; +import { UnknownOpError } from 'src/shared/errors/common'; import { NotificationType, SubscriptionType, @@ -83,11 +84,7 @@ describe('RefreshUserOperationExecutor', () => { const ops = [someOp]; const result = executor._execute(ops); - await expect(() => result).rejects.toThrow( - `Unrecognized operation(s)! Attempted operations:\n${JSON.stringify( - ops, - )}`, - ); + await expect(() => result).rejects.toThrow(UnknownOpError(ops)); }); describe('getUser', () => { diff --git a/src/core/executors/SubscriptionOperationExecutor.test.ts b/src/core/executors/SubscriptionOperationExecutor.test.ts index f9278c4b1..a85f40a6b 100644 --- a/src/core/executors/SubscriptionOperationExecutor.test.ts +++ b/src/core/executors/SubscriptionOperationExecutor.test.ts @@ -17,6 +17,7 @@ import { } from '__test__/support/helpers/requests'; import { setupSubscriptionModel } from '__test__/support/helpers/setup'; import { setPushToken } from 'src/shared/database/subscription'; +import { UnknownOpError } from 'src/shared/errors/common'; import { NotificationType, SubscriptionType, @@ -100,9 +101,7 @@ describe('SubscriptionOperationExecutor', () => { const ops = [someOp]; const res1 = executor._execute(ops); - await expect(() => res1).rejects.toThrow( - `Unrecognized operation: ${ops[0]}`, - ); + await expect(() => res1).rejects.toThrow(UnknownOpError(ops)); const deleteOp = new DeleteSubscriptionOperation( APP_ID, diff --git a/src/core/executors/UpdateUserOperationExecutor.test.ts b/src/core/executors/UpdateUserOperationExecutor.test.ts index f8e5ea803..50399b54e 100644 --- a/src/core/executors/UpdateUserOperationExecutor.test.ts +++ b/src/core/executors/UpdateUserOperationExecutor.test.ts @@ -6,6 +6,7 @@ import { setUpdateUserResponse, } from '__test__/support/helpers/requests'; import { updateIdentityModel } from '__test__/support/helpers/setup'; +import { UnknownOpError } from 'src/shared/errors/common'; import { type MockInstance } from 'vitest'; import { OPERATION_NAME } from '../constants'; import { RebuildUserService } from '../modelRepo/RebuildUserService'; @@ -70,9 +71,7 @@ describe('UpdateUserOperationExecutor', () => { const ops = [someOp]; const result = executor._execute(ops); - await expect(() => result).rejects.toThrow( - `Unrecognized operation: ${ops[0]}`, - ); + await expect(() => result).rejects.toThrow(UnknownOpError(someOp)); }); describe('SetPropertyOperation', () => { diff --git a/src/onesignal/SessionNamespace.ts b/src/onesignal/SessionNamespace.ts index 425d0a985..5b003354c 100644 --- a/src/onesignal/SessionNamespace.ts +++ b/src/onesignal/SessionNamespace.ts @@ -1,6 +1,6 @@ +import { error, warn } from 'src/shared/libraries/log'; import OutcomesHelper from '../shared/helpers/OutcomesHelper'; import { OutcomeAttributionType } from '../shared/models/Outcomes'; -import { error, warn } from 'src/shared/libraries/log'; export class SessionNamespace { async sendOutcome( @@ -60,9 +60,7 @@ export class SessionNamespace { const outcomeAttribution = await outcomesHelper._getAttribution(); if (outcomeAttribution.type === OutcomeAttributionType._NotSupported) { - warn( - 'You are on a free plan. Please upgrade to use this functionality.', - ); + warn('You are on a free plan. Please upgrade to use this functionality.'); return; }