@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.
- package/README.md +1 -0
- package/lib/SSIProject.d.ts +343 -0
- package/lib/SSIProject.js +429 -0
- package/lib/SSIProjectApi.d.ts +384 -0
- package/lib/SSIProjectApi.js +534 -0
- package/lib/SSISubscribedFeatureApi.d.ts +387 -0
- package/lib/SSISubscribedFeatureApi.js +511 -0
- package/lib/SSISubscribedLimitApi.d.ts +384 -0
- package/lib/SSISubscribedLimitApi.js +534 -0
- package/lib/SSISubscribedPlanApi.d.ts +384 -0
- package/lib/SSISubscribedPlanApi.js +537 -0
- package/lib/SubscribedPlanManager.d.ts +380 -0
- package/lib/SubscribedPlanManager.js +288 -0
- package/lib/UsageApi.d.ts +128 -0
- package/lib/UsageApi.js +224 -0
- package/lib/auth.server.d.ts +192 -0
- package/lib/auth.server.js +579 -0
- package/lib/cache/SSICache.d.ts +40 -0
- package/lib/cache/SSICache.js +134 -0
- package/lib/cache/backends/MemoryCacheBackend.d.ts +15 -0
- package/lib/cache/backends/MemoryCacheBackend.js +46 -0
- package/lib/cache/backends/RedisCacheBackend.d.ts +27 -0
- package/lib/cache/backends/RedisCacheBackend.js +95 -0
- package/lib/cache/constants.d.ts +7 -0
- package/lib/cache/constants.js +10 -0
- package/lib/cache/types.d.ts +27 -0
- package/lib/cache/types.js +2 -0
- package/lib/frontend/index.d.ts +1 -0
- package/lib/frontend/index.js +6 -0
- package/lib/frontend/session/SessionClient.d.ts +24 -0
- package/lib/frontend/session/SessionClient.js +145 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.js +38 -0
- package/lib/lib/session/SessionClient.d.ts +11 -0
- package/lib/lib/session/SessionClient.js +47 -0
- package/lib/lib/session/index.d.ts +3 -0
- package/lib/lib/session/index.js +3 -0
- package/lib/lib/session/stores/MemoryStore.d.ts +7 -0
- package/lib/lib/session/stores/MemoryStore.js +23 -0
- package/lib/lib/session/stores/index.d.ts +1 -0
- package/lib/lib/session/stores/index.js +1 -0
- package/lib/lib/session/types.d.ts +37 -0
- package/lib/lib/session/types.js +1 -0
- package/lib/session/SessionClient.d.ts +19 -0
- package/lib/session/SessionClient.js +132 -0
- package/lib/session/SessionManager.d.ts +139 -0
- package/lib/session/SessionManager.js +443 -0
- package/lib/stateStore.d.ts +5 -0
- package/lib/stateStore.js +9 -0
- package/lib/storage/SSIStorage.d.ts +24 -0
- package/lib/storage/SSIStorage.js +117 -0
- package/lib/storage/backends/MemoryBackend.d.ts +10 -0
- package/lib/storage/backends/MemoryBackend.js +44 -0
- package/lib/storage/backends/PostgresBackend.d.ts +24 -0
- package/lib/storage/backends/PostgresBackend.js +106 -0
- package/lib/storage/backends/RedisBackend.d.ts +19 -0
- package/lib/storage/backends/RedisBackend.js +78 -0
- package/lib/storage/types.d.ts +27 -0
- package/lib/storage/types.js +2 -0
- package/package.json +71 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresBackend = void 0;
|
|
4
|
+
const pg_1 = require("pg");
|
|
5
|
+
class PostgresBackend {
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
this.table = opts.table;
|
|
8
|
+
if (opts.url) {
|
|
9
|
+
this.client = new pg_1.Client({ connectionString: opts.url, ssl: opts.ssl ? { rejectUnauthorized: false } : undefined });
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
this.client = new pg_1.Client({
|
|
13
|
+
host: opts.host ?? 'localhost',
|
|
14
|
+
port: opts.port ?? 5432,
|
|
15
|
+
user: opts.user,
|
|
16
|
+
password: opts.password,
|
|
17
|
+
database: opts.database,
|
|
18
|
+
ssl: opts.ssl ? { rejectUnauthorized: false } : undefined,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async ensure() {
|
|
23
|
+
// One connect per process; re-use thereafter
|
|
24
|
+
// pg Client connects once and keeps pool-less connection
|
|
25
|
+
if (this.client._connected !== true) {
|
|
26
|
+
await this.client.connect();
|
|
27
|
+
this.client._connected = true;
|
|
28
|
+
// Ensure table exists (idempotent)
|
|
29
|
+
// Note: Use safe identifiers: we assume table was provided by trusted env.
|
|
30
|
+
await this.client.query(`
|
|
31
|
+
CREATE TABLE IF NOT EXISTS "${this.table}" (
|
|
32
|
+
class TEXT NOT NULL,
|
|
33
|
+
object_id TEXT NOT NULL,
|
|
34
|
+
key TEXT NOT NULL,
|
|
35
|
+
value JSONB,
|
|
36
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
37
|
+
expires_at TIMESTAMPTZ NULL,
|
|
38
|
+
PRIMARY KEY (class, object_id, key)
|
|
39
|
+
);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS "${this.table}_expires_idx" ON "${this.table}" (expires_at);
|
|
41
|
+
`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
parsePrefixedKey(prefixed) {
|
|
45
|
+
// ssi_container/[class]/[object_id]/[key] — class is "_" if omitted
|
|
46
|
+
const parts = prefixed.split('/');
|
|
47
|
+
if (parts.length < 4)
|
|
48
|
+
throw new Error(`Invalid prefixed key: ${prefixed}`);
|
|
49
|
+
const container = parts[0];
|
|
50
|
+
const cls = parts[1];
|
|
51
|
+
const objectId = parts[2];
|
|
52
|
+
const key = parts.slice(3).join('/'); // allow slashes in the tail key
|
|
53
|
+
return { container, cls, objectId, key };
|
|
54
|
+
}
|
|
55
|
+
async get(prefixedKey) {
|
|
56
|
+
await this.ensure();
|
|
57
|
+
const { cls, objectId, key } = this.parsePrefixedKey(prefixedKey);
|
|
58
|
+
const { rows } = await this.client.query(`SELECT value, expires_at FROM "${this.table}" WHERE class=$1 AND object_id=$2 AND key=$3`, [cls, objectId, key]);
|
|
59
|
+
if (rows.length === 0)
|
|
60
|
+
return null;
|
|
61
|
+
const r = rows[0];
|
|
62
|
+
if (r.expires_at && new Date(r.expires_at) < new Date()) {
|
|
63
|
+
// Expired — best-effort delete & return null
|
|
64
|
+
await this.del(prefixedKey);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return r.value;
|
|
68
|
+
}
|
|
69
|
+
async set(prefixedKey, value, ttlSeconds) {
|
|
70
|
+
await this.ensure();
|
|
71
|
+
const { cls, objectId, key } = this.parsePrefixedKey(prefixedKey);
|
|
72
|
+
const expiresAt = ttlSeconds && ttlSeconds > 0
|
|
73
|
+
? new Date(Date.now() + ttlSeconds * 1000)
|
|
74
|
+
: null;
|
|
75
|
+
await this.client.query(`INSERT INTO "${this.table}" (class, object_id, key, value, updated_at, expires_at)
|
|
76
|
+
VALUES ($1,$2,$3,$4,NOW(),$5)
|
|
77
|
+
ON CONFLICT (class, object_id, key)
|
|
78
|
+
DO UPDATE SET value=EXCLUDED.value, updated_at=NOW(), expires_at=EXCLUDED.expires_at`, [cls, objectId, key, value, expiresAt]);
|
|
79
|
+
}
|
|
80
|
+
async del(prefixedKey) {
|
|
81
|
+
await this.ensure();
|
|
82
|
+
const { cls, objectId, key } = this.parsePrefixedKey(prefixedKey);
|
|
83
|
+
await this.client.query(`DELETE FROM "${this.table}" WHERE class=$1 AND object_id=$2 AND key=$3`, [cls, objectId, key]);
|
|
84
|
+
}
|
|
85
|
+
async close() {
|
|
86
|
+
if (this.client._connected) {
|
|
87
|
+
await this.client.end();
|
|
88
|
+
this.client._connected = false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async getRemainingTtl(prefixedKey) {
|
|
92
|
+
await this.ensure();
|
|
93
|
+
const { cls, objectId, key } = this.parsePrefixedKey(prefixedKey);
|
|
94
|
+
const { rows } = await this.client.query(`SELECT expires_at FROM "${this.table}" WHERE class=$1 AND object_id=$2 AND key=$3`, [cls, objectId, key]);
|
|
95
|
+
if (rows.length === 0)
|
|
96
|
+
return null; // no such key
|
|
97
|
+
const expiresAt = rows[0].expires_at;
|
|
98
|
+
if (!expiresAt)
|
|
99
|
+
return null; // no expiry
|
|
100
|
+
const msRemaining = new Date(expiresAt).getTime() - Date.now();
|
|
101
|
+
if (msRemaining <= 0)
|
|
102
|
+
return 0; // expired
|
|
103
|
+
return Math.ceil(msRemaining / 1000);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.PostgresBackend = PostgresBackend;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Backend, KVValue } from '../types';
|
|
2
|
+
export declare class RedisBackend implements Backend {
|
|
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(key: string): Promise<KVValue | null>;
|
|
14
|
+
set(key: string, value: KVValue, ttlSeconds?: number): Promise<void>;
|
|
15
|
+
del(key: string): Promise<void>;
|
|
16
|
+
keys(prefix: string): Promise<string[]>;
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
getRemainingTtl(key: string): Promise<number | null>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RedisBackend = void 0;
|
|
4
|
+
const ioredis_1 = require("ioredis");
|
|
5
|
+
class RedisBackend {
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
if (opts.url) {
|
|
8
|
+
this.client = new ioredis_1.Redis(opts.url);
|
|
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 raw = await this.client.get(key);
|
|
28
|
+
if (raw === null)
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(raw);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return raw;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async set(key, value, ttlSeconds) {
|
|
38
|
+
await this.ensure();
|
|
39
|
+
const payload = typeof value === 'string' ? value : JSON.stringify(value);
|
|
40
|
+
if (ttlSeconds && ttlSeconds > 0) {
|
|
41
|
+
await this.client.set(key, payload, 'EX', ttlSeconds);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
await this.client.set(key, payload);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async del(key) {
|
|
48
|
+
await this.ensure();
|
|
49
|
+
await this.client.del(key);
|
|
50
|
+
}
|
|
51
|
+
async keys(prefix) {
|
|
52
|
+
await this.ensure();
|
|
53
|
+
// Use SCAN to avoid blocking (simple but effective)
|
|
54
|
+
const keys = [];
|
|
55
|
+
let cursor = '0';
|
|
56
|
+
do {
|
|
57
|
+
const [next, batch] = await this.client.scan(cursor, 'MATCH', `${prefix}*`, 'COUNT', 500);
|
|
58
|
+
cursor = next;
|
|
59
|
+
keys.push(...batch);
|
|
60
|
+
} while (cursor !== '0');
|
|
61
|
+
return keys;
|
|
62
|
+
}
|
|
63
|
+
async close() {
|
|
64
|
+
await this.client.quit();
|
|
65
|
+
}
|
|
66
|
+
async getRemainingTtl(key) {
|
|
67
|
+
await this.ensure();
|
|
68
|
+
const ms = await this.client.pttl(key);
|
|
69
|
+
if (ms === -2)
|
|
70
|
+
return null; // no such key
|
|
71
|
+
if (ms === -1)
|
|
72
|
+
return null; // no expiry
|
|
73
|
+
if (ms <= 0)
|
|
74
|
+
return 0; // expired
|
|
75
|
+
return Math.ceil(ms / 1000);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.RedisBackend = RedisBackend;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type StorageBackendType = 'memory' | 'redis' | 'postgres';
|
|
2
|
+
export interface StorageInitOpts {
|
|
3
|
+
backend?: StorageBackendType;
|
|
4
|
+
container: string;
|
|
5
|
+
host?: string;
|
|
6
|
+
port?: number;
|
|
7
|
+
user?: string;
|
|
8
|
+
password?: string;
|
|
9
|
+
database?: string;
|
|
10
|
+
ssl?: boolean;
|
|
11
|
+
url?: string;
|
|
12
|
+
}
|
|
13
|
+
export type KVValue = string | number | boolean | Record<string, unknown> | null;
|
|
14
|
+
export interface Backend {
|
|
15
|
+
get(prefixedKey: string): Promise<KVValue | null>;
|
|
16
|
+
set(prefixedKey: string, value: KVValue, ttlSeconds?: number): Promise<void>;
|
|
17
|
+
del(prefixedKey: string): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Return remaining TTL in seconds for the given key.
|
|
20
|
+
* - Returns a non-negative number if the key exists and has an expiry
|
|
21
|
+
* - Returns 0 if the key exists but is already expired (and may be deleted lazily)
|
|
22
|
+
* - Returns null if the key does not exist or has no expiry
|
|
23
|
+
*/
|
|
24
|
+
getRemainingTtl(prefixedKey: string): Promise<number | null>;
|
|
25
|
+
keys?(prefix: string): Promise<string[]>;
|
|
26
|
+
close?(): Promise<void>;
|
|
27
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@serialsubscriptions/platform-integration",
|
|
3
|
+
"version": "0.0.79",
|
|
4
|
+
"description": "Serial Subscriptions Libraries",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"browser": "./lib/frontend/index.js",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"browser": {
|
|
14
|
+
"import": "./lib/frontend/index.js",
|
|
15
|
+
"require": "./lib/frontend/index.js",
|
|
16
|
+
"types": "./lib/frontend/index.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"edge-light": {
|
|
19
|
+
"import": "./lib/frontend/index.js",
|
|
20
|
+
"require": "./lib/frontend/index.js",
|
|
21
|
+
"types": "./lib/frontend/index.d.ts"
|
|
22
|
+
},
|
|
23
|
+
"node": {
|
|
24
|
+
"import": "./lib/index.js",
|
|
25
|
+
"require": "./lib/index.js",
|
|
26
|
+
"types": "./lib/index.d.ts"
|
|
27
|
+
},
|
|
28
|
+
"import": "./lib/index.js",
|
|
29
|
+
"require": "./lib/index.js",
|
|
30
|
+
"default": "./lib/index.js",
|
|
31
|
+
"types": "./lib/index.d.ts"
|
|
32
|
+
},
|
|
33
|
+
"./auth.server": {
|
|
34
|
+
"import": "./lib/auth.server.js",
|
|
35
|
+
"require": "./lib/auth.server.js",
|
|
36
|
+
"default": "./lib/auth.server.js",
|
|
37
|
+
"types": "./lib/auth.server.d.ts"
|
|
38
|
+
},
|
|
39
|
+
"./stateStore": {
|
|
40
|
+
"import": "./lib/stateStore.js",
|
|
41
|
+
"require": "./lib/stateStore.js",
|
|
42
|
+
"default": "./lib/stateStore.js",
|
|
43
|
+
"types": "./lib/stateStore.d.ts"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"lib/**",
|
|
48
|
+
"README.md"
|
|
49
|
+
],
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsc"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@auth0/nextjs-auth0": "^3.5.0",
|
|
55
|
+
"ioredis": "^5.4.1",
|
|
56
|
+
"jose": "^5.9.3",
|
|
57
|
+
"node-cache": "^5.1.2",
|
|
58
|
+
"node-fetch": "^3.3.2",
|
|
59
|
+
"pg": "^8.16.3"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/node": "^22.7.4",
|
|
63
|
+
"@types/pg": "^8.15.6",
|
|
64
|
+
"next": "^15.0.0",
|
|
65
|
+
"typescript": "^5.6.2"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"next": "^15.0.0"
|
|
69
|
+
},
|
|
70
|
+
"license": "MIT"
|
|
71
|
+
}
|