@schibsted/account-sdk-browser 6.0.0-alpha.2 → 6.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +39 -39
  2. package/dist/account-sdk.d.ts +4 -0
  3. package/dist/account.d.ts +30 -0
  4. package/dist/global-registry.d.ts +1 -1
  5. package/dist/globals.d.ts +2 -0
  6. package/dist/has-access-response.d.ts +2 -0
  7. package/dist/identity.d.ts +37 -237
  8. package/dist/index.d.ts +8 -3
  9. package/dist/index.js +862 -4
  10. package/dist/index.js.map +1 -0
  11. package/dist/monetization.d.ts +7 -43
  12. package/dist/resolve-browser-window.d.ts +1 -0
  13. package/dist/{RESTClient.d.ts → rest-client.d.ts} +22 -11
  14. package/dist/rest-clients.d.ts +10 -0
  15. package/dist/session-response.d.ts +30 -0
  16. package/dist/types/account.d.ts +13 -0
  17. package/dist/types/common.d.ts +22 -0
  18. package/dist/types/identity.d.ts +41 -0
  19. package/dist/types/login.d.ts +120 -0
  20. package/dist/types/monetization-guards.d.ts +2 -0
  21. package/dist/types/monetization.d.ts +21 -0
  22. package/dist/types/session-guards.d.ts +36 -0
  23. package/dist/types/session.d.ts +124 -0
  24. package/dist/version.d.ts +1 -1
  25. package/package.json +1 -9
  26. package/src/account-sdk.ts +74 -0
  27. package/src/account.ts +153 -0
  28. package/src/cache.ts +1 -1
  29. package/src/global-registry.ts +1 -1
  30. package/src/globals.ts +2 -0
  31. package/src/has-access-response.ts +35 -0
  32. package/src/identity.ts +269 -423
  33. package/src/index.ts +28 -3
  34. package/src/monetization.ts +31 -68
  35. package/src/object.ts +1 -1
  36. package/src/resolve-browser-window.ts +11 -0
  37. package/src/{RESTClient.ts → rest-client.ts} +55 -28
  38. package/src/rest-clients.ts +30 -0
  39. package/src/session-response.ts +79 -0
  40. package/src/types/account.ts +27 -0
  41. package/src/types/common.ts +26 -0
  42. package/src/types/identity.ts +55 -0
  43. package/src/types/login.ts +145 -0
  44. package/src/types/monetization-guards.ts +35 -0
  45. package/src/types/monetization.ts +24 -0
  46. package/src/types/session-guards.ts +89 -0
  47. package/src/types/session.ts +147 -0
  48. package/src/validate.ts +1 -1
  49. package/src/version.ts +1 -1
  50. package/dist/identity-s4nofYmB.js +0 -370
  51. package/dist/identity-s4nofYmB.js.map +0 -1
  52. package/dist/identity.js +0 -2
  53. package/dist/monetization.js +0 -72
  54. package/dist/monetization.js.map +0 -1
  55. package/dist/version-spE-k97g.js +0 -289
  56. package/dist/version-spE-k97g.js.map +0 -1
  57. /package/dist/{SDKError.d.ts → sdk-error.d.ts} +0 -0
  58. /package/dist/{spidTalk.d.ts → spid-talk.d.ts} +0 -0
  59. /package/src/{SDKError.ts → sdk-error.ts} +0 -0
  60. /package/src/{spidTalk.ts → spid-talk.ts} +0 -0
package/src/index.ts CHANGED
@@ -2,6 +2,31 @@
2
2
  * See LICENSE.md in the project root.
3
3
  */
4
4
 
5
- export * from './identity.js';
6
- export * from './monetization.js';
7
- export { default as SDKError } from './SDKError.js';
5
+ export { Account } from './account.js';
6
+ export { createAccountSdk, getAccountSdk } from './account-sdk.js';
7
+ export { default as SDKError } from './sdk-error.js';
8
+
9
+ /* public available types */
10
+ export type {
11
+ AccountConfig,
12
+ AccountEventHandler,
13
+ AccountEventName,
14
+ AccountSessionEventName,
15
+ } from './types/account.js';
16
+ export type { AccountEnvironment, LogFunction } from './types/common.js';
17
+ export type {
18
+ LoginOptions,
19
+ SimplifiedLoginData,
20
+ SimplifiedLoginWidgetLoginOptions,
21
+ SimplifiedLoginWidgetOptions,
22
+ } from './types/login.js';
23
+ export type { HasAccessResult } from './types/monetization.js';
24
+ export type {
25
+ ConnectedSessionResponse,
26
+ ConnectedSessionWithUserIdResponse,
27
+ RedirectSessionResponse,
28
+ SessionFailureResponse,
29
+ SessionResponse,
30
+ SessionSuccessResponse,
31
+ SessionUserId,
32
+ } from './types/session.js';
@@ -4,33 +4,21 @@
4
4
 
