@serialsubscriptions/platform-integration 0.0.84 → 0.0.85
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/lib/SubscribedPlanManager.d.ts +7 -0
- package/lib/SubscribedPlanManager.js +16 -1
- package/lib/auth.server.d.ts +3 -1
- package/lib/auth.server.js +3 -2
- package/lib/clientConfig.d.ts +24 -0
- package/lib/clientConfig.js +15 -0
- package/lib/frontend/index.d.ts +2 -0
- package/lib/frontend/index.js +4 -2
- package/lib/frontend/session/SessionClient.d.ts +14 -2
- package/lib/frontend/session/SessionClient.js +23 -17
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/requestConfig.d.ts +38 -0
- package/lib/requestConfig.js +34 -0
- package/lib/session/SessionManager.d.ts +10 -8
- package/lib/session/SessionManager.js +9 -16
- package/package.json +4 -1
|
@@ -36,9 +36,16 @@ import { type JsonApiResource } from './SSISubscribedPlanApi';
|
|
|
36
36
|
* Attributes for a subscribed_plan--subscribed_plan resource.
|
|
37
37
|
* Based on your JSON sample; extra fields will still be present in the raw JSON:API resource.
|
|
38
38
|
*/
|
|
39
|
+
/**
|
|
40
|
+
* Known values for subscribed plan `status` (and for project `subscription_status`
|
|
41
|
+
* when synced from the platform). Document the full list in SUBSCRIBEDPLAN_MANAGER.md.
|
|
42
|
+
*/
|
|
43
|
+
export declare const SUBSCRIPTION_STATUS: {};
|
|
44
|
+
export type SubscriptionStatusValue = (typeof SUBSCRIPTION_STATUS)[keyof typeof SUBSCRIPTION_STATUS] | string;
|
|
39
45
|
export interface SubscribedPlanAttributes {
|
|
40
46
|
drupal_internal__id: number;
|
|
41
47
|
name: string;
|
|
48
|
+
/** Plan status from the platform. See SUBSCRIBEDPLAN_MANAGER.md for possible values. */
|
|
42
49
|
status: string;
|
|
43
50
|
subscription_period: string;
|
|
44
51
|
name_subscript: string | null;
|
|
@@ -33,11 +33,26 @@
|
|
|
33
33
|
* ```
|
|
34
34
|
*/
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.SubscribedPlanManager = void 0;
|
|
36
|
+
exports.SubscribedPlanManager = exports.SUBSCRIPTION_STATUS = void 0;
|
|
37
37
|
const SSISubscribedPlanApi_1 = require("./SSISubscribedPlanApi");
|
|
38
38
|
const SSISubscribedFeatureApi_1 = require("./SSISubscribedFeatureApi");
|
|
39
39
|
const SSISubscribedLimitApi_1 = require("./SSISubscribedLimitApi");
|
|
40
40
|
const SSICache_1 = require("./cache/SSICache");
|
|
41
|
+
/**
|
|
42
|
+
* Attributes for a subscribed_plan--subscribed_plan resource.
|
|
43
|
+
* Based on your JSON sample; extra fields will still be present in the raw JSON:API resource.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* Known values for subscribed plan `status` (and for project `subscription_status`
|
|
47
|
+
* when synced from the platform). Document the full list in SUBSCRIBEDPLAN_MANAGER.md.
|
|
48
|
+
*/
|
|
49
|
+
exports.SUBSCRIPTION_STATUS = {
|
|
50
|
+
// Add values as the platform defines them, e.g.:
|
|
51
|
+
// ACTIVE: 'active',
|
|
52
|
+
// CANCELLED: 'cancelled',
|
|
53
|
+
// TRIALING: 'trialing',
|
|
54
|
+
// PAST_DUE: 'past_due',
|
|
55
|
+
};
|
|
41
56
|
/**
|
|
42
57
|
* SubscribedPlanManager
|
|
43
58
|
*
|
package/lib/auth.server.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SSIStorage } from "./storage/SSIStorage";
|
|
2
|
+
import type { AuthConfigInput } from "./requestConfig";
|
|
2
3
|
export declare const scopes: {
|
|
3
4
|
readonly defaultScopes: "openid profile email view_project create_project delete_project update_project view_subscribed_plan view_subscribed_feature view_subscribed_limit access_subscription_usage";
|
|
4
5
|
};
|
|
@@ -67,7 +68,8 @@ export declare class AuthServer {
|
|
|
67
68
|
private stateStorage;
|
|
68
69
|
private jwksCache;
|
|
69
70
|
private lastTokens?;
|
|
70
|
-
|
|
71
|
+
/** Accepts AuthConfig or SSIRequestConfig (e.g. from getRequestConfig(req)). */
|
|
72
|
+
constructor(config?: AuthConfigInput);
|
|
71
73
|
/**
|
|
72
74
|
* Build the authorization URL and persist a CSRF state for the callback.
|
|
73
75
|
* Returns: { url, stateKey, stateValue }
|
package/lib/auth.server.js
CHANGED
|
@@ -43,6 +43,7 @@ const jose_1 = require("jose");
|
|
|
43
43
|
const stateStore_1 = require("./stateStore");
|
|
44
44
|
const SSICache_1 = require("./cache/SSICache");
|
|
45
45
|
const constants_1 = require("./cache/constants");
|
|
46
|
+
const requestConfig_1 = require("./requestConfig");
|
|
46
47
|
exports.scopes = {
|
|
47
48
|
defaultScopes: "openid profile email view_project create_project delete_project update_project view_subscribed_plan view_subscribed_feature view_subscribed_limit access_subscription_usage"
|
|
48
49
|
};
|
|
@@ -93,9 +94,9 @@ function getJwtExpirySeconds(jwt) {
|
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
class AuthServer {
|
|
97
|
+
/** Accepts AuthConfig or SSIRequestConfig (e.g. from getRequestConfig(req)). */
|
|
96
98
|
constructor(config) {
|
|
97
|
-
|
|
98
|
-
const cfg = config ?? {};
|
|
99
|
+
const cfg = (0, requestConfig_1.normalizeAuthConfig)(config) ?? {};
|
|
99
100
|
let scopesString;
|
|
100
101
|
if (cfg.scopes === undefined || cfg.scopes === null) {
|
|
101
102
|
scopesString = exports.scopes.defaultScopes;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config shape that host apps use in the browser (e.g. from getClientConfig()).
|
|
3
|
+
*
|
|
4
|
+
* Derived from public env (NEXT_PUBLIC_*) and optionally window.location.
|
|
5
|
+
* Use this type for the return value of your client config helper so SessionClient
|
|
6
|
+
* and other client code stay typed.
|
|
7
|
+
*
|
|
8
|
+
* - **baseUrl**: App origin (e.g. window.location.origin or NEXT_PUBLIC_APP_URL).
|
|
9
|
+
* - **apiUrl**: App API base; where your app’s routes live (e.g. /api/v1/auth/session).
|
|
10
|
+
* Pass to SessionClient.getSessionClient(config.apiUrl ?? config.baseUrl).
|
|
11
|
+
* - **ssiApiUrl**: SSI Platform API base (for links, account portal, etc.).
|
|
12
|
+
* - **ssiIssuerBaseUrl**: SSI issuer URL (often same as ssiApiUrl; e.g. for /pricing links).
|
|
13
|
+
*/
|
|
14
|
+
export type SSIClientConfig = {
|
|
15
|
+
baseUrl: string | null;
|
|
16
|
+
apiUrl?: string | null;
|
|
17
|
+
ssiApiUrl?: string | null;
|
|
18
|
+
ssiIssuerBaseUrl?: string | null;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Returns the URL to pass to SessionClient (app base so it can call the app’s session endpoint).
|
|
22
|
+
* Prefers apiUrl so the session route is resolved correctly when app and API differ.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getSessionClientBaseUrl(config: SSIClientConfig | undefined | null): string | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// clientConfig.ts
|
|
3
|
+
// Client-side config types and helpers. No server/auth dependencies so safe for frontend bundle.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getSessionClientBaseUrl = getSessionClientBaseUrl;
|
|
6
|
+
/**
|
|
7
|
+
* Returns the URL to pass to SessionClient (app base so it can call the app’s session endpoint).
|
|
8
|
+
* Prefers apiUrl so the session route is resolved correctly when app and API differ.
|
|
9
|
+
*/
|
|
10
|
+
function getSessionClientBaseUrl(config) {
|
|
11
|
+
if (config == null)
|
|
12
|
+
return undefined;
|
|
13
|
+
const url = config.apiUrl ?? config.baseUrl;
|
|
14
|
+
return url != null && url !== "" ? url : undefined;
|
|
15
|
+
}
|
package/lib/frontend/index.d.ts
CHANGED
package/lib/frontend/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SessionClient = void 0;
|
|
4
|
-
// Browser/middleware-safe exports only
|
|
3
|
+
exports.getSessionClientBaseUrl = exports.SessionClient = void 0;
|
|
4
|
+
// Browser/middleware-safe exports only (no auth.server / requestConfig)
|
|
5
5
|
var SessionClient_1 = require("./session/SessionClient");
|
|
6
6
|
Object.defineProperty(exports, "SessionClient", { enumerable: true, get: function () { return SessionClient_1.SessionClient; } });
|
|
7
|
+
var clientConfig_1 = require("../clientConfig");
|
|
8
|
+
Object.defineProperty(exports, "getSessionClientBaseUrl", { enumerable: true, get: function () { return clientConfig_1.getSessionClientBaseUrl; } });
|
|
@@ -1,13 +1,25 @@
|
|
|
1
|
+
import { type SSIClientConfig } from '../../clientConfig';
|
|
1
2
|
export declare class SessionClient {
|
|
2
3
|
private readonly cookieHeader?;
|
|
3
|
-
private static readonly instances;
|
|
4
4
|
private readonly baseUrl;
|
|
5
5
|
private claims;
|
|
6
6
|
private ttl;
|
|
7
7
|
private initPromise;
|
|
8
8
|
private static normalizeBaseUrl;
|
|
9
9
|
constructor(baseUrl?: string, cookieHeader?: string | null | undefined);
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Returns a new SessionClient for this request. Call once per request (or per user
|
|
12
|
+
* context) so session is not shared across requests.
|
|
13
|
+
*
|
|
14
|
+
* Accepts a base URL string or an SSIClientConfig (e.g. from getClientConfig());
|
|
15
|
+
* when given config, uses config.apiUrl ?? config.baseUrl.
|
|
16
|
+
*
|
|
17
|
+
* In Next.js server components/route handlers you can omit cookieHeader: the client
|
|
18
|
+
* will automatically use the current request's session cookie (via next/headers).
|
|
19
|
+
* In other server contexts (e.g. middleware, non-Next), pass the request's Cookie
|
|
20
|
+
* header so this client is bound to that request's session.
|
|
21
|
+
*/
|
|
22
|
+
static getSessionClient(baseUrlOrConfig?: string | SSIClientConfig, cookieHeader?: string | null): SessionClient;
|
|
11
23
|
isLoggedIn(): Promise<boolean>;
|
|
12
24
|
warmup(): void;
|
|
13
25
|
getTtl(): Promise<number | null>;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SessionClient = void 0;
|
|
4
|
+
const clientConfig_1 = require("../../clientConfig");
|
|
5
|
+
/** Session cookie name; must match SessionManager (SSI_COOKIE_NAME env or default). */
|
|
6
|
+
const SESSION_COOKIE_NAME = process.env.SSI_COOKIE_NAME ?? "ssi_session";
|
|
4
7
|
class SessionClient {
|
|
5
8
|
static normalizeBaseUrl(baseUrl) {
|
|
6
9
|
if (!baseUrl) {
|
|
@@ -30,16 +33,21 @@ class SessionClient {
|
|
|
30
33
|
}
|
|
31
34
|
this.initPromise = this.loadClaims();
|
|
32
35
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Returns a new SessionClient for this request. Call once per request (or per user
|
|
38
|
+
* context) so session is not shared across requests.
|
|
39
|
+
*
|
|
40
|
+
* Accepts a base URL string or an SSIClientConfig (e.g. from getClientConfig());
|
|
41
|
+
* when given config, uses config.apiUrl ?? config.baseUrl.
|
|
42
|
+
*
|
|
43
|
+
* In Next.js server components/route handlers you can omit cookieHeader: the client
|
|
44
|
+
* will automatically use the current request's session cookie (via next/headers).
|
|
45
|
+
* In other server contexts (e.g. middleware, non-Next), pass the request's Cookie
|
|
46
|
+
* header so this client is bound to that request's session.
|
|
47
|
+
*/
|
|
48
|
+
static getSessionClient(baseUrlOrConfig, cookieHeader) {
|
|
49
|
+
const baseUrl = typeof baseUrlOrConfig === 'string' ? baseUrlOrConfig : (0, clientConfig_1.getSessionClientBaseUrl)(baseUrlOrConfig);
|
|
50
|
+
return new SessionClient(baseUrl, cookieHeader);
|
|
43
51
|
}
|
|
44
52
|
async isLoggedIn() {
|
|
45
53
|
await this.initPromise;
|
|
@@ -87,14 +95,13 @@ class SessionClient {
|
|
|
87
95
|
return init;
|
|
88
96
|
}
|
|
89
97
|
try {
|
|
90
|
-
// Dynamic import of next/headers - only available in Next.js server context
|
|
91
|
-
// @ts-expect-error - next/headers types are available at runtime but TypeScript can't resolve them during package build
|
|
98
|
+
// Dynamic import of next/headers - only available in Next.js server context (request-scoped)
|
|
92
99
|
const { cookies } = await import("next/headers");
|
|
93
100
|
const cookieStore = await cookies();
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
101
|
+
const sessionCookie = cookieStore.get(SESSION_COOKIE_NAME);
|
|
102
|
+
const serializedCookies = sessionCookie
|
|
103
|
+
? `${sessionCookie.name}=${sessionCookie.value}`
|
|
104
|
+
: "";
|
|
98
105
|
if (!serializedCookies) {
|
|
99
106
|
return init;
|
|
100
107
|
}
|
|
@@ -141,5 +148,4 @@ class SessionClient {
|
|
|
141
148
|
}
|
|
142
149
|
}
|
|
143
150
|
exports.SessionClient = SessionClient;
|
|
144
|
-
SessionClient.instances = new Map();
|
|
145
151
|
exports.default = SessionClient;
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -16,6 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.SSISubscribedPlanApi = exports.SSISubscribedLimitApi = exports.SSISubscribedFeatureApi = exports.SessionClient = void 0;
|
|
18
18
|
__exportStar(require("./auth.server"), exports);
|
|
19
|
+
__exportStar(require("./requestConfig"), exports);
|
|
20
|
+
__exportStar(require("./clientConfig"), exports);
|
|
19
21
|
__exportStar(require("./stateStore"), exports);
|
|
20
22
|
__exportStar(require("./storage/SSIStorage"), exports);
|
|
21
23
|
__exportStar(require("./storage/types"), exports);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AuthConfig } from './auth.server';
|
|
2
|
+
/**
|
|
3
|
+
* SSI-related config that host apps typically derive from the current request
|
|
4
|
+
* (e.g. via getRequestConfig(req)) and pass to the library.
|
|
5
|
+
*
|
|
6
|
+
* Use this type when building a "request config" in your app so SessionManager,
|
|
7
|
+
* AuthServer, UsageApi, and SubscribedPlanManager get a consistent, typed shape.
|
|
8
|
+
*
|
|
9
|
+
* - **ssiIssuerBaseUrl**, **ssiRedirectUri**, **ssiClientId**: passed to
|
|
10
|
+
* AuthServer and SessionManager.fromEnv(cookieHeader, config).
|
|
11
|
+
* - **ssiApiUrl**: base URL for SSI Platform API (UsageApi, SubscribedPlanManager,
|
|
12
|
+
* SSIProjectApi, etc.).
|
|
13
|
+
* - **baseUrl** / **apiUrl**: optional; for app use (e.g. redirect after login).
|
|
14
|
+
* The library does not use these; they are included so apps can use this type
|
|
15
|
+
* as the SSI subset of a larger RequestConfig.
|
|
16
|
+
*/
|
|
17
|
+
export type SSIRequestConfig = {
|
|
18
|
+
baseUrl?: string | null;
|
|
19
|
+
apiUrl?: string | null;
|
|
20
|
+
ssiApiUrl: string | null;
|
|
21
|
+
ssiIssuerBaseUrl: string | null;
|
|
22
|
+
ssiRedirectUri: string | null;
|
|
23
|
+
ssiClientId: string | null;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Union type accepted anywhere AuthConfig is accepted (AuthServer, SessionManager).
|
|
27
|
+
*/
|
|
28
|
+
export type AuthConfigInput = AuthConfig | SSIRequestConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Converts SSIRequestConfig to AuthConfig for use with AuthServer and SessionManager.
|
|
31
|
+
* Drops null/undefined so the library can fall back to env vars where appropriate.
|
|
32
|
+
*/
|
|
33
|
+
export declare function toAuthConfig(rc: SSIRequestConfig): AuthConfig;
|
|
34
|
+
/**
|
|
35
|
+
* Normalizes AuthConfigInput to AuthConfig. Use internally so AuthServer and SessionManager
|
|
36
|
+
* accept both AuthConfig and SSIRequestConfig.
|
|
37
|
+
*/
|
|
38
|
+
export declare function normalizeAuthConfig(input: AuthConfigInput | undefined): AuthConfig | undefined;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// requestConfig.ts
|
|
3
|
+
// Types for config that host apps derive per-request and pass into AuthServer, SessionManager, and SSI API clients.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.toAuthConfig = toAuthConfig;
|
|
6
|
+
exports.normalizeAuthConfig = normalizeAuthConfig;
|
|
7
|
+
function isSSIRequestConfig(x) {
|
|
8
|
+
return x != null && typeof x === 'object' && 'ssiIssuerBaseUrl' in x;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Converts SSIRequestConfig to AuthConfig for use with AuthServer and SessionManager.
|
|
12
|
+
* Drops null/undefined so the library can fall back to env vars where appropriate.
|
|
13
|
+
*/
|
|
14
|
+
function toAuthConfig(rc) {
|
|
15
|
+
const auth = {};
|
|
16
|
+
if (rc.ssiIssuerBaseUrl != null && rc.ssiIssuerBaseUrl !== '')
|
|
17
|
+
auth.issuerBaseUrl = rc.ssiIssuerBaseUrl;
|
|
18
|
+
if (rc.ssiRedirectUri != null && rc.ssiRedirectUri !== '')
|
|
19
|
+
auth.redirectUri = rc.ssiRedirectUri;
|
|
20
|
+
if (rc.ssiClientId != null && rc.ssiClientId !== '')
|
|
21
|
+
auth.clientId = rc.ssiClientId;
|
|
22
|
+
return auth;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Normalizes AuthConfigInput to AuthConfig. Use internally so AuthServer and SessionManager
|
|
26
|
+
* accept both AuthConfig and SSIRequestConfig.
|
|
27
|
+
*/
|
|
28
|
+
function normalizeAuthConfig(input) {
|
|
29
|
+
if (input == null)
|
|
30
|
+
return undefined;
|
|
31
|
+
if (isSSIRequestConfig(input))
|
|
32
|
+
return toAuthConfig(input);
|
|
33
|
+
return input;
|
|
34
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SSIStorage } from '../storage/SSIStorage';
|
|
2
2
|
import type { KVValue } from '../storage/types';
|
|
3
|
-
import { AuthServer, type TokenResponse
|
|
3
|
+
import { AuthServer, type TokenResponse } from '../auth.server';
|
|
4
|
+
import { type AuthConfigInput } from '../requestConfig';
|
|
4
5
|
export declare const sessionRoles: {
|
|
5
6
|
allRoles: string[];
|
|
6
7
|
adminRoles: string[];
|
|
@@ -43,11 +44,12 @@ export declare class SessionManager {
|
|
|
43
44
|
private authConfig?;
|
|
44
45
|
private static inFlightRefresh;
|
|
45
46
|
private freshnessOnce;
|
|
46
|
-
|
|
47
|
+
/** Accepts AuthConfig or SSIRequestConfig (e.g. from getRequestConfig(req)). */
|
|
48
|
+
constructor(storage: SSIStorage, authConfig?: AuthConfigInput);
|
|
47
49
|
static fromEnv(): SessionManager;
|
|
48
|
-
static fromEnv(cookieHeader: string | null, authConfig?:
|
|
49
|
-
static fromEnv(request: Request, authConfig?:
|
|
50
|
-
static fromEnv(authConfig:
|
|
50
|
+
static fromEnv(cookieHeader: string | null, authConfig?: AuthConfigInput): SessionManager;
|
|
51
|
+
static fromEnv(request: Request, authConfig?: AuthConfigInput): SessionManager;
|
|
52
|
+
static fromEnv(authConfig: AuthConfigInput): SessionManager;
|
|
51
53
|
/**
|
|
52
54
|
* Async version that attempts to auto-detect the cookie header from Next.js context
|
|
53
55
|
* when called with no arguments. Falls back gracefully if not in a Next.js context.
|
|
@@ -65,9 +67,9 @@ export declare class SessionManager {
|
|
|
65
67
|
* const session = await SessionManager.fromEnvAsync(request, { clientId: 'my-client-id' });
|
|
66
68
|
*/
|
|
67
69
|
static fromEnvAsync(): Promise<SessionManager>;
|
|
68
|
-
static fromEnvAsync(cookieHeader: string | null, authConfig?:
|
|
69
|
-
static fromEnvAsync(request: Request, authConfig?:
|
|
70
|
-
static fromEnvAsync(authConfig:
|
|
70
|
+
static fromEnvAsync(cookieHeader: string | null, authConfig?: AuthConfigInput): Promise<SessionManager>;
|
|
71
|
+
static fromEnvAsync(request: Request, authConfig?: AuthConfigInput): Promise<SessionManager>;
|
|
72
|
+
static fromEnvAsync(authConfig: AuthConfigInput): Promise<SessionManager>;
|
|
71
73
|
private parseCookies;
|
|
72
74
|
get sessionId(): string | undefined;
|
|
73
75
|
/** Cryptographically strong, URL-safe session id */
|
|
@@ -4,6 +4,7 @@ exports.SessionManager = exports.sessionRoles = void 0;
|
|
|
4
4
|
const SSIStorage_1 = require("../storage/SSIStorage");
|
|
5
5
|
const crypto_1 = require("crypto");
|
|
6
6
|
const auth_server_1 = require("../auth.server");
|
|
7
|
+
const requestConfig_1 = require("../requestConfig");
|
|
7
8
|
exports.sessionRoles = {
|
|
8
9
|
allRoles: ['platform_admin', 'member', 'owner', 'admin', 'billing', 'readonly'],
|
|
9
10
|
adminRoles: ['platform_admin', 'owner', 'admin'],
|
|
@@ -35,25 +36,22 @@ function resolveCookieDomain() {
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
class SessionManager {
|
|
39
|
+
/** Accepts AuthConfig or SSIRequestConfig (e.g. from getRequestConfig(req)). */
|
|
38
40
|
constructor(storage, authConfig) {
|
|
39
41
|
// Per-request-instance guard so TTL/refresh is evaluated at most once per session
|
|
40
42
|
this.freshnessOnce = new Map();
|
|
41
43
|
this.storage = storage.withClass('session'); // pin class="session"
|
|
42
|
-
this.authConfig = authConfig;
|
|
44
|
+
this.authConfig = (0, requestConfig_1.normalizeAuthConfig)(authConfig);
|
|
43
45
|
}
|
|
44
46
|
static fromEnv(cookieHeaderOrRequestOrConfig, authConfig) {
|
|
45
|
-
// Handle case where first arg is AuthConfig (no cookie header/request)
|
|
46
47
|
let actualAuthConfig;
|
|
47
48
|
let cookieHeaderOrRequest;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
('clientId' in cookieHeaderOrRequestOrConfig || 'issuerBaseUrl' in cookieHeaderOrRequestOrConfig)) {
|
|
52
|
-
// First arg is AuthConfig
|
|
49
|
+
const isConfigLike = (x) => x != null && typeof x === 'object' && !(x instanceof Request) &&
|
|
50
|
+
('clientId' in x || 'issuerBaseUrl' in x || 'ssiClientId' in x || 'ssiIssuerBaseUrl' in x);
|
|
51
|
+
if (cookieHeaderOrRequestOrConfig && isConfigLike(cookieHeaderOrRequestOrConfig)) {
|
|
53
52
|
actualAuthConfig = cookieHeaderOrRequestOrConfig;
|
|
54
53
|
}
|
|
55
54
|
else {
|
|
56
|
-
// First arg is cookie header/request, second is optional AuthConfig
|
|
57
55
|
cookieHeaderOrRequest = cookieHeaderOrRequestOrConfig;
|
|
58
56
|
actualAuthConfig = authConfig;
|
|
59
57
|
}
|
|
@@ -73,18 +71,14 @@ class SessionManager {
|
|
|
73
71
|
return session;
|
|
74
72
|
}
|
|
75
73
|
static async fromEnvAsync(cookieHeaderOrRequestOrConfig, authConfig) {
|
|
76
|
-
// Handle case where first arg is AuthConfig (no cookie header/request)
|
|
77
74
|
let actualAuthConfig;
|
|
78
75
|
let cookieHeaderOrRequest;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
('clientId' in cookieHeaderOrRequestOrConfig || 'issuerBaseUrl' in cookieHeaderOrRequestOrConfig)) {
|
|
83
|
-
// First arg is AuthConfig
|
|
76
|
+
const isConfigLike = (x) => x != null && typeof x === 'object' && !(x instanceof Request) &&
|
|
77
|
+
('clientId' in x || 'issuerBaseUrl' in x || 'ssiClientId' in x || 'ssiIssuerBaseUrl' in x);
|
|
78
|
+
if (cookieHeaderOrRequestOrConfig && isConfigLike(cookieHeaderOrRequestOrConfig)) {
|
|
84
79
|
actualAuthConfig = cookieHeaderOrRequestOrConfig;
|
|
85
80
|
}
|
|
86
81
|
else {
|
|
87
|
-
// First arg is cookie header/request, second is optional AuthConfig
|
|
88
82
|
cookieHeaderOrRequest = cookieHeaderOrRequestOrConfig;
|
|
89
83
|
actualAuthConfig = authConfig;
|
|
90
84
|
}
|
|
@@ -102,7 +96,6 @@ class SessionManager {
|
|
|
102
96
|
// When called with no arguments, try to auto-detect cookie header from Next.js context
|
|
103
97
|
try {
|
|
104
98
|
// Dynamic import of next/headers - only available in Next.js server context
|
|
105
|
-
// @ts-expect-error - next/headers types are available at runtime but TypeScript can't resolve them during package build
|
|
106
99
|
const { headers } = await import('next/headers');
|
|
107
100
|
const headersList = await headers();
|
|
108
101
|
if (headersList && typeof headersList.get === 'function') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serialsubscriptions/platform-integration",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.85",
|
|
4
4
|
"description": "Serial Subscriptions Libraries",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -67,5 +67,8 @@
|
|
|
67
67
|
"peerDependencies": {
|
|
68
68
|
"next": "^15.0.0"
|
|
69
69
|
},
|
|
70
|
+
"optionalDependencies": {
|
|
71
|
+
"next": "^15.0.0"
|
|
72
|
+
},
|
|
70
73
|
"license": "MIT"
|
|
71
74
|
}
|