@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,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SSICache = void 0;
4
+ const MemoryCacheBackend_1 = require("./backends/MemoryCacheBackend");
5
+ const RedisCacheBackend_1 = require("./backends/RedisCacheBackend");
6
+ function envBool(v) {
7
+ if (v === undefined)
8
+ return undefined;
9
+ return ['1', 'true', 'yes', 'on'].includes(v.toLowerCase());
10
+ }
11
+ /**
12
+ * Creates a namespaced key according to the required format:
13
+ * container:prefix:key
14
+ */
15
+ function keyFor(container, prefix, key) {
16
+ const safePrefix = (prefix && prefix.length > 0) ? prefix : '_';
17
+ return `${container}:${safePrefix}:${key}`;
18
+ }
19
+ class SSICache {
20
+ constructor(backend, container, prefix) {
21
+ this.backend = backend;
22
+ this.container = container;
23
+ this.prefix = prefix;
24
+ }
25
+ static fromEnv() {
26
+ if (SSICache.__shared)
27
+ return SSICache.__shared;
28
+ const backend = process.env.SSI_CACHE_BACKEND || 'memory';
29
+ const container = process.env.SSI_CACHE_CONTAINER || 'ssi';
30
+ SSICache.__shared = SSICache.init({
31
+ backend,
32
+ container,
33
+ url: process.env.SSI_CACHE_URL,
34
+ host: process.env.SSI_CACHE_HOST,
35
+ port: process.env.SSI_CACHE_PORT ? Number(process.env.SSI_CACHE_PORT) : undefined,
36
+ user: process.env.SSI_CACHE_USER,
37
+ password: process.env.SSI_CACHE_PASSWORD,
38
+ tls: envBool(process.env.SSI_CACHE_SSL),
39
+ });
40
+ return SSICache.__shared;
41
+ }
42
+ static init(opts) {
43
+ const t = opts.backend || 'memory';
44
+ const container = opts.container;
45
+ let backend;
46
+ if (t === 'memory') {
47
+ backend = new MemoryCacheBackend_1.MemoryCacheBackend();
48
+ }
49
+ else if (t === 'redis') {
50
+ backend = new RedisCacheBackend_1.RedisCacheBackend({
51
+ url: opts.url,
52
+ host: opts.host,
53
+ port: opts.port,
54
+ user: opts.user,
55
+ password: opts.password,
56
+ tls: opts.tls,
57
+ });
58
+ }
59
+ else {
60
+ throw new Error(`Unsupported cache backend: ${t}`);
61
+ }
62
+ return new SSICache(backend, container);
63
+ }
64
+ /**
65
+ * Returns a cache instance pinned to a prefix ("jwks", "oidc", "rl", etc.).
66
+ */
67
+ withPrefix(prefix) {
68
+ return new SSICache(this.backend, this.container, prefix);
69
+ // shares the same backend connection; creates a new namespacer
70
+ }
71
+ k(key) {
72
+ return keyFor(this.container, this.prefix, key);
73
+ }
74
+ async get(key) {
75
+ return this.backend.get(this.k(key));
76
+ }
77
+ async set(key, value, ttlSec) {
78
+ await this.backend.set(this.k(key), value, ttlSec);
79
+ }
80
+ async del(key) {
81
+ await this.backend.del(this.k(key));
82
+ }
83
+ async mget(keys) {
84
+ return this.backend.mget(keys.map((k) => this.k(k)));
85
+ }
86
+ async mset(entries) {
87
+ return this.backend.mset(entries.map((e) => ({ key: this.k(e.key), value: e.value, ttlSec: e.ttlSec })));
88
+ }
89
+ async incrby(key, by, ttlSec) {
90
+ return this.backend.incrby(this.k(key), by, ttlSec);
91
+ }
92
+ async ttl(key) {
93
+ return this.backend.ttl(this.k(key));
94
+ }
95
+ /**
96
+ * compute-if-absent: get from cache or compute and cache the value
97
+ */
98
+ async remember(key, ttlSec, loader) {
99
+ const cached = await this.get(key);
100
+ if (cached !== null)
101
+ return cached;
102
+ const value = await loader();
103
+ await this.set(key, value, ttlSec);
104
+ return value;
105
+ }
106
+ /**
107
+ * Simple distributed lock (best-effort): returns lock token if acquired
108
+ * Only works properly with Redis backend; memory backend returns a naive token
109
+ */
110
+ async acquireLock(key, ttlMs) {
111
+ const token = Math.random().toString(36).slice(2);
112
+ if (typeof this.backend.tryLock === 'function') {
113
+ const ok = await this.backend.tryLock(this.k(`lock:${key}`), ttlMs, token);
114
+ return ok ? token : null;
115
+ }
116
+ return token; // naive fallback for memory backend
117
+ }
118
+ /**
119
+ * Release a lock acquired via acquireLock
120
+ */
121
+ async releaseLock(key, token) {
122
+ if (typeof this.backend.unlock === 'function') {
123
+ await this.backend.unlock(this.k(`lock:${key}`), token);
124
+ }
125
+ }
126
+ async close() {
127
+ if (this.prefix)
128
+ return; // only root closes the connection
129
+ if (this.backend.close)
130
+ await this.backend.close();
131
+ SSICache.__shared = undefined;
132
+ }
133
+ }
134
+ exports.SSICache = SSICache;
@@ -0,0 +1,15 @@
1
+ import type { CacheBackend } from '../types';
2
+ export declare class MemoryCacheBackend implements CacheBackend {
3
+ private store;
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
+ mget<T = unknown>(keys: string[]): Promise<(T | null)[]>;
8
+ mset<T = unknown>(entries: Array<{
9
+ key: string;
10
+ value: T;
11
+ ttlSec: number;
12
+ }>): Promise<void>;
13
+ incrby(key: string, by?: number, ttlSec?: number): Promise<number>;
14
+ ttl(key: string): Promise<number | null>;
15
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryCacheBackend = void 0;
4
+ class MemoryCacheBackend {
5
+ constructor() {
6
+ this.store = new Map();
7
+ }
8
+ async get(key) {
9
+ const it = this.store.get(key);
10
+ if (!it)
11
+ return null;
12
+ if (Date.now() > it.exp) {
13
+ this.store.delete(key);
14
+ return null;
15
+ }
16
+ return it.v;
17
+ }
18
+ async set(key, value, ttlSec) {
19
+ this.store.set(key, { v: value, exp: Date.now() + ttlSec * 1000 });
20
+ }
21
+ async del(key) {
22
+ this.store.delete(key);
23
+ }
24
+ async mget(keys) {
25
+ return Promise.all(keys.map((k) => this.get(k)));
26
+ }
27
+ async mset(entries) {
28
+ for (const e of entries) {
29
+ await this.set(e.key, e.value, e.ttlSec);
30
+ }
31
+ }
32
+ async incrby(key, by = 1, ttlSec) {
33
+ const cur = (await this.get(key)) ?? 0;
34
+ const next = cur + by;
35
+ await this.set(key, next, ttlSec ?? 60);
36
+ return next;
37
+ }
38
+ async ttl(key) {
39
+ const it = this.store.get(key);
40
+ if (!it)
41
+ return null;
42
+ const ms = it.exp - Date.now();
43
+ return ms > 0 ? Math.ceil(ms / 1000) : null;
44
+ }
45
+ }
46
+ exports.MemoryCacheBackend = MemoryCacheBackend;
@@ -0,0 +1,27 @@
1
+ import type { CacheBackend } from '../types';
2
+ export declare class RedisCacheBackend implements CacheBackend {
3
+ private client;
4
+ constructor(opts: {
5
+ url?: string;
6
+ host?: string;
7
+ port?: number;
8
+ user?: string;
9
+ password?: string;
10
+ tls?: boolean;
11
+ });
12
+ private ensure;
13
+ get<T = unknown>(key: string): Promise<T | null>;
14
+ set<T = unknown>(key: string, value: T, ttlSec: number): Promise<void>;
15
+ del(key: string): Promise<void>;
16
+ mget<T = unknown>(keys: string[]): Promise<(T | null)[]>;
17
+ mset<T = unknown>(entries: Array<{
18
+ key: string;
19
+ value: T;
20
+ ttlSec: number;
21
+ }>): Promise<void>;
22
+ incrby(key: string, by?: number, ttlSec?: number): Promise<number>;
23
+ ttl(key: string): Promise<number | null>;
24
+ close(): Promise<void>;
25
+ tryLock(key: string, ttlMs: number, token: string): Promise<boolean>;
26
+ unlock(key: string, token: string): Promise<void>;
27
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RedisCacheBackend = void 0;
4
+ const ioredis_1 = require("ioredis");
5
+ class RedisCacheBackend {
6
+ constructor(opts) {
7
+ if (opts.url) {
8
+ this.client = new ioredis_1.Redis(opts.url, { lazyConnect: true });
9
+ }
10
+ else {
11
+ this.client = new ioredis_1.Redis({
12
+ host: opts.host ?? 'localhost',
13
+ port: opts.port ?? 6379,
14
+ username: opts.user,
15
+ password: opts.password,
16
+ tls: opts.tls ? {} : undefined,
17
+ lazyConnect: true,
18
+ });
19
+ }
20
+ }
21
+ async ensure() {
22
+ if (this.client.status === 'wait')
23
+ await this.client.connect();
24
+ }
25
+ async get(key) {
26
+ await this.ensure();
27
+ const s = await this.client.get(key);
28
+ return s ? JSON.parse(s) : null;
29
+ }
30
+ async set(key, value, ttlSec) {
31
+ await this.ensure();
32
+ await this.client.set(key, JSON.stringify(value), 'EX', ttlSec);
33
+ }
34
+ async del(key) {
35
+ await this.ensure();
36
+ await this.client.del(key);
37
+ }
38
+ async mget(keys) {
39
+ await this.ensure();
40
+ if (!keys.length)
41
+ return [];
42
+ const res = await this.client.mget(...keys);
43
+ return res.map((s) => (s ? JSON.parse(s) : null));
44
+ }
45
+ async mset(entries) {
46
+ await this.ensure();
47
+ // Use pipeline to preserve per-key TTLs
48
+ const p = this.client.pipeline();
49
+ for (const e of entries) {
50
+ p.set(e.key, JSON.stringify(e.value), 'EX', e.ttlSec);
51
+ }
52
+ await p.exec();
53
+ }
54
+ async incrby(key, by = 1, ttlSec) {
55
+ await this.ensure();
56
+ const p = this.client.pipeline();
57
+ p.incrby(key, by);
58
+ if (ttlSec)
59
+ p.expire(key, ttlSec);
60
+ const results = await p.exec();
61
+ if (!results || results.length === 0) {
62
+ throw new Error('Pipeline exec failed');
63
+ }
64
+ const [error, val] = results[0];
65
+ if (error) {
66
+ throw error;
67
+ }
68
+ return val;
69
+ }
70
+ async ttl(key) {
71
+ await this.ensure();
72
+ const t = await this.client.ttl(key);
73
+ return t >= 0 ? t : null;
74
+ }
75
+ async close() {
76
+ await this.client.quit();
77
+ }
78
+ // Simple locks (SET NX PX)
79
+ async tryLock(key, ttlMs, token) {
80
+ await this.ensure();
81
+ const r = await this.client.set(key, token, 'PX', ttlMs, 'NX');
82
+ return r === 'OK';
83
+ }
84
+ async unlock(key, token) {
85
+ await this.ensure();
86
+ // Lua compare-and-del
87
+ const lua = `
88
+ if redis.call("get", KEYS[1]) == ARGV[1] then
89
+ return redis.call("del", KEYS[1])
90
+ else return 0 end
91
+ `;
92
+ await this.client.eval(lua, 1, key, token);
93
+ }
94
+ }
95
+ exports.RedisCacheBackend = RedisCacheBackend;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Recommended default TTLs for cache operations
3
+ */
4
+ export declare const TTL_SHORT = 60;
5
+ export declare const TTL_DEFAULT = 300;
6
+ export declare const TTL_LONG = 3600;
7
+ export declare const TTL_JWKS = 43200;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TTL_JWKS = exports.TTL_LONG = exports.TTL_DEFAULT = exports.TTL_SHORT = void 0;
4
+ /**
5
+ * Recommended default TTLs for cache operations
6
+ */
7
+ exports.TTL_SHORT = 60; // rate-limit buckets, nonces
8
+ exports.TTL_DEFAULT = 300; // API responses
9
+ exports.TTL_LONG = 3600; // discovery docs
10
+ exports.TTL_JWKS = 43200; // 12h; rotate if kid miss
@@ -0,0 +1,27 @@
1
+ export type CacheBackendType = 'memory' | 'redis';
2
+ export interface CacheInitOpts {
3
+ backend?: CacheBackendType;
4
+ container: string;
5
+ url?: string;
6
+ host?: string;
7
+ port?: number;
8
+ user?: string;
9
+ password?: string;
10
+ tls?: boolean;
11
+ }
12
+ export interface CacheBackend {
13
+ get<T = unknown>(key: string): Promise<T | null>;
14
+ set<T = unknown>(key: string, value: T, ttlSec: number): Promise<void>;
15
+ del(key: string): Promise<void>;
16
+ mget<T = unknown>(keys: string[]): Promise<(T | null)[]>;
17
+ mset<T = unknown>(entries: Array<{
18
+ key: string;
19
+ value: T;
20
+ ttlSec: number;
21
+ }>): Promise<void>;
22
+ incrby(key: string, by?: number, ttlSec?: number): Promise<number>;
23
+ ttl(key: string): Promise<number | null>;
24
+ close?(): Promise<void>;
25
+ tryLock?(key: string, ttlMs: number, token: string): Promise<boolean>;
26
+ unlock?(key: string, token: string): Promise<void>;
27
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export { SessionClient } from './session/SessionClient';
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SessionClient = void 0;
4
+ // Browser/middleware-safe exports only
5
+ var SessionClient_1 = require("./session/SessionClient");
6
+ Object.defineProperty(exports, "SessionClient", { enumerable: true, get: function () { return SessionClient_1.SessionClient; } });
@@ -0,0 +1,24 @@
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 getSessionClient(baseUrl?: string): SessionClient;
11
+ isLoggedIn(): Promise<boolean>;
12
+ warmup(): void;
13
+ getTtl(): Promise<number | null>;
14
+ get(claimName: string): Promise<unknown>;
15
+ /**
16
+ * Get a specific claim from the session.
17
+ * Alias for `get()` method for consistency with SessionManager.
18
+ */
19
+ getClaim(claimName: string): Promise<unknown>;
20
+ getAll(): Promise<unknown | null>;
21
+ private withSession;
22
+ private loadClaims;
23
+ }
24
+ export default SessionClient;
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SessionClient = void 0;
4
+ class SessionClient {
5
+ static normalizeBaseUrl(baseUrl) {
6
+ if (!baseUrl) {
7
+ return "";
8
+ }
9
+ try {
10
+ const url = new URL(baseUrl);
11
+ // Remove trailing slash and default ports
12
+ url.pathname = url.pathname.replace(/\/$/, "");
13
+ if ((url.protocol === "https:" && url.port === "443") || (url.protocol === "http:" && url.port === "80")) {
14
+ url.port = "";
15
+ }
16
+ return url.toString().replace(/\/$/, "");
17
+ }
18
+ catch {
19
+ return baseUrl;
20
+ }
21
+ }
22
+ constructor(baseUrl, cookieHeader) {
23
+ this.cookieHeader = cookieHeader;
24
+ this.claims = null;
25
+ this.ttl = null;
26
+ const resolvedBaseUrl = baseUrl ?? process.env.NEXT_PUBLIC_BASE_URL ?? "";
27
+ this.baseUrl = SessionClient.normalizeBaseUrl(resolvedBaseUrl);
28
+ if (!this.baseUrl || !this.baseUrl.startsWith("http://") && !this.baseUrl.startsWith("https://")) {
29
+ console.error(`You must set baseUrl to SessionClient or you must set env variable NEXT_PUBLIC_BASE_URL. Incorrect value \`${resolvedBaseUrl}\``);
30
+ }
31
+ this.initPromise = this.loadClaims();
32
+ }
33
+ static getSessionClient(baseUrl) {
34
+ const resolvedBaseUrl = baseUrl ?? process.env.NEXT_PUBLIC_BASE_URL ?? "";
35
+ const normalizedBaseUrl = SessionClient.normalizeBaseUrl(resolvedBaseUrl);
36
+ if (!normalizedBaseUrl || !normalizedBaseUrl.startsWith("http://") && !normalizedBaseUrl.startsWith("https://")) {
37
+ console.error(`You must set baseUrl to SessionClient or you must set env variable NEXT_PUBLIC_BASE_URL. Incorrect value \`${resolvedBaseUrl}\``);
38
+ }
39
+ if (!SessionClient.instances.has(normalizedBaseUrl)) {
40
+ SessionClient.instances.set(normalizedBaseUrl, new SessionClient(baseUrl));
41
+ }
42
+ return SessionClient.instances.get(normalizedBaseUrl);
43
+ }
44
+ async isLoggedIn() {
45
+ await this.initPromise;
46
+ return this.claims != null;
47
+ }
48
+ // Non-awaiting stub to ensure initialization happens without blocking
49
+ warmup() {
50
+ void this.initPromise;
51
+ }
52
+ async getTtl() {
53
+ await this.initPromise;
54
+ return this.ttl;
55
+ }
56
+ async get(claimName) {
57
+ await this.initPromise;
58
+ if (this.claims && typeof this.claims === "object") {
59
+ const record = this.claims;
60
+ return record[claimName];
61
+ }
62
+ return undefined;
63
+ }
64
+ /**
65
+ * Get a specific claim from the session.
66
+ * Alias for `get()` method for consistency with SessionManager.
67
+ */
68
+ async getClaim(claimName) {
69
+ return this.get(claimName);
70
+ }
71
+ async getAll() {
72
+ await this.initPromise;
73
+ return this.claims;
74
+ }
75
+ async withSession(init = {}) {
76
+ if (this.cookieHeader) {
77
+ const headers = new Headers(init.headers ?? {});
78
+ if (!headers.has("Cookie")) {
79
+ headers.set("Cookie", this.cookieHeader);
80
+ }
81
+ return {
82
+ ...init,
83
+ headers,
84
+ };
85
+ }
86
+ if (typeof window !== "undefined") {
87
+ return init;
88
+ }
89
+ 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
92
+ const { cookies } = await import("next/headers");
93
+ const cookieStore = await cookies();
94
+ const serializedCookies = cookieStore
95
+ .getAll()
96
+ .map((cookie) => `${cookie.name}=${cookie.value}`)
97
+ .join("; ");
98
+ if (!serializedCookies) {
99
+ return init;
100
+ }
101
+ const headers = new Headers(init.headers ?? {});
102
+ if (!headers.has("Cookie")) {
103
+ headers.set("Cookie", serializedCookies);
104
+ }
105
+ return {
106
+ ...init,
107
+ headers,
108
+ };
109
+ }
110
+ catch {
111
+ return init;
112
+ }
113
+ }
114
+ async loadClaims() {
115
+ try {
116
+ const url = new URL("/api/v1/auth/session", this.baseUrl).toString();
117
+ const response = await fetch(url, await this.withSession({
118
+ method: "GET",
119
+ headers: { accept: "application/json" },
120
+ credentials: "include",
121
+ }));
122
+ if (!response.ok) {
123
+ this.claims = null;
124
+ this.ttl = null;
125
+ return;
126
+ }
127
+ const data = (await response.json());
128
+ if (data.ok) {
129
+ this.claims = data.claims ?? null;
130
+ this.ttl = typeof data.ttl_seconds === "number" ? data.ttl_seconds : null;
131
+ }
132
+ else {
133
+ this.claims = null;
134
+ this.ttl = null;
135
+ }
136
+ }
137
+ catch (_err) {
138
+ this.claims = null;
139
+ this.ttl = null;
140
+ }
141
+ }
142
+ }
143
+ exports.SessionClient = SessionClient;
144
+ SessionClient.instances = new Map();
145
+ exports.default = SessionClient;
package/lib/index.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export * from './auth.server';
2
+ export * from './stateStore';
3
+ export * from './storage/SSIStorage';
4
+ export * from './storage/types';
5
+ export * from './session/SessionManager';
6
+ export { SessionClient } from './frontend/session/SessionClient';
7
+ export * from './cache/SSICache';
8
+ export * from './cache/types';
9
+ export * from './cache/constants';
10
+ export * from './SSIProjectApi';
11
+ export { SSISubscribedFeatureApi } from './SSISubscribedFeatureApi';
12
+ export { SSISubscribedLimitApi } from './SSISubscribedLimitApi';
13
+ export { SSISubscribedPlanApi } from './SSISubscribedPlanApi';
14
+ export * from './SubscribedPlanManager';
15
+ export * from './UsageApi';
package/lib/index.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.SSISubscribedPlanApi = exports.SSISubscribedLimitApi = exports.SSISubscribedFeatureApi = exports.SessionClient = void 0;
18
+ __exportStar(require("./auth.server"), exports);
19
+ __exportStar(require("./stateStore"), exports);
20
+ __exportStar(require("./storage/SSIStorage"), exports);
21
+ __exportStar(require("./storage/types"), exports);
22
+ __exportStar(require("./session/SessionManager"), exports);
23
+ var SessionClient_1 = require("./frontend/session/SessionClient");
24
+ Object.defineProperty(exports, "SessionClient", { enumerable: true, get: function () { return SessionClient_1.SessionClient; } });
25
+ __exportStar(require("./cache/SSICache"), exports);
26
+ __exportStar(require("./cache/types"), exports);
27
+ __exportStar(require("./cache/constants"), exports);
28
+ // Export all types and classes from SSIProjectApi (includes shared JSON:API types)
29
+ __exportStar(require("./SSIProjectApi"), exports);
30
+ // Export only the unique classes from subscribed APIs (types are already exported from SSIProjectApi)
31
+ var SSISubscribedFeatureApi_1 = require("./SSISubscribedFeatureApi");
32
+ Object.defineProperty(exports, "SSISubscribedFeatureApi", { enumerable: true, get: function () { return SSISubscribedFeatureApi_1.SSISubscribedFeatureApi; } });
33
+ var SSISubscribedLimitApi_1 = require("./SSISubscribedLimitApi");
34
+ Object.defineProperty(exports, "SSISubscribedLimitApi", { enumerable: true, get: function () { return SSISubscribedLimitApi_1.SSISubscribedLimitApi; } });
35
+ var SSISubscribedPlanApi_1 = require("./SSISubscribedPlanApi");
36
+ Object.defineProperty(exports, "SSISubscribedPlanApi", { enumerable: true, get: function () { return SSISubscribedPlanApi_1.SSISubscribedPlanApi; } });
37
+ __exportStar(require("./SubscribedPlanManager"), exports);
38
+ __exportStar(require("./UsageApi"), exports);
@@ -0,0 +1,11 @@
1
+ import type { SessionClientInit, SessionSnapshot, TokenBundle } from './types';
2
+ export declare class SessionClient {
3
+ private readonly init;
4
+ constructor(init: SessionClientInit);
5
+ private k;
6
+ getAll(sessionId: string): Promise<SessionSnapshot>;
7
+ setTokens(sessionId: string, t: TokenBundle): Promise<void>;
8
+ getTtl(_sessionId: string): Promise<number | null>;
9
+ clear(sessionId: string): Promise<void>;
10
+ maybeRefresh(_sessionId: string): Promise<boolean>;
11
+ }
@@ -0,0 +1,47 @@
1
+ const ACCESS = 'access';
2
+ const ID = 'id';
3
+ const REFRESH = 'refresh';
4
+ const CLAIMS = 'claims';
5
+ const DEFAULT_REFRESH_TTL_SEC = 7 * 24 * 60 * 60;
6
+ export class SessionClient {
7
+ constructor(init) {
8
+ this.init = init;
9
+ }
10
+ k(sessionId, suffix) {
11
+ return `${sessionId}:${suffix}`;
12
+ }
13
+ async getAll(sessionId) {
14
+ const claims = await this.init.store.get(this.k(sessionId, CLAIMS));
15
+ const access_token = await this.init.store.get(this.k(sessionId, ACCESS));
16
+ const id_token = await this.init.store.get(this.k(sessionId, ID));
17
+ const refresh_token = await this.init.store.get(this.k(sessionId, REFRESH));
18
+ return { claims, access_token, id_token, refresh_token };
19
+ }
20
+ async setTokens(sessionId, t) {
21
+ const { store } = this.init;
22
+ await store.set(this.k(sessionId, ACCESS), t.access_token, t.ttlSec);
23
+ await store.set(this.k(sessionId, ID), t.id_token, t.ttlSec);
24
+ if (t.refresh_token) {
25
+ const refreshTtl = this.init.refresh?.defaultTtlSec ?? DEFAULT_REFRESH_TTL_SEC;
26
+ await store.set(this.k(sessionId, REFRESH), t.refresh_token, refreshTtl);
27
+ }
28
+ // No JWT verification. Clear cached claims to force re-derive later (future step).
29
+ await store.del(this.k(sessionId, CLAIMS));
30
+ }
31
+ async getTtl(_sessionId) {
32
+ // Will compute from JWT exp later; parity with original means null for now.
33
+ return null;
34
+ }
35
+ async clear(sessionId) {
36
+ await Promise.all([
37
+ this.init.store.del(this.k(sessionId, ACCESS)),
38
+ this.init.store.del(this.k(sessionId, ID)),
39
+ this.init.store.del(this.k(sessionId, REFRESH)),
40
+ this.init.store.del(this.k(sessionId, CLAIMS)),
41
+ ]);
42
+ }
43
+ async maybeRefresh(_sessionId) {
44
+ // Stub; parity with original (no auto-refresh yet).
45
+ return false;
46
+ }
47
+ }
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './SessionClient';
3
+ export * from './stores';