@schibsted/account-sdk-browser 6.0.0-alpha.1 → 6.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -280
- package/dist/account-sdk.d.ts +22 -0
- package/dist/account.d.ts +179 -0
- package/dist/cache.d.ts +65 -0
- package/dist/compatibility/index.d.ts +2 -0
- package/dist/compatibility/install-legacy-compatibility.d.ts +10 -0
- package/dist/compatibility/legacy-identity.d.ts +29 -0
- package/dist/compatibility/legacy-monetization.d.ts +9 -0
- package/dist/compatibility/types.d.ts +40 -0
- package/dist/compatibility/warnings.d.ts +3 -0
- package/dist/compatibility.js +167 -0
- package/dist/compatibility.js.map +1 -0
- package/dist/config.d.ts +86 -0
- package/dist/globals.d.ts +11 -0
- package/dist/has-access-response.d.ts +2 -0
- package/dist/identity.d.ts +302 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +782 -0
- package/dist/index.js.map +1 -0
- package/dist/monetization.d.ts +39 -0
- package/{src → dist}/object.d.ts +4 -9
- package/dist/popup.d.ts +9 -0
- package/dist/resolve-browser-window-X5jXljW9.js +55 -0
- package/dist/resolve-browser-window-X5jXljW9.js.map +1 -0
- package/dist/resolve-browser-window.d.ts +1 -0
- package/dist/rest-client.d.ts +102 -0
- package/dist/rest-clients.d.ts +10 -0
- package/dist/sdk-error.d.ts +29 -0
- package/dist/session-response.d.ts +54 -0
- package/dist/session-state.d.ts +13 -0
- package/{src/spidTalk.d.ts → dist/spid-talk.d.ts} +4 -6
- package/dist/types/account.d.ts +48 -0
- package/dist/types/common.d.ts +28 -0
- package/dist/types/identity.d.ts +23 -0
- package/dist/types/login.d.ts +125 -0
- package/dist/types/monetization.d.ts +26 -0
- package/dist/types/session.d.ts +146 -0
- package/dist/url.d.ts +8 -0
- package/dist/validate.d.ts +50 -0
- package/dist/version.d.ts +2 -0
- package/package.json +34 -25
- package/src/account-sdk.ts +92 -0
- package/src/account.ts +337 -0
- package/src/{cache.js → cache.ts} +53 -38
- package/src/compatibility/index.ts +10 -0
- package/src/compatibility/install-legacy-compatibility.ts +144 -0
- package/src/compatibility/legacy-identity.ts +220 -0
- package/src/compatibility/legacy-monetization.ts +30 -0
- package/src/compatibility/types.ts +76 -0
- package/src/compatibility/warnings.ts +28 -0
- package/src/{config.js → config.ts} +7 -32
- package/src/globals.ts +8 -0
- package/src/has-access-response.ts +35 -0
- package/src/identity.ts +1026 -0
- package/src/index.ts +40 -0
- package/src/monetization.ts +128 -0
- package/src/{object.js → object.ts} +9 -16
- package/src/popup.ts +74 -0
- package/src/resolve-browser-window.ts +11 -0
- package/src/rest-client.ts +253 -0
- package/src/rest-clients.ts +30 -0
- package/src/sdk-error.ts +61 -0
- package/src/session-response.ts +100 -0
- package/src/session-state.ts +20 -0
- package/src/{spidTalk.js → spid-talk.ts} +10 -12
- package/src/types/account.ts +55 -0
- package/src/types/common.ts +32 -0
- package/src/types/identity.ts +26 -0
- package/src/types/login.ts +150 -0
- package/src/types/monetization.ts +29 -0
- package/src/types/session.ts +169 -0
- package/src/{url.js → url.ts} +6 -10
- package/src/{validate.js → validate.ts} +27 -43
- package/src/{version.js → version.ts} +1 -2
- package/identity.d.ts +0 -1
- package/identity.js +0 -5
- package/index.d.ts +0 -4
- package/index.js +0 -9
- package/monetization.d.ts +0 -1
- package/monetization.js +0 -5
- package/payment.d.ts +0 -1
- package/payment.js +0 -5
- package/src/RESTClient.d.ts +0 -89
- package/src/RESTClient.js +0 -193
- package/src/SDKError.d.ts +0 -16
- package/src/SDKError.js +0 -55
- package/src/cache.d.ts +0 -64
- package/src/config.d.ts +0 -34
- package/src/global-registry.js +0 -20
- package/src/identity.d.ts +0 -679
- package/src/identity.js +0 -1154
- package/src/monetization.d.ts +0 -80
- package/src/monetization.js +0 -172
- package/src/payment.d.ts +0 -115
- package/src/payment.js +0 -211
- package/src/popup.d.ts +0 -10
- package/src/popup.js +0 -59
- package/src/url.d.ts +0 -10
- package/src/validate.d.ts +0 -64
- package/src/version.d.ts +0 -2
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/* Copyright 2026 Schibsted Products & Technology AS. Licensed under the terms of the MIT license.
|
|
2
|
+
* See LICENSE.md in the project root.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Account } from './account.js';
|
|
6
|
+
import { resolveBrowserWindow } from './resolve-browser-window.js';
|
|
7
|
+
import type { AccountConfig } from './types/account.js';
|
|
8
|
+
|
|
9
|
+
const ACCOUNT_READY_EVENT = 'schAccount:ready';
|
|
10
|
+
const GET_ACCOUNT_SDK_TIMEOUT_MS = 4000;
|
|
11
|
+
|
|
12
|
+
let pendingAccountPromise: Promise<Account> | undefined;
|
|
13
|
+
|
|
14
|
+
const createUnavailableError = (): Error =>
|
|
15
|
+
new Error('Schibsted Account SDK is not available in this browser context');
|
|
16
|
+
|
|
17
|
+
const createTimeoutError = (): Error =>
|
|
18
|
+
new Error(`Schibsted Account SDK was not initialized within ${GET_ACCOUNT_SDK_TIMEOUT_MS} ms`);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Creates and registers the single Account SDK instance for the current browser window.
|
|
22
|
+
*
|
|
23
|
+
* The created instance is stored on `window.schAccount` and the SDK emits
|
|
24
|
+
* `schAccount:ready` with the instance in `event.detail.instance`.
|
|
25
|
+
*
|
|
26
|
+
* @param config - Client, redirect, environment, and Session Service configuration.
|
|
27
|
+
* @throws {SDKError} If the SDK cannot run in the current browser context, if an Account instance
|
|
28
|
+
* has already been initialized, or if configuration validation fails.
|
|
29
|
+
* @group Core API
|
|
30
|
+
*/
|
|
31
|
+
export function createAccountSdk(config: AccountConfig): Account {
|
|
32
|
+
return new Account(config);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Resolves the Account SDK instance registered by `createAccountSdk()`.
|
|
37
|
+
*
|
|
38
|
+
* If the instance already exists, the promise resolves immediately. Otherwise it waits for
|
|
39
|
+
* `schAccount:ready` and rejects if initialization does not happen within the SDK timeout.
|
|
40
|
+
* @group Core API
|
|
41
|
+
*/
|
|
42
|
+
export function getAccountSdk(): Promise<Account> {
|
|
43
|
+
const browserWindow = resolveBrowserWindow();
|
|
44
|
+
|
|
45
|
+
if (!browserWindow) {
|
|
46
|
+
const error = createUnavailableError();
|
|
47
|
+
console.error(error.message);
|
|
48
|
+
return Promise.reject(error);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (browserWindow.schAccount) {
|
|
52
|
+
return Promise.resolve(browserWindow.schAccount);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (pendingAccountPromise) {
|
|
56
|
+
return pendingAccountPromise;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
pendingAccountPromise = new Promise<Account>((resolve, reject) => {
|
|
60
|
+
let timeoutId: number | undefined;
|
|
61
|
+
|
|
62
|
+
const cleanup = () => {
|
|
63
|
+
browserWindow.removeEventListener(ACCOUNT_READY_EVENT, resolveRegisteredAccount);
|
|
64
|
+
if (timeoutId !== undefined) {
|
|
65
|
+
browserWindow.clearTimeout(timeoutId);
|
|
66
|
+
}
|
|
67
|
+
pendingAccountPromise = undefined;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const resolveRegisteredAccount = () => {
|
|
71
|
+
const account = browserWindow.schAccount;
|
|
72
|
+
if (!account) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
cleanup();
|
|
77
|
+
resolve(account);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
browserWindow.addEventListener(ACCOUNT_READY_EVENT, resolveRegisteredAccount);
|
|
81
|
+
timeoutId = browserWindow.setTimeout(() => {
|
|
82
|
+
const error = createTimeoutError();
|
|
83
|
+
console.error(error.message);
|
|
84
|
+
cleanup();
|
|
85
|
+
reject(error);
|
|
86
|
+
}, GET_ACCOUNT_SDK_TIMEOUT_MS);
|
|
87
|
+
|
|
88
|
+
resolveRegisteredAccount();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return pendingAccountPromise;
|
|
92
|
+
}
|
package/src/account.ts
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/* Copyright 2026 Schibsted Products & Technology AS. Licensed under the terms of the MIT license.
|
|
2
|
+
* See LICENSE.md in the project root.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import Identity from './identity.js';
|
|
6
|
+
import Monetization from './monetization.js';
|
|
7
|
+
import { resolveBrowserWindow } from './resolve-browser-window.js';
|
|
8
|
+
import SDKError from './sdk-error.js';
|
|
9
|
+
import { sessionStates } from './session-state.js';
|
|
10
|
+
import type { AccountConfig, AccountEventListener, AccountEventName } from './types/account.js';
|
|
11
|
+
import type {
|
|
12
|
+
LoginOptions,
|
|
13
|
+
SimplifiedLoginData,
|
|
14
|
+
SimplifiedLoginWidgetLoginOptions,
|
|
15
|
+
SimplifiedLoginWidgetOptions,
|
|
16
|
+
} from './types/login.js';
|
|
17
|
+
import type { HasAccessResult } from './types/monetization.js';
|
|
18
|
+
import type { ConnectedSessionResponse, SessionResponse, SessionUserId } from './types/session.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Unified client-side interface for a configured Schibsted Account integration.
|
|
22
|
+
*
|
|
23
|
+
* Create an instance with `createAccountSdk()` unless you explicitly need to construct it
|
|
24
|
+
* yourself. The instance coordinates identity, login, session, and access-check features for one
|
|
25
|
+
* configured client.
|
|
26
|
+
*
|
|
27
|
+
* @group Core API
|
|
28
|
+
*/
|
|
29
|
+
export class Account {
|
|
30
|
+
#identity: Identity;
|
|
31
|
+
#monetization: Monetization;
|
|
32
|
+
#defaultProductIds?: string[];
|
|
33
|
+
|
|
34
|
+
constructor(config: AccountConfig) {
|
|
35
|
+
const browserWindow = resolveBrowserWindow(config.window);
|
|
36
|
+
|
|
37
|
+
if (!browserWindow) {
|
|
38
|
+
throw new SDKError('Schibsted Account SDK is not available in this browser context');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (browserWindow.schAccount) {
|
|
42
|
+
throw new SDKError('Schibsted Account SDK has already been initialized');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const { log, callbackBeforeRedirect, defaultProductIds, varnish } = config;
|
|
46
|
+
const sharedConfig = {
|
|
47
|
+
clientId: config.clientId,
|
|
48
|
+
redirectUri: config.redirectUri,
|
|
49
|
+
sessionDomain: config.sessionDomain,
|
|
50
|
+
env: config.env,
|
|
51
|
+
window: browserWindow,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
this.#identity = new Identity({
|
|
55
|
+
...sharedConfig,
|
|
56
|
+
log,
|
|
57
|
+
callbackBeforeRedirect,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (defaultProductIds !== undefined && !Array.isArray(defaultProductIds)) {
|
|
61
|
+
throw new SDKError('Account defaultProductIds config must be an array');
|
|
62
|
+
}
|
|
63
|
+
this.#defaultProductIds = defaultProductIds;
|
|
64
|
+
|
|
65
|
+
if (varnish) {
|
|
66
|
+
if (typeof varnish !== 'object' || Array.isArray(varnish)) {
|
|
67
|
+
throw new SDKError('Account varnish config must be an object');
|
|
68
|
+
}
|
|
69
|
+
this.#identity.enableVarnishCookie(varnish);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
this.#monetization = new Monetization(sharedConfig);
|
|
73
|
+
|
|
74
|
+
const sessionState = sessionStates.get(this.#identity);
|
|
75
|
+
if (sessionState) {
|
|
76
|
+
sessionStates.set(this, sessionState);
|
|
77
|
+
}
|
|
78
|
+
browserWindow.schAccount = this;
|
|
79
|
+
browserWindow.dispatchEvent(
|
|
80
|
+
new CustomEvent('schAccount:ready', { detail: { instance: this } }),
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Queries Session Service and returns the current browser session state.
|
|
86
|
+
*
|
|
87
|
+
* This call may trigger a full-page session refresh redirect. Configure
|
|
88
|
+
* `callbackBeforeRedirect` if your app needs to persist state before that navigation.
|
|
89
|
+
*
|
|
90
|
+
* @throws {SDKError} If the Session Service call fails.
|
|
91
|
+
*/
|
|
92
|
+
hasSession(): Promise<SessionResponse> {
|
|
93
|
+
return this.#identity.hasSession();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Checks whether the browser currently has a Schibsted Account session.
|
|
98
|
+
*
|
|
99
|
+
* Returns `false` instead of throwing when the session lookup fails.
|
|
100
|
+
*/
|
|
101
|
+
isLoggedIn(): Promise<boolean> {
|
|
102
|
+
return this.#identity.isLoggedIn();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Checks whether the current user is connected to the configured client.
|
|
107
|
+
*
|
|
108
|
+
* A user can be logged in to Schibsted Account without being connected to your client, for
|
|
109
|
+
* example before accepting required terms.
|
|
110
|
+
*/
|
|
111
|
+
isConnected(): Promise<boolean> {
|
|
112
|
+
return this.#identity.isConnected();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Returns the connected user session data.
|
|
117
|
+
*
|
|
118
|
+
* @throws {SDKError} If the user is not connected to the configured client.
|
|
119
|
+
*/
|
|
120
|
+
getUser(): Promise<ConnectedSessionResponse> {
|
|
121
|
+
return this.#identity.getUser();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Returns the realm-specific Schibsted Account user id as a number.
|
|
126
|
+
*
|
|
127
|
+
* Use `getUserUuid()` when you need the globally unique user id.
|
|
128
|
+
*
|
|
129
|
+
* @throws {SDKError} If the user is not connected to the configured client.
|
|
130
|
+
*/
|
|
131
|
+
getUserId(): Promise<number> {
|
|
132
|
+
return this.#identity.getUserId();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Returns an external identifier for the authenticated user, scoped to the configured client
|
|
137
|
+
* and external party.
|
|
138
|
+
*
|
|
139
|
+
* @param externalParty - External party for which the identifier is generated.
|
|
140
|
+
* @param optionalSuffix - Optional suffix included when generating the identifier.
|
|
141
|
+
* @throws {SDKError} If the session lookup fails, the session does not contain a `pairId`, or
|
|
142
|
+
* `externalParty` is empty.
|
|
143
|
+
* @deprecated Retained for compatibility with existing integrations. Avoid new usage.
|
|
144
|
+
*/
|
|
145
|
+
getExternalId(externalParty: string, optionalSuffix: string = ''): Promise<string> {
|
|
146
|
+
return this.#identity.getExternalId(externalParty, optionalSuffix);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Returns the globally unique user id from the current session.
|
|
151
|
+
*
|
|
152
|
+
* @throws {SDKError} If the user is not connected to the configured client.
|
|
153
|
+
*/
|
|
154
|
+
getUserUuid(): Promise<string> {
|
|
155
|
+
return this.#identity.getUserUuid();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Returns the user SDRN from the current session.
|
|
160
|
+
*
|
|
161
|
+
* @throws {SDKError} If the SDRN is missing from the session response.
|
|
162
|
+
*/
|
|
163
|
+
getUserSDRN(): Promise<string> {
|
|
164
|
+
return this.#identity.getUserSDRN();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Returns minimal user context for simplified login prompts.
|
|
169
|
+
*
|
|
170
|
+
* Returns `null` if the global account session cannot be read.
|
|
171
|
+
*/
|
|
172
|
+
getUserContextData(): Promise<SimplifiedLoginData | null> {
|
|
173
|
+
return this.#identity.getUserContextData();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Returns the Varnish `sp_id` value from the current session when present.
|
|
178
|
+
*/
|
|
179
|
+
getSpId(): Promise<string | null> {
|
|
180
|
+
return this.#identity.getSpId();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Starts the login flow with either a full-page redirect or a popup.
|
|
185
|
+
*
|
|
186
|
+
* Call this from a user gesture when `preferPopup` is enabled, otherwise browser popup blockers
|
|
187
|
+
* may block the popup and the SDK will fall back to redirect navigation.
|
|
188
|
+
*
|
|
189
|
+
* @param options - Login URL parameters.
|
|
190
|
+
* @returns A popup window reference when a popup is opened; otherwise `null`.
|
|
191
|
+
*/
|
|
192
|
+
login(options: LoginOptions): Window | null {
|
|
193
|
+
return this.#identity.login(options);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Logs the user out from the brand Session Service session and redirects the browser.
|
|
198
|
+
*
|
|
199
|
+
* @param redirectUri - Where Session Service should redirect the browser after logout.
|
|
200
|
+
*/
|
|
201
|
+
logout(redirectUri?: string): void {
|
|
202
|
+
this.#identity.logout(redirectUri);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Builds the login URL without navigating the browser.
|
|
207
|
+
*
|
|
208
|
+
* @param options - Login URL parameters.
|
|
209
|
+
*/
|
|
210
|
+
loginUrl(options: LoginOptions): string {
|
|
211
|
+
return this.#identity.loginUrl(options);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Builds the logout URL without navigating the browser.
|
|
216
|
+
*
|
|
217
|
+
* @param redirectUri - Where Session Service should redirect the browser after logout.
|
|
218
|
+
*/
|
|
219
|
+
logoutUrl(redirectUri?: string): string {
|
|
220
|
+
return this.#identity.logoutUrl(redirectUri);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Builds the Schibsted Account profile page URL.
|
|
225
|
+
*
|
|
226
|
+
* @param redirectUri - Where the account page should redirect the browser afterwards.
|
|
227
|
+
*/
|
|
228
|
+
accountUrl(redirectUri?: string): string {
|
|
229
|
+
return this.#identity.accountUrl(redirectUri);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Loads and displays the simplified login widget when user context is available.
|
|
234
|
+
*
|
|
235
|
+
* Your application decides how often to call this method. The `state` field in `loginParams`
|
|
236
|
+
* may be a string or a function that resolves to a string.
|
|
237
|
+
* Widget open and cancel events can be observed with `on()`.
|
|
238
|
+
*
|
|
239
|
+
* @returns `true` when the widget was displayed.
|
|
240
|
+
* @throws {SDKError} If user context data is missing or the widget script cannot be loaded.
|
|
241
|
+
*/
|
|
242
|
+
showSimplifiedLoginWidget(
|
|
243
|
+
loginParams: SimplifiedLoginWidgetLoginOptions,
|
|
244
|
+
options?: SimplifiedLoginWidgetOptions,
|
|
245
|
+
): Promise<boolean> {
|
|
246
|
+
return this.#identity.showSimplifiedLoginWidget(loginParams, options);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Enables or disables caching for subsequent session lookups.
|
|
251
|
+
*
|
|
252
|
+
* Changing this setting does not remove an existing cached session.
|
|
253
|
+
*/
|
|
254
|
+
setSessionCachingEnabled(enabled: boolean): void {
|
|
255
|
+
this.#identity.setSessionCachingEnabled(enabled);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Removes the cached Session Service user session response.
|
|
260
|
+
*/
|
|
261
|
+
clearCachedUserSession(): void {
|
|
262
|
+
this.#identity.clearCachedUserSession();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Checks whether the current user has access to any of the requested products or features.
|
|
267
|
+
*
|
|
268
|
+
* When `productIds` is omitted, the ids configured as `defaultProductIds` are used.
|
|
269
|
+
* Results are cached according to the TTL returned by Session Service.
|
|
270
|
+
*
|
|
271
|
+
* @param productIds - Product or feature ids to check instead of the configured defaults.
|
|
272
|
+
* @returns Access data, or `null` when the user is not entitled.
|
|
273
|
+
* @throws {SDKError} If product ids are not provided or configured, `sessionDomain` is missing,
|
|
274
|
+
* the current user cannot be resolved, input is invalid, or the request fails.
|
|
275
|
+
*/
|
|
276
|
+
async hasAccess(productIds = this.#defaultProductIds): Promise<HasAccessResult | null> {
|
|
277
|
+
if (!productIds) {
|
|
278
|
+
throw new SDKError(
|
|
279
|
+
'hasAccess requires productIds or defaultProductIds in the Account config',
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
if (productIds.length === 0) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const userId = await this.#identity.getUserId();
|
|
287
|
+
return this.#monetization.hasAccess(productIds, userId);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Removes a cached access-check result.
|
|
292
|
+
*
|
|
293
|
+
* @param productIds - Product or feature ids used for the cached lookup.
|
|
294
|
+
* @param userId - User id used for the cached lookup.
|
|
295
|
+
*/
|
|
296
|
+
clearCachedAccessResult(productIds: string[], userId: SessionUserId): void {
|
|
297
|
+
this.#monetization.clearCachedAccessResult(productIds, userId);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Subscribes to Account events.
|
|
302
|
+
*
|
|
303
|
+
* Supported event names are defined by {@link AccountEventName}.
|
|
304
|
+
*
|
|
305
|
+
* @param event - Event name.
|
|
306
|
+
* @param listener - Listener that receives an `Event` or `CustomEvent`.
|
|
307
|
+
*/
|
|
308
|
+
on<EventName extends AccountEventName>(
|
|
309
|
+
event: EventName,
|
|
310
|
+
listener: AccountEventListener<EventName>,
|
|
311
|
+
): this;
|
|
312
|
+
on(event: AccountEventName, listener: EventListener): this {
|
|
313
|
+
this.#identity.addEventListener(event, listener);
|
|
314
|
+
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Unsubscribes from Account events.
|
|
320
|
+
*
|
|
321
|
+
* Supported event names are defined by {@link AccountEventName}.
|
|
322
|
+
*
|
|
323
|
+
* @param event - Event name.
|
|
324
|
+
* @param listener - Listener to remove.
|
|
325
|
+
*/
|
|
326
|
+
off<EventName extends AccountEventName>(
|
|
327
|
+
event: EventName,
|
|
328
|
+
listener: AccountEventListener<EventName>,
|
|
329
|
+
): this;
|
|
330
|
+
off(event: AccountEventName, listener: EventListener): this {
|
|
331
|
+
this.#identity.removeEventListener(event, listener);
|
|
332
|
+
|
|
333
|
+
return this;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export default Account;
|
|
@@ -2,45 +2,47 @@
|
|
|
2
2
|
* See LICENSE.md in the project root.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import SDKError from './SDKError.js';
|
|
5
|
+
import SDKError from './sdk-error.js';
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* Check whether we are able to use web storage
|
|
11
|
-
* @param
|
|
9
|
+
* @param storeProvider - A function to return a WebStorage instance (either
|
|
12
10
|
* `sessionStorage` or `localStorage` from a `Window` object)
|
|
13
11
|
* @private
|
|
14
|
-
* @returns {boolean}
|
|
15
12
|
*/
|
|
16
|
-
function webStorageWorks(storeProvider) {
|
|
13
|
+
function webStorageWorks(storeProvider: (() => Storage) | undefined): boolean {
|
|
17
14
|
if (!storeProvider) {
|
|
18
15
|
return false;
|
|
19
16
|
}
|
|
20
17
|
try {
|
|
21
18
|
const store = storeProvider();
|
|
22
|
-
const randomKey = 'x-x-x-x'.replace(/x/g, () => Math.random());
|
|
19
|
+
const randomKey = 'x-x-x-x'.replace(/x/g, () => String(Math.random()));
|
|
23
20
|
const testValue = 'TEST-VALUE';
|
|
24
21
|
store.setItem(randomKey, testValue);
|
|
25
22
|
const val = store.getItem(randomKey);
|
|
26
23
|
store.removeItem(randomKey);
|
|
27
|
-
return
|
|
28
|
-
} catch
|
|
24
|
+
return val === testValue;
|
|
25
|
+
} catch {
|
|
29
26
|
return false;
|
|
30
27
|
}
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
/**
|
|
34
|
-
*
|
|
31
|
+
* Cache implementation used when web storage is available. Wraps a `Storage` instance.
|
|
35
32
|
* @private
|
|
36
33
|
*/
|
|
37
34
|
class WebStorageCache {
|
|
35
|
+
store: Storage;
|
|
36
|
+
get: (key: string) => string | null;
|
|
37
|
+
set: (key: string, value: string) => void;
|
|
38
|
+
delete: (key: string) => void;
|
|
39
|
+
|
|
38
40
|
/**
|
|
39
41
|
* Create web storage cache object
|
|
40
|
-
* @param
|
|
42
|
+
* @param store - A reference to either `sessionStorage` or `localStorage` from a
|
|
41
43
|
* `Window` object
|
|
42
44
|
*/
|
|
43
|
-
constructor(store) {
|
|
45
|
+
constructor(store: Storage) {
|
|
44
46
|
this.store = store;
|
|
45
47
|
this.get = (key) => this.store.getItem(key);
|
|
46
48
|
this.set = (key, value) => this.store.setItem(key, value);
|
|
@@ -49,35 +51,49 @@ class WebStorageCache {
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
/**
|
|
52
|
-
*
|
|
54
|
+
* Cache implementation used when web storage is not available. Stores entries in an in-memory object.
|
|
53
55
|
* @private
|
|
54
56
|
*/
|
|
55
57
|
class LiteralCache {
|
|
58
|
+
store: Record<string, string>;
|
|
59
|
+
get: (key: string) => string | undefined;
|
|
60
|
+
set: (key: string, value: string) => void;
|
|
61
|
+
delete: (key: string) => void;
|
|
62
|
+
|
|
56
63
|
/**
|
|
57
64
|
* Create JS object literal cache object
|
|
58
65
|
*/
|
|
59
66
|
constructor() {
|
|
60
67
|
this.store = {};
|
|
61
68
|
this.get = (key) => this.store[key];
|
|
62
|
-
this.set = (key, value) =>
|
|
63
|
-
|
|
69
|
+
this.set = (key, value) => {
|
|
70
|
+
this.store[key] = value;
|
|
71
|
+
};
|
|
72
|
+
this.delete = (key) => {
|
|
73
|
+
delete this.store[key];
|
|
74
|
+
};
|
|
64
75
|
}
|
|
65
76
|
}
|
|
66
77
|
|
|
67
|
-
|
|
78
|
+
type CacheEntry = { expiresOn: number; value: unknown };
|
|
79
|
+
|
|
80
|
+
const maxExpiresIn = 2 ** 31 - 1;
|
|
68
81
|
|
|
69
82
|
/**
|
|
70
83
|
* Cache class that attempts WebStorage (session/local storage), and falls back to JS object literal
|
|
71
84
|
* @private
|
|
72
85
|
*/
|
|
73
86
|
export default class Cache {
|
|
87
|
+
cache: WebStorageCache | LiteralCache;
|
|
88
|
+
type: string;
|
|
89
|
+
|
|
74
90
|
/**
|
|
75
|
-
* @param
|
|
91
|
+
* @param storeProvider - A function to return a WebStorage instance (either
|
|
76
92
|
* `sessionStorage` or `localStorage` from a `Window` object)
|
|
77
93
|
* @throws {SDKError} - If sessionStorage or localStorage are not accessible
|
|
78
94
|
*/
|
|
79
|
-
constructor(storeProvider) {
|
|
80
|
-
if (webStorageWorks(storeProvider)) {
|
|
95
|
+
constructor(storeProvider?: () => Storage) {
|
|
96
|
+
if (storeProvider && webStorageWorks(storeProvider)) {
|
|
81
97
|
this.cache = new WebStorageCache(storeProvider());
|
|
82
98
|
this.type = 'WebStorage';
|
|
83
99
|
} else {
|
|
@@ -88,46 +104,46 @@ export default class Cache {
|
|
|
88
104
|
|
|
89
105
|
/**
|
|
90
106
|
* Get a value from cache (checks that the object has not expired)
|
|
91
|
-
* @param
|
|
107
|
+
* @param key
|
|
92
108
|
* @private
|
|
93
|
-
* @returns {*} - The value if it exists, otherwise null
|
|
94
109
|
*/
|
|
95
|
-
get(key) {
|
|
110
|
+
get(key: string): unknown {
|
|
96
111
|
/**
|
|
97
112
|
* JSON.parse safe wrapper
|
|
98
|
-
* @param
|
|
99
|
-
* @returns {*} parsed value or null if failed to parse
|
|
113
|
+
* @param raw
|
|
100
114
|
*/
|
|
101
|
-
function getObj(raw) {
|
|
115
|
+
function getObj(raw: string | null | undefined): CacheEntry | null {
|
|
116
|
+
if (raw == null) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
102
119
|
try {
|
|
103
120
|
return JSON.parse(raw);
|
|
104
|
-
} catch
|
|
121
|
+
} catch {
|
|
105
122
|
return null;
|
|
106
123
|
}
|
|
107
124
|
}
|
|
108
125
|
|
|
109
126
|
try {
|
|
110
127
|
const raw = this.cache.get(key);
|
|
111
|
-
|
|
128
|
+
const obj = getObj(raw);
|
|
112
129
|
if (obj && Number.isInteger(obj.expiresOn) && obj.expiresOn > Date.now()) {
|
|
113
130
|
return obj.value;
|
|
114
131
|
}
|
|
115
132
|
this.delete(key);
|
|
116
133
|
return null;
|
|
117
134
|
} catch (e) {
|
|
118
|
-
throw new SDKError(e);
|
|
135
|
+
throw new SDKError(String(e));
|
|
119
136
|
}
|
|
120
137
|
}
|
|
121
138
|
|
|
122
139
|
/**
|
|
123
140
|
* Set a cache entry
|
|
124
|
-
* @param
|
|
125
|
-
* @param
|
|
126
|
-
* @param
|
|
141
|
+
* @param key
|
|
142
|
+
* @param value
|
|
143
|
+
* @param expiresIn - Value in milliseconds until the entry expires
|
|
127
144
|
* @private
|
|
128
|
-
* @returns {void}
|
|
129
145
|
*/
|
|
130
|
-
set(key, value, expiresIn = 0) {
|
|
146
|
+
set(key: string, value: unknown, expiresIn = 0): void {
|
|
131
147
|
if (expiresIn <= 0) {
|
|
132
148
|
return;
|
|
133
149
|
}
|
|
@@ -138,21 +154,20 @@ export default class Cache {
|
|
|
138
154
|
this.cache.set(key, JSON.stringify({ expiresOn, value }));
|
|
139
155
|
setTimeout(() => this.delete(key), expiresIn);
|
|
140
156
|
} catch (e) {
|
|
141
|
-
throw new SDKError(e);
|
|
157
|
+
throw new SDKError(String(e));
|
|
142
158
|
}
|
|
143
159
|
}
|
|
144
160
|
|
|
145
161
|
/**
|
|
146
162
|
* Delete a cache entry
|
|
147
|
-
* @param
|
|
163
|
+
* @param key
|
|
148
164
|
* @private
|
|
149
|
-
* @returns {void}
|
|
150
165
|
*/
|
|
151
|
-
delete(key) {
|
|
166
|
+
delete(key: string): void {
|
|
152
167
|
try {
|
|
153
168
|
this.cache.delete(key);
|
|
154
169
|
} catch (e) {
|
|
155
|
-
throw new SDKError(e);
|
|
170
|
+
throw new SDKError(String(e));
|
|
156
171
|
}
|
|
157
172
|
}
|
|
158
173
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/* Copyright 2026 Schibsted Products & Technology AS. Licensed under the terms of the MIT license.
|
|
2
|
+
* See LICENSE.md in the project root.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { enableLegacyCompatibility } from './install-legacy-compatibility.js';
|
|
6
|
+
export type {
|
|
7
|
+
LegacyCompatibilityOptions,
|
|
8
|
+
LegacyIdentity,
|
|
9
|
+
LegacyMonetization,
|
|
10
|
+
} from './types.js';
|