5
5
  import { TinyEmitter } from 'tiny-emitter';
6
6
  import Cache from './cache.js';
7
- import { ENDPOINTS, NAMESPACE } from './config.js';
7
+ import { ENDPOINTS } from './config.js';
8
8
  import { registerAndDispatchInGlobal } from './global-registry.js';
9
- import RESTClient from './RESTClient.js';
10
- import SDKError from './SDKError.js';
11
- import * as spidTalk from './spidTalk.js';
9
+ import { parseHasAccessResult } from './has-access-response.js';
10
+ import type { SessionUserId } from './identity.js';
11
+ import type RESTClient from './rest-client.js';
12
+ import { buildClientSdrn, createAccountRestClient } from './rest-clients.js';
13
+ import SDKError from './sdk-error.js';
14
+ import * as spidTalk from './spid-talk.js';
15
+ import type { HasAccessResult, MonetizationOptions } from './types/monetization.js';
12
16
  import { urlMapper } from './url.js';
13
17
  import { assert, isNonEmptyString, isStr, isUrl } from './validate.js';
14
18
  import version from './version.js';
15
19
 
16
20
  const globalWindow = () => window;
17
21
 
18
- /**
19
- * Result returned by the Session Service `/hasAccess` endpoint, describing whether the user
20
- * is entitled to a requested set of products/features.
21
- * @internal
22
- */
23
- export interface HasAccessResult {
24
- /** Whether the user is entitled to at least one of the requested products/features. */
25
- entitled: boolean;
26
- /** How long this result stays valid, in seconds, before the cache entry expires. */
27
- ttl: number;
28
- allowedFeatures: string[];
29
- userId: number;
30
- uuid: string;
31
- sig: string;
32
- }
33
-
34
22
  /**
35
23
  * Provides features related to monetization
36
24
  */
@@ -38,8 +26,8 @@ export class Monetization extends TinyEmitter {
38
26
  cache: Cache;
39
27
  clientId: string;
40
28
  env: string;
41
- redirectUri: string;
42
- _spid!: RESTClient;
29
+ redirectUri?: string;
30
+ _spid: RESTClient;
43
31
  _sessionService?: RESTClient;
44
32
  private pendingHasAccessRequests: Record<string, Promise<HasAccessResult>>;
45
33
 
@@ -53,63 +41,36 @@ export class Monetization extends TinyEmitter {
53
41
  env = 'PRE',
54
42
  sessionDomain,
55
43
  window = globalWindow(),
56
- }: {
57
- /** Mandatory client id */
58
- clientId: string;
59
- /** Redirect uri */
60
- redirectUri: string;
61
- /** Example: `"https://id.site.com"` */
62
- sessionDomain: string;
63
- /** Schibsted account environment: `PRE` (default), `PRO`, `PRO_NO` */
64
- env?: string;
65
- /** Window object to use (defaults to the global `window`). */
66
- window?: Window;
67
- }) {
44
+ }: MonetizationOptions) {
68
45
  super();
69
46
  spidTalk.emulate(window);
70
47
  assert(isNonEmptyString(clientId), 'clientId parameter is required');
48
+ assert(isStr(env), `env parameter is invalid: ${env}`);
71
49
 
72
50
  this.cache = new Cache(() => window && window.sessionStorage);
73
51
  this.clientId = clientId;
74
52
  this.env = env;
75
53
  this.redirectUri = redirectUri;
76
54
  this.pendingHasAccessRequests = {};
77
- this._setSpidServerUrl(env);
55
+ this._spid = createAccountRestClient({
56
+ serverUrl: urlMapper(env, ENDPOINTS.SPiD),
57
+ defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },
58
+ });
78
59
 
