@serialsubscriptions/platform-integration 0.0.79

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 +1 -0
  2. package/lib/SSIProject.d.ts +343 -0
  3. package/lib/SSIProject.js +429 -0
  4. package/lib/SSIProjectApi.d.ts +384 -0
  5. package/lib/SSIProjectApi.js +534 -0
  6. package/lib/SSISubscribedFeatureApi.d.ts +387 -0
  7. package/lib/SSISubscribedFeatureApi.js +511 -0
  8. package/lib/SSISubscribedLimitApi.d.ts +384 -0
  9. package/lib/SSISubscribedLimitApi.js +534 -0
  10. package/lib/SSISubscribedPlanApi.d.ts +384 -0
  11. package/lib/SSISubscribedPlanApi.js +537 -0
  12. package/lib/SubscribedPlanManager.d.ts +380 -0
  13. package/lib/SubscribedPlanManager.js +288 -0
  14. package/lib/UsageApi.d.ts +128 -0
  15. package/lib/UsageApi.js +224 -0
  16. package/lib/auth.server.d.ts +192 -0
  17. package/lib/auth.server.js +579 -0
  18. package/lib/cache/SSICache.d.ts +40 -0
  19. package/lib/cache/SSICache.js +134 -0
  20. package/lib/cache/backends/MemoryCacheBackend.d.ts +15 -0
  21. package/lib/cache/backends/MemoryCacheBackend.js +46 -0
  22. package/lib/cache/backends/RedisCacheBackend.d.ts +27 -0
  23. package/lib/cache/backends/RedisCacheBackend.js +95 -0
  24. package/lib/cache/constants.d.ts +7 -0
  25. package/lib/cache/constants.js +10 -0
  26. package/lib/cache/types.d.ts +27 -0
  27. package/lib/cache/types.js +2 -0
  28. package/lib/frontend/index.d.ts +1 -0
  29. package/lib/frontend/index.js +6 -0
  30. package/lib/frontend/session/SessionClient.d.ts +24 -0
  31. package/lib/frontend/session/SessionClient.js +145 -0
  32. package/lib/index.d.ts +15 -0
  33. package/lib/index.js +38 -0
  34. package/lib/lib/session/SessionClient.d.ts +11 -0
  35. package/lib/lib/session/SessionClient.js +47 -0
  36. package/lib/lib/session/index.d.ts +3 -0
  37. package/lib/lib/session/index.js +3 -0
  38. package/lib/lib/session/stores/MemoryStore.d.ts +7 -0
  39. package/lib/lib/session/stores/MemoryStore.js +23 -0
  40. package/lib/lib/session/stores/index.d.ts +1 -0
  41. package/lib/lib/session/stores/index.js +1 -0
  42. package/lib/lib/session/types.d.ts +37 -0
  43. package/lib/lib/session/types.js +1 -0
  44. package/lib/session/SessionClient.d.ts +19 -0
  45. package/lib/session/SessionClient.js +132 -0
  46. package/lib/session/SessionManager.d.ts +139 -0
  47. package/lib/session/SessionManager.js +443 -0
  48. package/lib/stateStore.d.ts +5 -0
  49. package/lib/stateStore.js +9 -0
  50. package/lib/storage/SSIStorage.d.ts +24 -0
  51. package/lib/storage/SSIStorage.js +117 -0
  52. package/lib/storage/backends/MemoryBackend.d.ts +10 -0
  53. package/lib/storage/backends/MemoryBackend.js +44 -0
  54. package/lib/storage/backends/PostgresBackend.d.ts +24 -0
  55. package/lib/storage/backends/PostgresBackend.js +106 -0
  56. package/lib/storage/backends/RedisBackend.d.ts +19 -0
  57. package/lib/storage/backends/RedisBackend.js +78 -0
  58. package/lib/storage/types.d.ts +27 -0
  59. package/lib/storage/types.js +2 -0
  60. package/package.json +71 -0
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './SessionClient';
3
+ export * from './stores';
@@ -0,0 +1,7 @@
1
+ import type { SessionStore } from '../types';
2
+ export declare class MemoryStore implements SessionStore {
3
+ private map;
4
+ get<T = unknown>(key: string): Promise<T | null>;
5
+ set<T = unknown>(key: string, value: T, ttlSec?: number): Promise<void>;
6
+ del(key: string): Promise<void>;
7
+ }
@@ -0,0 +1,23 @@
1
+ export class MemoryStore {
2
+ constructor() {
3
+ this.map = new Map();
4
+ }
5
+ async get(key) {
6
+ const now = Date.now();
7
+ const hit = this.map.get(key);
8
+ if (!hit)
9
+ return null;
10
+ if (hit.expiresAt !== undefined && hit.expiresAt <= now) {
11
+ this.map.delete(key);
12
+ return null;
13
+ }
14
+ return hit.value;
15
+ }
16
+ async set(key, value, ttlSec) {
17
+ const expiresAt = ttlSec !== undefined && ttlSec > 0 ? Date.now() + ttlSec * 1000 : undefined;
18
+ this.map.set(key, { value, expiresAt });
19
+ }
20
+ async del(key) {
21
+ this.map.delete(key);
22
+ }
23
+ }
@@ -0,0 +1 @@
1
+ export { MemoryStore } from './MemoryStore';
@@ -0,0 +1 @@
1
+ export { MemoryStore } from './MemoryStore';
@@ -0,0 +1,37 @@
1
+ export interface SessionStore {
2
+ get<T = unknown>(key: string): Promise<T | null>;
3
+ set<T = unknown>(key: string, value: T, ttlSec?: number): Promise<void>;
4
+ del(key: string): Promise<void>;
5
+ }
6
+ export type SameSite = 'lax' | 'strict' | 'none';
7
+ export interface JWKSOptions {
8
+ issuer: string;
9
+ jwksUri: string;
10
+ cacheTtlSec?: number;
11
+ }
12
+ export interface RequiredClaims {
13
+ sub: string;
14
+ organization_id?: number | string;
15
+ role?: string;
16
+ [k: string]: unknown;
17
+ }
18
+ export interface SessionClientInit {
19
+ store: SessionStore;
20
+ refresh?: {
21
+ endpoint: string;
22
+ graceSec?: number;
23
+ defaultTtlSec?: number;
24
+ };
25
+ }
26
+ export interface TokenBundle {
27
+ id_token: string;
28
+ access_token: string;
29
+ refresh_token?: string;
30
+ ttlSec?: number;
31
+ }
32
+ export interface SessionSnapshot {
33
+ claims: unknown | null;
34
+ access_token: string | null;
35
+ id_token: string | null;
36
+ refresh_token: string | null;
37
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ export declare class SessionClient {
2
+ private readonly cookieHeader?;
3
+ private static readonly instances;
4
+ private readonly baseUrl;
5
+ private claims;
6
+ private ttl;
7
+ private initPromise;
8
+ private static normalizeBaseUrl;
9
+ constructor(baseUrl?: string, cookieHeader?: string | null | undefined);
10
+ static getSessionManager(baseUrl?: string): SessionClient;
11
+ isLoggedIn(): Promise<boolean>;
12
+ warmup(): void;
13
+ getTtl(): Promise<number | null>;
14
+ get(claimName: string): Promise<unknown>;
15
+ getAll(): Promise<unknown | null>;
16
+ private withSession;
17
+ private loadClaims;
18
+ }
19
+ export default SessionClient;
@@ -0,0 +1,132 @@
1
+ export class SessionClient {
2
+ static normalizeBaseUrl(baseUrl) {
3
+ if (!baseUrl) {
4
+ return "";
5
+ }
6
+ try {
7
+ const url = new URL(baseUrl);
8
+ // Remove trailing slash and default ports
9
+ url.pathname = url.pathname.replace(/\/$/, "");
10
+ if ((url.protocol === "https:" && url.port === "443") || (url.protocol === "http:" && url.port === "80")) {
11
+ url.port = "";
12
+ }
13
+ return url.toString().replace(/\/$/, "");
14
+ }
15
+ catch {
16
+ return baseUrl;
17
+ }
18
+ }
19
+ constructor(baseUrl, cookieHeader) {
20
+ this.cookieHeader = cookieHeader;
21
+ this.claims = null;
22
+ this.ttl = null;
23
+ const resolvedBaseUrl = baseUrl ?? process.env.NEXT_PUBLIC_BASE_URL ?? "";
24
+ this.baseUrl = SessionClient.normalizeBaseUrl(resolvedBaseUrl);
25
+ if (!this.baseUrl || !this.baseUrl.startsWith("http://") && !this.baseUrl.startsWith("https://")) {
26
+ console.error(`You must set baseUrl to SessionClient or you must set env variable NEXT_PUBLIC_BASE_URL. Incorrect value \`${resolvedBaseUrl}\``);
27
+ }
28
+ this.initPromise = this.loadClaims();
29
+ }
30
+ static getSessionManager(baseUrl) {
31
+ const resolvedBaseUrl = baseUrl ?? process.env.NEXT_PUBLIC_BASE_URL ?? "";
32
+ const normalizedBaseUrl = SessionClient.normalizeBaseUrl(resolvedBaseUrl);
33
+ if (!normalizedBaseUrl || !normalizedBaseUrl.startsWith("http://") && !normalizedBaseUrl.startsWith("https://")) {
34
+ console.error(`You must set baseUrl to SessionClient or you must set env variable NEXT_PUBLIC_BASE_URL. Incorrect value \`${resolvedBaseUrl}\``);
35
+ }
36
+ if (!SessionClient.instances.has(normalizedBaseUrl)) {
37
+ SessionClient.instances.set(normalizedBaseUrl, new SessionClient(baseUrl));
38
+ }
39
+ return SessionClient.instances.get(normalizedBaseUrl);
40
+ }
41
+ async isLoggedIn() {
42
+ await this.initPromise;
43
+ return this.claims != null;
44
+ }
45
+ // Non-awaiting stub to ensure initialization happens without blocking
46
+ warmup() {
47
+ void this.initPromise;
48
+ }
49
+ async getTtl() {
50
+ await this.initPromise;
51
+ return this.ttl;
52
+ }
53
+ async get(claimName) {
54
+ await this.initPromise;
55
+ if (this.claims && typeof this.claims === "object") {
56
+ const record = this.claims;
57
+ return record[claimName];
58
+ }
59
+ return undefined;
60
+ }
61
+ async getAll() {
62
+ await this.initPromise;
63
+ return this.claims;
64
+ }
65
+ async withSession(init = {}) {
66
+ if (this.cookieHeader) {
67
+ const headers = new Headers(init.headers ?? {});
68
+ if (!headers.has("Cookie")) {
69
+ headers.set("Cookie", this.cookieHeader);
70
+ }
71
+ return {
72
+ ...init,
73
+ headers,
74
+ };
75
+ }
76
+ if (typeof window !== "undefined") {
77
+ return init;
78
+ }
79
+ try {
80
+ const { cookies } = await import("next/headers");
81
+ const cookieStore = await cookies();
82
+ const serializedCookies = cookieStore
83
+ .getAll()
84
+ .map(({ name, value }) => `${name}=${value}`)
85
+ .join("; ");
86
+ if (!serializedCookies) {
87
+ return init;
88
+ }
89
+ const headers = new Headers(init.headers ?? {});
90
+ if (!headers.has("Cookie")) {
91
+ headers.set("Cookie", serializedCookies);
92
+ }
93
+ return {
94
+ ...init,
95
+ headers,
96
+ };
97
+ }
98
+ catch {
99
+ return init;
100
+ }
101
+ }
102
+ async loadClaims() {
103
+ try {
104
+ const url = new URL("/api/v1/auth/session", this.baseUrl).toString();
105
+ const response = await fetch(url, await this.withSession({
106
+ method: "GET",
107
+ headers: { accept: "application/json" },
108
+ credentials: "include",
109
+ }));
110
+ if (!response.ok) {
111
+ this.claims = null;
112
+ this.ttl = null;
113
+ return;
114
+ }
115
+ const data = (await response.json());
116
+ if (data.ok) {
117
+ this.claims = data.claims ?? null;
118
+ this.ttl = typeof data.ttl_seconds === "number" ? data.ttl_seconds : null;
119
+ }
120
+ else {
121
+ this.claims = null;
122
+ this.ttl = null;
123
+ }
124
+ }
125
+ catch (_err) {
126
+ this.claims = null;
127
+ this.ttl = null;
128
+ }
129
+ }
130
+ }
131
+ SessionClient.instances = new Map();
132
+ export default SessionClient;
@@ -0,0 +1,139 @@
1
+ import { SSIStorage } from '../storage/SSIStorage';
2
+ import type { KVValue } from '../storage/types';
3
+ import { AuthServer, type TokenResponse, type AuthConfig } from '../auth.server';
4
+ export declare const sessionRoles: {
5
+ allRoles: string[];
6
+ adminRoles: string[];
7
+ userRoles: string[];
8
+ userAdminRoles: string[];
9
+ };
10
+ export type SessionDataKey = 'claims' | 'id_token' | 'access_token' | 'refresh_token';
11
+ export interface SetSessionInput {
12
+ sessionId?: string;
13
+ id_token: string;
14
+ access_token: string;
15
+ refresh_token: string;
16
+ /**
17
+ * TTL for the refresh token (seconds). Defaults to 7 days.
18
+ * id_token/access_token inherit the same TTL unless you pass token-specific values.
19
+ */
20
+ refreshTtlSeconds?: number;
21
+ idTokenTtlSeconds?: number;
22
+ accessTokenTtlSeconds?: number;
23
+ /**
24
+ * Cookie overrides. If omitted, sensible defaults are used.
25
+ */
26
+ cookie?: Partial<CookieOptions>;
27
+ }
28
+ export interface CookieOptions {
29
+ name: string;
30
+ domain?: string;
31
+ path: string;
32
+ sameSite: 'Lax' | 'Strict' | 'None';
33
+ secure: boolean;
34
+ httpOnly: boolean;
35
+ /** seconds */
36
+ maxAge: number;
37
+ }
38
+ export declare class SessionManager {
39
+ private storage;
40
+ private auth?;
41
+ private _sessionId?;
42
+ private authConfig?;
43
+ private static inFlightRefresh;
44
+ private freshnessOnce;
45
+ constructor(storage: SSIStorage, authConfig?: AuthConfig);
46
+ static fromEnv(): SessionManager;
47
+ static fromEnv(cookieHeader: string | null, authConfig?: AuthConfig): SessionManager;
48
+ static fromEnv(request: Request, authConfig?: AuthConfig): SessionManager;
49
+ static fromEnv(authConfig: AuthConfig): SessionManager;
50
+ /**
51
+ * Async version that attempts to auto-detect the cookie header from Next.js context
52
+ * when called with no arguments. Falls back gracefully if not in a Next.js context.
53
+ *
54
+ * @example
55
+ * // In Next.js server components or route handlers without Request object
56
+ * const session = await SessionManager.fromEnvAsync();
57
+ *
58
+ * // Still supports explicit cookie header or Request object
59
+ * const session = await SessionManager.fromEnvAsync(request);
60
+ * const session = await SessionManager.fromEnvAsync(cookieHeader);
61
+ *
62
+ * // With AuthConfig
63
+ * const session = await SessionManager.fromEnvAsync({ clientId: 'my-client-id' });
64
+ * const session = await SessionManager.fromEnvAsync(request, { clientId: 'my-client-id' });
65
+ */
66
+ static fromEnvAsync(): Promise<SessionManager>;
67
+ static fromEnvAsync(cookieHeader: string | null, authConfig?: AuthConfig): Promise<SessionManager>;
68
+ static fromEnvAsync(request: Request, authConfig?: AuthConfig): Promise<SessionManager>;
69
+ static fromEnvAsync(authConfig: AuthConfig): Promise<SessionManager>;
70
+ private parseCookies;
71
+ get sessionId(): string | undefined;
72
+ /** Cryptographically strong, URL-safe session id */
73
+ generateSessionId(): string;
74
+ /**
75
+ * Store tokens from AuthServer TokenResponse and return { sessionId, setCookieHeader }.
76
+ * Keys: id_token, access_token, refresh_token
77
+ */
78
+ setSession(auth: AuthServer, tokenResponse: TokenResponse, options?: {
79
+ sessionId?: string;
80
+ refreshTtlSeconds?: number;
81
+ idTokenTtlSeconds?: number;
82
+ accessTokenTtlSeconds?: number;
83
+ cookie?: Partial<CookieOptions>;
84
+ }): Promise<{
85
+ sessionId: string;
86
+ setCookieHeader: string;
87
+ }>;
88
+ /** Convenience overload that reads the last TokenResponse from AuthServer */
89
+ setSession(auth: AuthServer, options?: {
90
+ sessionId?: string;
91
+ refreshTtlSeconds?: number;
92
+ idTokenTtlSeconds?: number;
93
+ accessTokenTtlSeconds?: number;
94
+ cookie?: Partial<CookieOptions>;
95
+ }): Promise<{
96
+ sessionId: string;
97
+ setCookieHeader: string;
98
+ }>;
99
+ /**
100
+ * Store tokens and return { sessionId, setCookieHeader }.
101
+ * Keys: id_token, access_token, refresh_token
102
+ */
103
+ setSession(input: SetSessionInput): Promise<{
104
+ sessionId: string;
105
+ setCookieHeader: string;
106
+ }>;
107
+ /** Build a single Set-Cookie header string for the session id */
108
+ buildSessionCookie(sessionId: string, overrides?: Partial<CookieOptions>): string;
109
+ /**
110
+ * Get session data by key. For 'claims', decodes the id_token payload
111
+ * WITHOUT verification (use your verifier upstream for security).
112
+ */
113
+ getSessionData(sessionId: string, dataKey: SessionDataKey): Promise<KVValue | null>;
114
+ private ensureFreshOnce;
115
+ /**
116
+ * Delete all keys under this session object (id/access/refresh).
117
+ */
118
+ clearSession(sessionId: string): Promise<string>;
119
+ /**
120
+ * Refresh session (stub): you’ll likely:
121
+ * 1) read refresh_token
122
+ * 2) call your token endpoint
123
+ * 3) update stored tokens + extend TTL
124
+ * 4) optionally rotate session id & cookie
125
+ */
126
+ refreshSession(_sessionId: string): Promise<never>;
127
+ /** Returns remaining TTL in seconds for this session's id_token, or null if none */
128
+ getSessionTtlSeconds(sessionId: string): Promise<number | null>;
129
+ private getVerifiedClaims;
130
+ private getRoles;
131
+ hasRole(roleName: string): Promise<boolean>;
132
+ hasRoleOneOf(roleNames: string[]): Promise<boolean>;
133
+ /**
134
+ * Get a specific claim from the session's ID token.
135
+ * Requires `sessionId` to be set (via `fromEnv()` with cookies).
136
+ */
137
+ getClaim(claimName: string): Promise<unknown>;
138
+ private getAuth;
139
+ }