@lti-tool/postgresql 1.0.0 → 1.0.1
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/CHANGELOG.md +6 -0
- package/README.md +294 -0
- package/dist/cacheConfig.d.ts +11 -0
- package/dist/cacheConfig.d.ts.map +1 -0
- package/dist/cacheConfig.js +14 -0
- package/dist/db/schema/clients.schema.d.ts +133 -0
- package/dist/db/schema/clients.schema.d.ts.map +1 -0
- package/dist/db/schema/clients.schema.js +13 -0
- package/dist/db/schema/deployments.schema.d.ts +97 -0
- package/dist/db/schema/deployments.schema.d.ts.map +1 -0
- package/dist/db/schema/deployments.schema.js +14 -0
- package/dist/db/schema/index.d.ts +6 -0
- package/dist/db/schema/index.d.ts.map +1 -0
- package/dist/db/schema/index.js +5 -0
- package/dist/db/schema/nonces.schema.d.ts +44 -0
- package/dist/db/schema/nonces.schema.d.ts.map +1 -0
- package/dist/db/schema/nonces.schema.js +5 -0
- package/dist/db/schema/registrationSessions.schema.d.ts +62 -0
- package/dist/db/schema/registrationSessions.schema.d.ts.map +1 -0
- package/dist/db/schema/registrationSessions.schema.js +8 -0
- package/dist/db/schema/sessions.schema.d.ts +62 -0
- package/dist/db/schema/sessions.schema.d.ts.map +1 -0
- package/dist/db/schema/sessions.schema.js +6 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/interfaces/postgresStorageConfig.d.ts +35 -0
- package/dist/interfaces/postgresStorageConfig.d.ts.map +1 -0
- package/dist/interfaces/postgresStorageConfig.js +1 -0
- package/dist/postgresStorage.d.ts +53 -0
- package/dist/postgresStorage.d.ts.map +1 -0
- package/dist/postgresStorage.js +443 -0
- package/package.json +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { LTIDynamicRegistrationSession } from '@lti-tool/core';
|
|
2
|
+
export declare const registrationSessionsTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
3
|
+
name: "registration_sessions";
|
|
4
|
+
schema: undefined;
|
|
5
|
+
columns: {
|
|
6
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
7
|
+
name: "id";
|
|
8
|
+
tableName: "registration_sessions";
|
|
9
|
+
dataType: "string";
|
|
10
|
+
columnType: "PgUUID";
|
|
11
|
+
data: string;
|
|
12
|
+
driverParam: string;
|
|
13
|
+
notNull: true;
|
|
14
|
+
hasDefault: true;
|
|
15
|
+
isPrimaryKey: true;
|
|
16
|
+
isAutoincrement: false;
|
|
17
|
+
hasRuntimeDefault: false;
|
|
18
|
+
enumValues: undefined;
|
|
19
|
+
baseColumn: never;
|
|
20
|
+
identity: undefined;
|
|
21
|
+
generated: undefined;
|
|
22
|
+
}, {}, {}>;
|
|
23
|
+
data: import("drizzle-orm/pg-core").PgColumn<{
|
|
24
|
+
name: "data";
|
|
25
|
+
tableName: "registration_sessions";
|
|
26
|
+
dataType: "json";
|
|
27
|
+
columnType: "PgJsonb";
|
|
28
|
+
data: Omit<LTIDynamicRegistrationSession, "sessionId">;
|
|
29
|
+
driverParam: unknown;
|
|
30
|
+
notNull: true;
|
|
31
|
+
hasDefault: false;
|
|
32
|
+
isPrimaryKey: false;
|
|
33
|
+
isAutoincrement: false;
|
|
34
|
+
hasRuntimeDefault: false;
|
|
35
|
+
enumValues: undefined;
|
|
36
|
+
baseColumn: never;
|
|
37
|
+
identity: undefined;
|
|
38
|
+
generated: undefined;
|
|
39
|
+
}, {}, {
|
|
40
|
+
$type: Omit<LTIDynamicRegistrationSession, "sessionId">;
|
|
41
|
+
}>;
|
|
42
|
+
expiresAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
43
|
+
name: "expires_at";
|
|
44
|
+
tableName: "registration_sessions";
|
|
45
|
+
dataType: "date";
|
|
46
|
+
columnType: "PgTimestamp";
|
|
47
|
+
data: Date;
|
|
48
|
+
driverParam: string;
|
|
49
|
+
notNull: true;
|
|
50
|
+
hasDefault: false;
|
|
51
|
+
isPrimaryKey: false;
|
|
52
|
+
isAutoincrement: false;
|
|
53
|
+
hasRuntimeDefault: false;
|
|
54
|
+
enumValues: undefined;
|
|
55
|
+
baseColumn: never;
|
|
56
|
+
identity: undefined;
|
|
57
|
+
generated: undefined;
|
|
58
|
+
}, {}, {}>;
|
|
59
|
+
};
|
|
60
|
+
dialect: "pg";
|
|
61
|
+
}>;
|
|
62
|
+
//# sourceMappingURL=registrationSessions.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registrationSessions.schema.d.ts","sourceRoot":"","sources":["../../../src/db/schema/registrationSessions.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAGpE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUrC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { index, jsonb, pgTable, timestamp, uuid } from 'drizzle-orm/pg-core';
|
|
2
|
+
export const registrationSessionsTable = pgTable('registration_sessions', {
|
|
3
|
+
id: uuid('id').primaryKey().defaultRandom(),
|
|
4
|
+
data: jsonb('data')
|
|
5
|
+
.$type()
|
|
6
|
+
.notNull(),
|
|
7
|
+
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
|
8
|
+
}, (table) => [index('reg_sessions_expires_at_idx').on(table.expiresAt)]);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { LTISession } from '@lti-tool/core';
|
|
2
|
+
export declare const sessionsTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
3
|
+
name: "sessions";
|
|
4
|
+
schema: undefined;
|
|
5
|
+
columns: {
|
|
6
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
7
|
+
name: "id";
|
|
8
|
+
tableName: "sessions";
|
|
9
|
+
dataType: "string";
|
|
10
|
+
columnType: "PgUUID";
|
|
11
|
+
data: string;
|
|
12
|
+
driverParam: string;
|
|
13
|
+
notNull: true;
|
|
14
|
+
hasDefault: true;
|
|
15
|
+
isPrimaryKey: true;
|
|
16
|
+
isAutoincrement: false;
|
|
17
|
+
hasRuntimeDefault: false;
|
|
18
|
+
enumValues: undefined;
|
|
19
|
+
baseColumn: never;
|
|
20
|
+
identity: undefined;
|
|
21
|
+
generated: undefined;
|
|
22
|
+
}, {}, {}>;
|
|
23
|
+
data: import("drizzle-orm/pg-core").PgColumn<{
|
|
24
|
+
name: "data";
|
|
25
|
+
tableName: "sessions";
|
|
26
|
+
dataType: "json";
|
|
27
|
+
columnType: "PgJsonb";
|
|
28
|
+
data: Omit<LTISession, "id">;
|
|
29
|
+
driverParam: unknown;
|
|
30
|
+
notNull: true;
|
|
31
|
+
hasDefault: false;
|
|
32
|
+
isPrimaryKey: false;
|
|
33
|
+
isAutoincrement: false;
|
|
34
|
+
hasRuntimeDefault: false;
|
|
35
|
+
enumValues: undefined;
|
|
36
|
+
baseColumn: never;
|
|
37
|
+
identity: undefined;
|
|
38
|
+
generated: undefined;
|
|
39
|
+
}, {}, {
|
|
40
|
+
$type: Omit<LTISession, "id">;
|
|
41
|
+
}>;
|
|
42
|
+
expiresAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
43
|
+
name: "expires_at";
|
|
44
|
+
tableName: "sessions";
|
|
45
|
+
dataType: "date";
|
|
46
|
+
columnType: "PgTimestamp";
|
|
47
|
+
data: Date;
|
|
48
|
+
driverParam: string;
|
|
49
|
+
notNull: true;
|
|
50
|
+
hasDefault: false;
|
|
51
|
+
isPrimaryKey: false;
|
|
52
|
+
isAutoincrement: false;
|
|
53
|
+
hasRuntimeDefault: false;
|
|
54
|
+
enumValues: undefined;
|
|
55
|
+
baseColumn: never;
|
|
56
|
+
identity: undefined;
|
|
57
|
+
generated: undefined;
|
|
58
|
+
}, {}, {}>;
|
|
59
|
+
};
|
|
60
|
+
dialect: "pg";
|
|
61
|
+
}>;
|
|
62
|
+
//# sourceMappingURL=sessions.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.schema.d.ts","sourceRoot":"","sources":["../../../src/db/schema/sessions.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQzB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { index, jsonb, pgTable, timestamp, uuid } from 'drizzle-orm/pg-core';
|
|
2
|
+
export const sessionsTable = pgTable('sessions', {
|
|
3
|
+
id: uuid('id').primaryKey().defaultRandom(),
|
|
4
|
+
data: jsonb('data').$type().notNull(),
|
|
5
|
+
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
|
6
|
+
}, (table) => [index('sessions_expires_at_idx').on(table.expiresAt)]);
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PostgresStorage } from './postgresStorage.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Logger } from 'pino';
|
|
2
|
+
export interface PostgresStorageConfig {
|
|
3
|
+
logger?: Logger;
|
|
4
|
+
/**
|
|
5
|
+
* PostgreSQL connection URL in format: postgresql://user:password@host:port/database
|
|
6
|
+
* Compatible with DATABASE_URL environment variable used by most ORMs
|
|
7
|
+
*/
|
|
8
|
+
connectionUrl: string;
|
|
9
|
+
/**
|
|
10
|
+
* Optional postgres.js connection options
|
|
11
|
+
*/
|
|
12
|
+
poolOptions?: {
|
|
13
|
+
/**
|
|
14
|
+
* Maximum number of connections in the pool.
|
|
15
|
+
* Defaults to 1 in serverless environments, 10 otherwise.
|
|
16
|
+
*
|
|
17
|
+
* Recommended values:
|
|
18
|
+
* - Serverless (Lambda, Cloud Functions): 1
|
|
19
|
+
* - Low traffic servers: 5-10
|
|
20
|
+
* - Medium traffic servers: 10-20
|
|
21
|
+
* - High traffic servers: 20-50
|
|
22
|
+
*/
|
|
23
|
+
max?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Idle timeout in seconds before a connection is closed.
|
|
26
|
+
* Defaults to 20 seconds.
|
|
27
|
+
*/
|
|
28
|
+
idleTimeout?: number;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Nonce expiration time in seconds (defaults to 600 = 10 minutes)
|
|
32
|
+
*/
|
|
33
|
+
nonceExpirationSeconds?: number;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=postgresStorageConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgresStorageConfig.d.ts","sourceRoot":"","sources":["../../src/interfaces/postgresStorageConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,WAAW,CAAC,EAAE;QACZ;;;;;;;;;WASG;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;QACb;;;WAGG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type LTIClient, type LTIDeployment, type LTIDynamicRegistrationSession, type LTILaunchConfig, type LTISession, type LTIStorage } from '@lti-tool/core';
|
|
2
|
+
import type { PostgresStorageConfig } from './interfaces/postgresStorageConfig.js';
|
|
3
|
+
/**
|
|
4
|
+
* PostgreSQL implementation of LTI storage interface.
|
|
5
|
+
*
|
|
6
|
+
* Stores clients, deployments, sessions, and nonces in PostgreSQL with LRU caching.
|
|
7
|
+
* Uses Drizzle ORM for type-safe database operations.
|
|
8
|
+
*/
|
|
9
|
+
export declare class PostgresStorage implements LTIStorage {
|
|
10
|
+
private logger;
|
|
11
|
+
private db;
|
|
12
|
+
private sql;
|
|
13
|
+
private nonceExpirationSeconds;
|
|
14
|
+
constructor(config: PostgresStorageConfig);
|
|
15
|
+
listClients(): Promise<Omit<LTIClient, 'deployments'>[]>;
|
|
16
|
+
getClientById(clientId: string): Promise<LTIClient | undefined>;
|
|
17
|
+
addClient(client: Omit<LTIClient, 'id'>): Promise<string>;
|
|
18
|
+
updateClient(clientId: string, client: Partial<Omit<LTIClient, 'id'>>): Promise<void>;
|
|
19
|
+
deleteClient(clientId: string): Promise<void>;
|
|
20
|
+
private updateClientLaunchConfigs;
|
|
21
|
+
listDeployments(clientId: string): Promise<LTIDeployment[]>;
|
|
22
|
+
getDeployment(clientId: string, deploymentId: string): Promise<LTIDeployment | undefined>;
|
|
23
|
+
addDeployment(clientId: string, deployment: Omit<LTIDeployment, 'id'>): Promise<string>;
|
|
24
|
+
updateDeployment(clientId: string, deploymentId: string, deployment: Partial<LTIDeployment>): Promise<void>;
|
|
25
|
+
deleteDeployment(clientId: string, deploymentId: string): Promise<void>;
|
|
26
|
+
storeNonce(nonce: string, expiresAt: Date): Promise<void>;
|
|
27
|
+
validateNonce(nonce: string): Promise<boolean>;
|
|
28
|
+
getSession(sessionId: string): Promise<LTISession | undefined>;
|
|
29
|
+
addSession(session: LTISession): Promise<string>;
|
|
30
|
+
getLaunchConfig(iss: string, clientId: string, deploymentId: string): Promise<LTILaunchConfig | undefined>;
|
|
31
|
+
saveLaunchConfig(launchConfig: LTILaunchConfig): Promise<void>;
|
|
32
|
+
setRegistrationSession(sessionId: string, session: LTIDynamicRegistrationSession): Promise<void>;
|
|
33
|
+
getRegistrationSession(sessionId: string): Promise<LTIDynamicRegistrationSession | undefined>;
|
|
34
|
+
deleteRegistrationSession(sessionId: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Clean up expired nonces, sessions, and registration sessions.
|
|
37
|
+
* Should be called periodically (e.g., every 30 minutes via EventBridge).
|
|
38
|
+
*
|
|
39
|
+
* @returns Object with counts of deleted items
|
|
40
|
+
*/
|
|
41
|
+
cleanup(): Promise<{
|
|
42
|
+
noncesDeleted: number;
|
|
43
|
+
sessionsDeleted: number;
|
|
44
|
+
registrationSessionsDeleted: number;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Close the PostgreSQL connection pool.
|
|
48
|
+
* Should be called on graceful server shutdown or after tests.
|
|
49
|
+
* Not required for serverless environments (Lambda manages lifecycle).
|
|
50
|
+
*/
|
|
51
|
+
close(): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=postgresStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgresStorage.d.ts","sourceRoot":"","sources":["../src/postgresStorage.ts"],"names":[],"mappings":"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"}
|