79
60
  if (sessionDomain) {
80
61
  assert(isUrl(sessionDomain), 'sessionDomain parameter is not a valid URL');
81
- this._setSessionServiceUrl(sessionDomain);
62
+ this._sessionService = createAccountRestClient({
63
+ serverUrl: sessionDomain,
64
+ defaultParams: {
65
+ client_sdrn: buildClientSdrn(this.env, this.clientId),
66
+ redirect_uri: this.redirectUri,
67
+ sdk_version: version,
68
+ },
69
+ });
82
70
  }
83
71
  registerAndDispatchInGlobal(window, 'schMonetization', this);
84
72
  }
85
73
 
86
- /**
87
- * Set SPiD server URL
88
- * @private
89
- * @param url
90
- */
91
- private _setSpidServerUrl(url: string): void {
92
- assert(isStr(url), `url parameter is invalid: ${url}`);
93
- this._spid = new RESTClient({
94
- serverUrl: urlMapper(url, ENDPOINTS.SPiD),
95
- defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },
96
- });
97
- }
98
-
99
- /**
100
- * Set session-service domain
101
- * @private
102
- * @param domain - real URL — (**not** 'PRE' style env key)
103
- */
104
- private _setSessionServiceUrl(domain: string): void {
105
- assert(isStr(domain), `domain parameter is invalid: ${domain}`);
106
- const client_sdrn = `sdrn:${NAMESPACE[this.env as keyof typeof NAMESPACE]}:client:${this.clientId}`;
107
- this._sessionService = new RESTClient({
108
- serverUrl: domain,
109
- defaultParams: { client_sdrn, redirect_uri: this.redirectUri, sdk_version: version },
110
- });
111
- }
112
-
113
74
  /**
114
75
  * Checks if the user has access to a set of products or features.
115
76
  * @param productIds - which products/features to check
@@ -119,7 +80,7 @@ export class Monetization extends TinyEmitter {
119
80
  * @returns The data object returned from Schibsted account (or `null` if the user
120
81
  * doesn't have access to any of the given products/features)
121
82
  */
122
- async hasAccess(productIds: string[], userId: number): Promise<HasAccessResult | null> {
83
+ async hasAccess(productIds: string[], userId: SessionUserId): Promise<HasAccessResult | null> {
123
84
  if (!this._sessionService) {
124
85
  throw new SDKError(`hasAccess can only be called if 'sessionDomain' is configured`);
125
86
  }
@@ -137,6 +98,8 @@ export class Monetization extends TinyEmitter {
137
98
  if (!this.pendingHasAccessRequests[cacheKey]) {
138
99
  this.pendingHasAccessRequests[cacheKey] = this._sessionService.get(
139
100
  `/hasAccess/${sortedIds.join(',')}`,
101
+ undefined,
102
+ parseHasAccessResult,
140
103
  );
141
104
  }
142
105
  const promise = this.pendingHasAccessRequests[cacheKey];
@@ -163,7 +126,7 @@ export class Monetization extends TinyEmitter {
163
126
  * @param productIds - which products/features to check
164
127
  * @param userId - id of currently logged in user
165
128
  */
166
- clearCachedAccessResult(productIds: string[], userId: number): void {
129
+ clearCachedAccessResult(productIds: string[], userId: SessionUserId): void {
167
130
  this.cache.delete(this._accessCacheKey(productIds, userId));
168
131
  }
169
132
 
@@ -173,7 +136,7 @@ export class Monetization extends TinyEmitter {
173
136
  * @param productIds - which products/features to check
174
137
  * @param userId - id of currently logged in user
175
138
  */
176
- private _accessCacheKey(productIds: string[], userId: number): string {
139
+ private _accessCacheKey(productIds: string[], userId: SessionUserId): string {
177
140
  return `prd_${[...productIds].sort()}_${userId}`;
178
141
  }
179
142
 
@@ -182,7 +145,7 @@ export class Monetization extends TinyEmitter {
182
145
  * @param redirectUri
183
146
  * @returns - The url to the subscriptions review page
184
147
  */
185
- subscriptionsUrl(redirectUri: string = this.redirectUri): string {
148
+ subscriptionsUrl(redirectUri: string = this.redirectUri ?? ''): string {
186
149
  assert(isUrl(redirectUri), `subscriptionsUrl(): redirectUri is invalid`);
187
150
  return this._spid.makeUrl('account/subscriptions', { redirect_uri: redirectUri });
188
151
  }
@@ -192,7 +155,7 @@ export class Monetization extends TinyEmitter {
192
155
  * @param redirectUri
193
156
  * @returns - The url to the products review page
194
157
  */
195
- productsUrl(redirectUri: string = this.redirectUri): string {
158
+ productsUrl(redirectUri: string = this.redirectUri ?? ''): string {
196
159
  assert(isUrl(redirectUri), `productsUrl(): redirectUri is invalid`);
197
160
  return this._spid.makeUrl('account/products', { redirect_uri: redirectUri });
198
161
  }
package/src/object.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * @private
8
8
  */
9
9
 
10
- import SDKError from './SDKError.js';
10
+ import SDKError from './sdk-error.js';
11
11
  import { assert, isNonEmptyObj, isObject } from './validate.js';
12
12
 
13
13
  /**
@@ -0,0 +1,11 @@
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 const resolveBrowserWindow = (providedWindow?: Window): Window | undefined => {
6
+ if (providedWindow) {
7
+ return providedWindow;
8
+ }
9
+
10
+ return typeof window === 'undefined' ? undefined : window;
11
+ };
@@ -3,7 +3,8 @@
3
3
  */
4
4
 
5
5
  import { cloneDefined } from './object.js';
6
- import SDKError from './SDKError.js';
6
+ import SDKError from './sdk-error.js';
7
+ import type { LogFunction } from './types/common.js';
7
8
  import { urlMapper } from './url.js';
8
9
  import { assert, isFunction, isNonEmptyString, isObject, isStr } from './validate.js';
9
10
 
@@ -15,13 +16,7 @@ import { assert, isFunction, isNonEmptyString, isObject, isStr } from './validat
15
16
  const logString = (msg: unknown[]): string =>
16
17
  msg.map((m) => (isObject(m) ? JSON.stringify(m, null, 2) : m)).join(' ');
17
18
 
18
- /**
19
- * Calls a log function passing a string
20
- * @private
21
- * @param fn - The log function
22
- * @param msg - The values to log
23
- */
24
- const logFn = (fn: Function | undefined, ...msg: unknown[]): void => {
19
+ const logFn = (fn: LogFunction | undefined, ...msg: unknown[]): void => {
25
20
  if (fn) {
26
21
  fn(logString(msg));
27
22
  }
@@ -65,6 +60,20 @@ type QueryParams = Record<string, QueryValue>;
65
60
  */
66
61
  type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
67
62
 
63
+ type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };
64
+
65
+ type ResponseParser<T> = (value: JsonValue) => T;
66
+
67
+ type RESTRequestOptions<T = JsonValue> = {
68
+ method: HttpMethod;
69
+ pathname: string;
70
+ data?: QueryParams;
71
+ headers?: Record<string, string>;
72
+ useDefaultParams?: boolean;
73
+ fetchOptions?: RequestInit;
74
+ parseResponse?: ResponseParser<T>;
75
+ };
76
+
68
77
  /**
69
78
  * This class can be used for creating a wrapper around a server and all its endpoints.
70
79
  * Its functionality is extended by {@link JSONPClient}
@@ -78,7 +87,7 @@ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
78
87
  export class RESTClient {
79
88
  url: URL;
80
89
  defaultParams: QueryParams;
81
- log?: Function;
90
+ log?: LogFunction;
82
91
  fetch: FetchFunction;
83
92
 
84
93
  /**
@@ -103,7 +112,7 @@ export class RESTClient {
103
112
  serverUrl?: string;
104
113
  envDic?: Record<string, string>;
105
114
  fetch?: FetchFunction;
106
- log?: Function;
115
+ log?: LogFunction;
107
116
  defaultParams?: QueryParams;
108
117
  }) {
109
118
  assert(isObject(defaultParams), `defaultParams should be a non-null object`);
@@ -135,21 +144,23 @@ export class RESTClient {
135
144
  * @param options.fetchOptions - Additional fetch options
136
145
  * @throws {SDKError} - If the call can't be made for whatever reason.
137
146
  */
138
- async go({
139
- method,
140
- headers,
141
- pathname,
142
- data = {},
143
- useDefaultParams = true,
144
- fetchOptions = { method, credentials: 'include' },
145
- }: {
146
- method: HttpMethod;
147
- pathname: string;
148
- data?: QueryParams;
149
- headers?: Record<string, string>;
150
- useDefaultParams?: boolean;
151
- fetchOptions?: RequestInit;
152
- }): Promise<any> {
147
+ // Overloads describe the two supported modes:
148
+ // - without a parser: return the parsed JSON response as-is;
149
+ // - with a parser: return the parser's typed result.
150
+ async go(options: RESTRequestOptions): Promise<JsonValue>;
151
+ async go<T>(options: RESTRequestOptions<T> & { parseResponse: ResponseParser<T> }): Promise<T>;
152
+
153
+ // TypeScript requires one implementation signature for the overloads above.
154
+ async go<T = JsonValue>(options: RESTRequestOptions<T>): Promise<JsonValue | T> {
155
+ const {
156
+ method,
157
+ headers,
158
+ pathname,
159
+ data = {},
160
+ useDefaultParams = true,
161
+ fetchOptions = { method: options.method, credentials: 'include' },
162
+ parseResponse,
163
+ } = options;
153
164
  assert(isNonEmptyString(method), `Method must be a non empty string but it is "${method}"`);
154
165
  assert(isNonEmptyString(pathname), `Pathname must be string but it is "${pathname}"`);
155
166
  assert(isObject(data), `data must be a non-null object`);
@@ -167,9 +178,9 @@ export class RESTClient {
167
178
  // status code not in range 200-299
168
179
  throw new SDKError(response.statusText, { code: response.status });
169
180
  }
170
- const responseObject = await response.json();
181
+ const responseObject: JsonValue = await response.json();
171
182
  logFn(this.log, 'Response Parsed:', responseObject);
172
- return responseObject;
183
+ return parseResponse ? parseResponse(responseObject) : responseObject;
173
184
  } catch (err: unknown) {
174
185
  let msg = isStr(err) ? err : 'Unknown RESTClient error';
175
186
  if (isObject(err) && isStr(err.message)) {
@@ -199,7 +210,23 @@ export class RESTClient {
199
210
  * @param pathname - WHATWG pathname ie. 'api/2/endpoint-name'
200
211
  * @param data - Query parameters
201
212
  */
202
- get(pathname: string, data?: QueryParams): Promise<any> {
213
+ // Mirrors `go()` overloads for the common GET helper.
214
+ get(pathname: string, data?: QueryParams): Promise<JsonValue>;
215
+ get<T>(
216
+ pathname: string,
217
+ data: QueryParams | undefined,
218
+ parseResponse: ResponseParser<T>,
219
+ ): Promise<T>;
220
+
221
+ // TypeScript requires one implementation signature for the overloads above.
222
+ get<T>(
223
+ pathname: string,
224
+ data?: QueryParams,
225
+ parseResponse?: ResponseParser<T>,
226
+ ): Promise<JsonValue | T> {
227
+ if (parseResponse) {
228
+ return this.go({ method: 'GET', pathname, data, parseResponse });
229
+ }
203
230
  return this.go({ method: 'GET', pathname, data });
204
231
  }
205
232
 
@@ -0,0 +1,30 @@
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 { NAMESPACE } from './config.js';
6
+ import RESTClient from './rest-client.js';
7
+ import type { LogFunction } from './types/common.js';
8
+ import { assert, isNonEmptyString } from './validate.js';
9
+
10
+ type AccountRestClientOptions = {
11
+ serverUrl: string;
12
+ log?: LogFunction;
13
+ defaultParams: Record<string, string | number | boolean | undefined>;
14
+ };
15
+
16
+ const isKnownNamespace = (env: string): env is keyof typeof NAMESPACE =>
17
+ Object.hasOwn(NAMESPACE, env);
18
+
19
+ export const buildClientSdrn = (env: string, clientId: string): string => {
20
+ assert(isNonEmptyString(clientId), 'clientId parameter is required');
21
+ assert(isKnownNamespace(env), `env parameter is invalid: ${env}`);
22
+
23
+ return `sdrn:${NAMESPACE[env]}:client:${clientId}`;
24
+ };
25
+
26
+ export const createAccountRestClient = ({
27
+ serverUrl,
28
+ log,
29
+ defaultParams,
30
+ }: AccountRestClientOptions): RESTClient => new RESTClient({ serverUrl, log, defaultParams });
@@ -0,0 +1,79 @@
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 type {
6
+ ConnectedSessionResponse,
7
+ ConnectedSessionWithUserIdResponse,
8
+ NormalizedSessionPayload,
9
+ RedirectSessionPayload,
10
+ SessionFailureResponse,
11
+ SessionResponse,
12
+ SessionSuccessResponse,
13
+ } from './types/session.js';
14
+ import { isObject, isStr } from './validate.js';
15
+
16
+ export function isSessionSuccessResponse(value: unknown): value is SessionSuccessResponse {
17
+ return isObject(value) && typeof value.result === 'boolean';
18
+ }
19
+
20
+ export function isConnectedSessionResponse(value: unknown): value is ConnectedSessionResponse {
21
+ return isSessionSuccessResponse(value) && value.result === true;
22
+ }
23
+
24
+ export function isSessionFailureResponse(value: unknown): value is SessionFailureResponse {
25
+ return isObject(value) && Boolean(value.error);
26
+ }
27
+
28
+ export function isRedirectSessionPayload(value: unknown): value is RedirectSessionPayload {
29
+ return isObject(value) && Object.keys(value).length === 1 && isStr(value.redirectURL);
30
+ }
31
+
32
+ export function isConnectedSessionWithUserIdResponse(
33
+ value: SessionResponse,
34
+ ): value is ConnectedSessionWithUserIdResponse {
35
+ return (
36
+ isConnectedSessionResponse(value) &&
37
+ (typeof value.userId === 'number' || typeof value.userId === 'string')
38
+ );
39
+ }
40
+
41
+ /**
42
+ * Converts an unknown Session Service `hasSession` payload into one of the shapes the SDK knows how
43
+ * to handle.
44
+ *
45
+ * This function is intentionally tolerant because `hasSession()` historically resolved unknown
46
+ * object payloads instead of rejecting them. The SDK relies on that behavior for backwards
47
+ * compatibility with clients that check the raw response themselves.
48
+ *
49
+ * The normal cases are:
50
+ * - regular success payloads with a boolean `result`;
51
+ * - failure payloads wrapped as `{ error, response? }`;
52
+ * - Safari/session-refresh redirect payloads shaped as `{ redirectURL }`.
53
+ *
54
+ * Any other object is preserved as an unrecognized response so callers can still receive it.
55
+ * Non-object values are normalized to `{}`, matching the old "empty response" fallback used by
56
+ * `hasSession()` and cached-session reads.
57
+ *
58
+ * This is used both for network responses parsed by `RESTClient` and for values restored from the
59
+ * session cache, so the rest of the Identity flow can switch on typed guards instead of repeatedly
60
+ * re-validating unknown data.
61
+ *
62
+ * @internal
63
+ */
64
+ export function normalizeSessionResponse(value: unknown): NormalizedSessionPayload {
65
+ if (isRedirectSessionPayload(value)) {
66
+ return value;
67
+ }
68
+ if (isSessionFailureResponse(value)) {
69
+ return value;
70
+ }
71
+ if (isSessionSuccessResponse(value)) {
72
+ return value;
73
+ }
74
+ if (isObject(value)) {
75
+ return value;
76
+ }
77
+
78
+ return {};
79
+ }
@@ -0,0 +1,27 @@
1
+ import type { AccountBaseConfig, LogFunction } from './common';
2
+ import type { IdentityBeforeRedirectCallback, VarnishCookieOptions } from './identity';
3
+
4
+ export type AccountConfig = AccountBaseConfig & {
5
+ /** Receives debug log information. If not set, no logging will be done. */
6
+ log?: LogFunction;
7
+ /** Callback triggered before a session refresh redirect happens. */
8
+ callbackBeforeRedirect?: IdentityBeforeRedirectCallback;
9
+ /** Optional Varnish cookie setup applied during Account initialization. */
10
+ varnish?: VarnishCookieOptions;
11
+ };
12
+
13
+ export type AccountSessionEventName =
14
+ | 'login'
15
+ | 'logout'
16
+ | 'userChange'
17
+ | 'sessionChange'
18
+ | 'notLoggedin'
19
+ | 'sessionInit'
20
+ | 'statusChange'
21
+ | 'error'
22
+ | 'simplifiedLoginOpened'
23
+ | 'simplifiedLoginCancelled';
24
+
25
+ export type AccountEventName = AccountSessionEventName | 'hasAccess';
26
+
27
+ export type AccountEventHandler = (...args: unknown[]) => void;
@@ -0,0 +1,26 @@
1
+ /* Common types used across the SDK */
2
+
3
+ /**
4
+ * Log callback used by the SDK for debug output.
5
+ * Receives a pre-formatted log line.
6
+ * @internal
7
+ */
8
+ export type LogFunction = (message: string) => void;
9
+
10
+ /**
11
+ * Supported Schibsted account environment keys.
12
+ */
13
+ export type AccountEnvironment = 'LOCAL' | 'DEV' | 'PRE' | 'PRO' | 'PRO_NO' | 'PRO_FI' | 'PRO_DK';
14
+
15
+ export type AccountBaseConfig = {
16
+ /** Mandatory client id. Example: "1234567890abcdef12345678" */
17
+ clientId: string;
18
+ /** Redirect uri. Example: "https://site.com" */
19
+ redirectUri: string;
20
+ /** Session Service domain. Example: "https://id.site.com" */
21
+ sessionDomain: string;
22
+ /** Schibsted account environment. Defaults to PRE. */
23
+ env?: AccountEnvironment;
24
+ /** Window object to use. Defaults to the global `window`. */
25
+ window?: Window;
26
+ };
@@ -0,0 +1,55 @@
1
+ import type { AccountBaseConfig, LogFunction } from './common';
2
+
3
+ /**
4
+ * Callback invoked before the SDK performs a full-page session refresh redirect.
5
+ */
6
+ export type IdentityBeforeRedirectCallback = () => void | Promise<void>;
7
+
8
+ /**
9
+ * Options accepted by the {@link Identity} constructor.
10
+ */
11
+ export type IdentityOptions = AccountBaseConfig & {
12
+ /** Receives debug log information. If not set, no logging will be done. */
13
+ log?: LogFunction;
14
+ /** Callback triggered before a session refresh redirect happens. */
15
+ callbackBeforeRedirect?: IdentityBeforeRedirectCallback;
16
+ };
17
+
18
+ /**
19
+ * Identity events emitted by the SDK.
20
+ *
21
+ * - `login`: emitted when `hasSession()` resolves with a logged-in user payload.
22
+ * - `logout`: emitted when a previously logged-in user is no longer logged in, or when
23
+ * `logout()` is called.
24
+ * - `userChange`: emitted when the current session user id changes.
25
+ * - `sessionChange`: emitted when either the previous or current `hasSession()` payload contains
26
+ * a logged-in user.
27
+ * - `notLoggedin`: emitted when neither the previous nor current `hasSession()` payload contains
28
+ * a logged-in user.
29
+ * - `sessionInit`: emitted once for the first logged-in session payload.
30
+ * - `statusChange`: emitted when the session `userStatus` changes.
31
+ * - `error`: emitted when `hasSession()` fails.
32
+ * - `simplifiedLoginOpened`: emitted when the simplified login widget is displayed.
33
+ * - `simplifiedLoginCancelled`: emitted when the simplified login widget is closed.
34
+ */
35
+ export type IdentityEventName =
36
+ | 'login'
37
+ | 'logout'
38
+ | 'userChange'
39
+ | 'sessionChange'
40
+ | 'notLoggedin'
41
+ | 'sessionInit'
42
+ | 'statusChange'
43
+ | 'error'
44
+ | 'simplifiedLoginOpened'
45
+ | 'simplifiedLoginCancelled';
46
+
47
+ /**
48
+ * Options for {@link Identity#enableVarnishCookie}.
49
+ */
50
+ export type VarnishCookieOptions = {
51
+ /** Override number of seconds before the Varnish cookie expires. */
52
+ expiresIn?: number;
53
+ /** Override cookie domain. E.g. "vg.no" instead of "www.vg.no". */
54
+ domain?: string;
55
+ };