aws-classify-server 0.1.0

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/lib/cjs/ClassDef.d.ts +6 -0
  4. package/lib/cjs/ClassDef.js +2 -0
  5. package/lib/cjs/ClassifyResponse.d.ts +6 -0
  6. package/lib/cjs/ClassifyResponse.js +11 -0
  7. package/lib/cjs/ClassifyServerless.d.ts +27 -0
  8. package/lib/cjs/ClassifyServerless.js +288 -0
  9. package/lib/cjs/SessionData.d.ts +6 -0
  10. package/lib/cjs/SessionData.js +2 -0
  11. package/lib/cjs/aws-classify-common/EndPointsLogging.d.ts +8 -0
  12. package/lib/cjs/aws-classify-common/EndPointsLogging.js +11 -0
  13. package/lib/cjs/aws-classify-common/LambdaRequest.d.ts +6 -0
  14. package/lib/cjs/aws-classify-common/LambdaRequest.js +2 -0
  15. package/lib/cjs/aws-classify-common/LambdaResponse.d.ts +6 -0
  16. package/lib/cjs/aws-classify-common/LambdaResponse.js +2 -0
  17. package/lib/cjs/aws-classify-common/index.d.ts +4 -0
  18. package/lib/cjs/aws-classify-common/index.js +7 -0
  19. package/lib/cjs/dispatch.d.ts +7 -0
  20. package/lib/cjs/dispatch.js +79 -0
  21. package/lib/cjs/index.d.ts +3 -0
  22. package/lib/cjs/index.js +12 -0
  23. package/lib/esm/ClassDef.d.ts +6 -0
  24. package/lib/esm/ClassDef.js +1 -0
  25. package/lib/esm/ClassifyResponse.d.ts +6 -0
  26. package/lib/esm/ClassifyResponse.js +7 -0
  27. package/lib/esm/ClassifyServerless.d.ts +27 -0
  28. package/lib/esm/ClassifyServerless.js +282 -0
  29. package/lib/esm/SessionData.d.ts +6 -0
  30. package/lib/esm/SessionData.js +1 -0
  31. package/lib/esm/aws-classify-common/EndPointsLogging.d.ts +8 -0
  32. package/lib/esm/aws-classify-common/EndPointsLogging.js +8 -0
  33. package/lib/esm/aws-classify-common/LambdaRequest.d.ts +6 -0
  34. package/lib/esm/aws-classify-common/LambdaRequest.js +1 -0
  35. package/lib/esm/aws-classify-common/LambdaResponse.d.ts +6 -0
  36. package/lib/esm/aws-classify-common/LambdaResponse.js +1 -0
  37. package/lib/esm/aws-classify-common/index.d.ts +4 -0
  38. package/lib/esm/aws-classify-common/index.js +2 -0
  39. package/lib/esm/dispatch.d.ts +7 -0
  40. package/lib/esm/dispatch.js +73 -0
  41. package/lib/esm/index.d.ts +3 -0
  42. package/lib/esm/index.js +3 -0
  43. package/package.json +36 -0
@@ -0,0 +1,6 @@
1
+ import { ClassDef } from "./ClassDef";
2
+ export interface SessionData {
3
+ classDef: ClassDef<any, any>;
4
+ cargo: any;
5
+ sessionId: any;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ export declare const EndPointsLogging: {
2
+ create: boolean;
3
+ connect: boolean;
4
+ exceptions: boolean;
5
+ calls: boolean;
6
+ requests: boolean;
7
+ data: boolean;
8
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EndPointsLogging = void 0;
4
+ exports.EndPointsLogging = {
5
+ create: true,
6
+ connect: true,
7
+ exceptions: true,
8
+ calls: true,
9
+ requests: false,
10
+ data: false,
11
+ };
@@ -0,0 +1,6 @@
1
+ export interface LambdaRequest {
2
+ interfaceName: string;
3
+ methodName: string;
4
+ args: any;
5
+ sessionId: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ export interface LambdaResponse {
2
+ data: any;
3
+ cargo: any;
4
+ exception: string | undefined;
5
+ sessionId: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export type { LambdaRequest } from './LambdaRequest';
2
+ export type { LambdaResponse } from './LambdaResponse';
3
+ export { EndPointsLogging } from './EndPointsLogging';
4
+ export declare const reqBody: () => never;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reqBody = exports.EndPointsLogging = void 0;
4
+ var EndPointsLogging_1 = require("./EndPointsLogging");
5
+ Object.defineProperty(exports, "EndPointsLogging", { enumerable: true, get: function () { return EndPointsLogging_1.EndPointsLogging; } });
6
+ const reqBody = () => { throw new Error('Request class not registered'); };
7
+ exports.reqBody = reqBody;
@@ -0,0 +1,7 @@
1
+ import { APIGatewayProxyEvent, Context } from 'aws-lambda';
2
+ import { ClassifyServerless } from "./index";
3
+ import { APIGatewayProxyStructuredResultV2 } from "aws-lambda/trigger/api-gateway-proxy";
4
+ export declare const classifyServerless: ClassifyServerless;
5
+ export declare const responseHandler: (event: APIGatewayProxyEvent, context: Context) => Promise<APIGatewayProxyStructuredResultV2>;
6
+ export declare const webSocketConnect: (event: APIGatewayProxyEvent, _context: Context) => Promise<APIGatewayProxyStructuredResultV2>;
7
+ export declare const webSocketDisconnect: (_event: APIGatewayProxyEvent, _context: Context) => Promise<APIGatewayProxyStructuredResultV2>;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.webSocketDisconnect = exports.webSocketConnect = exports.responseHandler = exports.classifyServerless = void 0;
13
+ const index_1 = require("./index");
14
+ const js_freeze_dry_1 = require("js-freeze-dry");
15
+ const ClassifyServerless_1 = require("./ClassifyServerless");
16
+ exports.classifyServerless = new index_1.ClassifyServerless();
17
+ const responseHandler = (event, context) => __awaiter(void 0, void 0, void 0, function* () {
18
+ try {
19
+ //console.log(`dispatching`);
20
+ return {
21
+ statusCode: 200,
22
+ body: (yield exports.classifyServerless.dispatch(event, context)) || "",
23
+ };
24
+ }
25
+ catch (err) {
26
+ //console.log(`request.body = ${event.body}`);
27
+ console.log(`error = ${err.message} ${err.stack}`);
28
+ return {
29
+ statusCode: 200,
30
+ body: (0, js_freeze_dry_1.serialize)({
31
+ data: undefined,
32
+ exception: `Internal Server Error (${err}) - see log at ${new Date()}`,
33
+ cargo: undefined,
34
+ sessionId: undefined
35
+ })
36
+ };
37
+ }
38
+ });
39
+ exports.responseHandler = responseHandler;
40
+ const webSocketConnect = (event, _context) => __awaiter(void 0, void 0, void 0, function* () {
41
+ //console.log('connecting');
42
+ const sessionId = event.headers['Sec-WebSocket-Protocol'] || "";
43
+ const connectId = event.requestContext.connectionId;
44
+ //console.log(JSON.stringify(event));
45
+ const result = yield (0, ClassifyServerless_1.getSessionData)(sessionId); // Make sure session id passed in is valid
46
+ if (result) {
47
+ // Save connection id
48
+ yield (0, ClassifyServerless_1.saveSessionData)(sessionId, undefined, undefined, connectId);
49
+ //console.log(`webSocketConnect session ${sessionId} connected to websocket connectId ${connectId}`);
50
+ return {
51
+ statusCode: 200,
52
+ headers: {
53
+ 'Sec-WebSocket-Protocol': sessionId
54
+ },
55
+ body: JSON.stringify({
56
+ msg: connectId,
57
+ })
58
+ };
59
+ }
60
+ else {
61
+ console.log(`invalid sessionId - webSocketConnect sessionId=${sessionId} connectId=${connectId}`);
62
+ return {
63
+ statusCode: 500,
64
+ body: 'Opps'
65
+ };
66
+ }
67
+ });
68
+ exports.webSocketConnect = webSocketConnect;
69
+ const webSocketDisconnect = (_event, _context) => __awaiter(void 0, void 0, void 0, function* () {
70
+ //console.log('Disconnect ' + JSON.stringify(event));
71
+ //console.log(`webSocketDisconnect sessionId=${sessionId} connectId=${connectId}`);
72
+ return {
73
+ statusCode: 200,
74
+ headers: {
75
+ 'Sec-WebSocket-Protocol': 'websocket'
76
+ }
77
+ };
78
+ });
79
+ exports.webSocketDisconnect = webSocketDisconnect;
@@ -0,0 +1,3 @@
1
+ export { ClassifyServerless } from './ClassifyServerless';
2
+ export { ClassifyResponse } from './ClassifyResponse';
3
+ export { classifyServerless, webSocketConnect, webSocketDisconnect, responseHandler } from './dispatch';
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.responseHandler = exports.webSocketDisconnect = exports.webSocketConnect = exports.classifyServerless = exports.ClassifyResponse = exports.ClassifyServerless = void 0;
4
+ var ClassifyServerless_1 = require("./ClassifyServerless");
5
+ Object.defineProperty(exports, "ClassifyServerless", { enumerable: true, get: function () { return ClassifyServerless_1.ClassifyServerless; } });
6
+ var ClassifyResponse_1 = require("./ClassifyResponse");
7
+ Object.defineProperty(exports, "ClassifyResponse", { enumerable: true, get: function () { return ClassifyResponse_1.ClassifyResponse; } });
8
+ var dispatch_1 = require("./dispatch");
9
+ Object.defineProperty(exports, "classifyServerless", { enumerable: true, get: function () { return dispatch_1.classifyServerless; } });
10
+ Object.defineProperty(exports, "webSocketConnect", { enumerable: true, get: function () { return dispatch_1.webSocketConnect; } });
11
+ Object.defineProperty(exports, "webSocketDisconnect", { enumerable: true, get: function () { return dispatch_1.webSocketDisconnect; } });
12
+ Object.defineProperty(exports, "responseHandler", { enumerable: true, get: function () { return dispatch_1.responseHandler; } });
@@ -0,0 +1,6 @@
1
+ import { ClassifyResponse } from "./ClassifyResponse";
2
+ export interface ClassDef<ServerClass extends ClassifyResponse, ClientClass> {
3
+ serverClass: new () => ServerClass;
4
+ clientClass: new () => ClientClass;
5
+ authorizer: ((endPoint: ServerClass, method: string, args: IArguments) => Promise<boolean>) | undefined;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ export declare class ClassifyResponse {
2
+ __sessionId__: string | undefined;
3
+ __connectionId__: string | undefined;
4
+ __interfaceName__: string | undefined;
5
+ constructor(interfaceName: string, sessionId: string, connectionId: string);
6
+ }
@@ -0,0 +1,7 @@
1
+ export class ClassifyResponse {
2
+ constructor(interfaceName, sessionId, connectionId) {
3
+ this.__connectionId__ = connectionId;
4
+ this.__sessionId__ = sessionId;
5
+ this.__interfaceName__ = interfaceName;
6
+ }
7
+ }
@@ -0,0 +1,27 @@
1
+ import { ClassDef } from "./ClassDef";
2
+ import { APIGatewayProxyEvent, Context } from "aws-lambda";
3
+ export declare class ClassifyServerless {
4
+ logLevel: Partial<typeof EndPointsLogging>;
5
+ classDefs: Map<any, ClassDef<any, any>>;
6
+ requests: Map<any, any>;
7
+ log: (_message: string) => void;
8
+ setLogger(log: (_message: string) => void): void;
9
+ setLogLevel(logLevel: Partial<typeof EndPointsLogging>): void;
10
+ registerResponse<T>(responseClass: new () => T, authorizer?: (_endPoint: T, _method: string, _args: IArguments) => Promise<boolean>): void;
11
+ dispatch(ev: APIGatewayProxyEvent, context: Context, classes?: {}): Promise<string>;
12
+ registerRequest<T>(requestClass: new () => T, classes?: any): new () => T;
13
+ getSessionId<T>(responseObj: T): any;
14
+ createRequest<T, U>(responseObj: U, requestClass: new () => T): T;
15
+ createRequestForSession<T>(sessionId: string, requestClass: new () => T): Promise<T>;
16
+ createResponse<T, R>(responseClass: new () => T, sessionId: string, callback: (_obj: T) => Promise<R>, classes?: any): Promise<R>;
17
+ }
18
+ export declare function getSessionData(sessionId: string, interfaceName?: string): Promise<Record<string, any> | undefined>;
19
+ export declare function saveSessionData(sessionId: string, interfaceName?: string, sessionData?: string, connectionId?: string): Promise<string>;
20
+ export declare const EndPointsLogging: {
21
+ create: boolean;
22
+ connect: boolean;
23
+ exceptions: boolean;
24
+ calls: boolean;
25
+ requests: boolean;
26
+ data: boolean;
27
+ };
@@ -0,0 +1,282 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { deserialize, serialize } from "js-freeze-dry";
11
+ import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb";
12
+ import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
13
+ import { ApiGatewayManagementApiClient, PostToConnectionCommand } from "@aws-sdk/client-apigatewaymanagementapi";
14
+ const ddbClient = new DynamoDBClient({ region: process.env.DD_REGION, endpoint: process.env.DD_ENDPOINT });
15
+ const ddbDocClient = DynamoDBDocument.from(ddbClient);
16
+ export class ClassifyServerless {
17
+ constructor() {
18
+ this.logLevel = {};
19
+ this.classDefs = new Map();
20
+ this.requests = new Map();
21
+ this.log = msg => console.log(msg);
22
+ }
23
+ setLogger(log) {
24
+ this.log = log;
25
+ }
26
+ setLogLevel(logLevel) {
27
+ this.logLevel = logLevel;
28
+ }
29
+ registerResponse(responseClass, authorizer) {
30
+ // Find ultimate base class
31
+ let clientClass = responseClass;
32
+ while (Object.getPrototypeOf(clientClass).prototype)
33
+ clientClass = Object.getPrototypeOf(clientClass);
34
+ if (clientClass === responseClass)
35
+ throw ('ClassifyServerless.registerResponse: Response class must extend a request class');
36
+ // Get interface name as static property of request class
37
+ const interfaceName = clientClass['interfaceName'];
38
+ if (!interfaceName)
39
+ throw ('ClassifyServerless.registerResponse: Request must have interfaceName as a static property');
40
+ this.classDefs.set(interfaceName, { serverClass: responseClass, clientClass, authorizer });
41
+ responseClass.__interfaceName__ = interfaceName;
42
+ }
43
+ dispatch(ev, context, classes = {}) {
44
+ return __awaiter(this, void 0, void 0, function* () {
45
+ const request = deserialize(ev.body, classes);
46
+ const logName = `${request.interfaceName}.${request.methodName}`;
47
+ let sessionId = request.sessionId; // May be empty
48
+ // Pseudo interface/method to request socket access and return a session id to use in connect
49
+ // session id will be passed in sec-websocket-protocol on connect request
50
+ if (logName === '$WebSocket.$authorize') {
51
+ const socketResult = yield getSessionData(sessionId, "");
52
+ if (!socketResult) {
53
+ sessionId = context.awsRequestId;
54
+ yield saveSessionData(sessionId, undefined, undefined, undefined);
55
+ }
56
+ const lambdaResponse = {
57
+ data: process.env.IS_OFFLINE ? 'ws://localhost:3001' : `wss://${process.env.APIG_ENDPOINT}`,
58
+ exception: undefined,
59
+ cargo: undefined,
60
+ sessionId: sessionId,
61
+ };
62
+ return serialize(lambdaResponse, classes);
63
+ }
64
+ if (this.logLevel.data && this.logLevel.calls)
65
+ this.log(`Lambda ${logName} invoked with ${ev.body}`);
66
+ else if (this.logLevel.calls)
67
+ this.log(`Lambda ${logName} invoked`);
68
+ const classDef = this.classDefs.get(request.interfaceName);
69
+ if (!classDef)
70
+ throw new Error(`No Response defined for ${request.interfaceName}`);
71
+ if (!classDef.clientClass.prototype[request.methodName])
72
+ throw new Error(`${request.methodName} not found in ${request.interfaceName} client request class`);
73
+ // If authorizer passed in make sure request is authorized
74
+ if (!classDef.authorizer || (yield classDef.authorizer(request.interfaceName, request.methodName, request.args))) {
75
+ // Instantiate the class
76
+ const obj = new classDef.serverClass();
77
+ // Retrieve session data from DynamoDB base on sessionId in request
78
+ const result = yield getSessionData(sessionId, request.interfaceName);
79
+ if (!result)
80
+ sessionId = context.awsRequestId;
81
+ else {
82
+ const sessionData = result[`interface_${request.interfaceName}`];
83
+ if (sessionData) // Enrich it with session data
84
+ Object.assign(obj, deserialize(sessionData, classes));
85
+ }
86
+ obj.__sessionId__ = sessionId;
87
+ obj.__connectionId__ = result === null || result === void 0 ? void 0 : result.connectionId;
88
+ // Call the class method and catch any exceptions it might throw to pass back
89
+ let fnResponse;
90
+ try {
91
+ fnResponse = yield obj[request.methodName].call(obj, ...request.args);
92
+ }
93
+ catch (e) {
94
+ if (this.logLevel.calls)
95
+ this.log(`Lambda ${logName} had exception ${e}`);
96
+ const lambdaResponse = {
97
+ data: undefined,
98
+ exception: e.message,
99
+ cargo: undefined,
100
+ sessionId: sessionId,
101
+ };
102
+ return serialize(lambdaResponse, classes);
103
+ }
104
+ const updatedSessionData = serialize(obj, classes);
105
+ if (!result || updatedSessionData !== result.sessionData)
106
+ sessionId = yield saveSessionData(sessionId, request.interfaceName, updatedSessionData, undefined);
107
+ // Formulate response
108
+ const lambdaResponse = {
109
+ data: fnResponse,
110
+ exception: undefined,
111
+ cargo: undefined,
112
+ sessionId,
113
+ };
114
+ const response = serialize(lambdaResponse, classes);
115
+ if (this.logLevel.data && this.logLevel.calls)
116
+ this.log(`Lambda ${logName} responded with ${response}`);
117
+ else if (this.logLevel.calls)
118
+ this.log(`Lambda ${logName} responded`);
119
+ return response;
120
+ }
121
+ else {
122
+ this.log(`Lambda ${logName} not authorized`);
123
+ throw new Error("Not Authorized");
124
+ }
125
+ });
126
+ }
127
+ registerRequest(requestClass, classes = {}) {
128
+ const interfaceName = requestClass['interfaceName'];
129
+ if (!interfaceName)
130
+ throw ('ClassifyServerless.registerRequest: Request must have interfaceName as a static property');
131
+ for (const methodName of Object.getOwnPropertyNames(requestClass.prototype)) {
132
+ if (methodName === 'constructor' || typeof (requestClass.prototype)[methodName] !== 'function')
133
+ continue;
134
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
135
+ const expressServer = this;
136
+ requestClass.prototype[methodName] = function (...args) {
137
+ return __awaiter(this, void 0, void 0, function* () {
138
+ try {
139
+ // Build request
140
+ const sessionId = this['__sessionId__'];
141
+ const connectionId = this['__connectionId__'];
142
+ if (!sessionId)
143
+ throw new Error(`You must instantiate ${interfaceName} using the ClassifyServerless.createRequest`);
144
+ if (!connectionId)
145
+ throw new Error(`WebSocket handshake not established for ${interfaceName}`);
146
+ const request = {
147
+ interfaceName: interfaceName,
148
+ args, methodName,
149
+ sessionId
150
+ };
151
+ const payload = serialize(request, classes);
152
+ // Log request
153
+ if (expressServer.logLevel.data && expressServer.logLevel.requests)
154
+ expressServer.log(`Request ${interfaceName} emitting with ${payload}`);
155
+ else if (expressServer.logLevel && expressServer.logLevel.requests)
156
+ expressServer.log(`Request ${interfaceName} emitting`);
157
+ // Post request to the gateway to be sent to src
158
+ const endpoint = process.env.IS_OFFLINE ? 'http://localhost:3001' : `https://${process.env.APIG_ENDPOINT}`;
159
+ if (expressServer.logLevel.calls)
160
+ expressServer.log(`creating APIGatewayManagementApiClient for endpoint ${endpoint}`);
161
+ const client = new ApiGatewayManagementApiClient({ endpoint });
162
+ if (expressServer.logLevel.data)
163
+ expressServer.log(`posting to ${connectionId} ${payload}`);
164
+ const post = new PostToConnectionCommand({
165
+ ConnectionId: connectionId,
166
+ Data: Buffer.from(payload)
167
+ });
168
+ yield client.send(post);
169
+ // Catch any exception, so it can be logged and then rethrown
170
+ }
171
+ catch (e) {
172
+ if (expressServer.logLevel.exceptions)
173
+ expressServer.log(e.message);
174
+ throw e;
175
+ }
176
+ });
177
+ };
178
+ if (this.logLevel.create)
179
+ this.log(`${interfaceName} bound to ${requestClass.name}.${methodName}`);
180
+ }
181
+ return requestClass;
182
+ }
183
+ getSessionId(responseObj) {
184
+ const sessionId = responseObj['__sessionId__'];
185
+ if (!sessionId)
186
+ throw Error('ClassifyServerless.getSessionId: no session id');
187
+ return sessionId;
188
+ }
189
+ createRequest(responseObj, requestClass) {
190
+ const obj = new requestClass();
191
+ obj['__sessionId__'] = responseObj['__sessionId__'];
192
+ obj['__connectionId__'] = responseObj['__connectionId__'];
193
+ return obj;
194
+ }
195
+ createRequestForSession(sessionId, requestClass) {
196
+ return __awaiter(this, void 0, void 0, function* () {
197
+ // Get connection Id
198
+ const result = yield getSessionData(sessionId);
199
+ if (!result)
200
+ throw new Error(`ClassifyResponse.createRequestForSession: invalid session id`);
201
+ if (!result.connectionId)
202
+ throw new Error(`WebSocket handshake not established for session`);
203
+ // Create request
204
+ const obj = new requestClass();
205
+ obj['__sessionId__'] = sessionId;
206
+ obj['__connectionId__'] = result.connectionId;
207
+ return obj;
208
+ });
209
+ }
210
+ createResponse(responseClass, sessionId, callback, classes = {}) {
211
+ return __awaiter(this, void 0, void 0, function* () {
212
+ const interfaceName = responseClass.__interfaceName__;
213
+ if (!interfaceName)
214
+ throw new Error(`ClassifyResponse.createResponse: Failed to call registerResponse for ${responseClass.name}`);
215
+ const result = yield getSessionData(sessionId, interfaceName);
216
+ if (!result)
217
+ throw new Error(`ClassifyResponse.createResponse: invalid session id for interface ${interfaceName}`);
218
+ const sessionData = result[`interface_${interfaceName}`];
219
+ // Instantiate the class
220
+ const obj = (new responseClass());
221
+ // Enrich it with session data
222
+ if (sessionData)
223
+ Object.assign(obj, deserialize(sessionData, classes));
224
+ obj.__sessionId__ = sessionId;
225
+ obj.__connectionId__ = result.connectionId;
226
+ if (this.logLevel.calls)
227
+ this.log(`creating response for ${interfaceName} with sessionId=${sessionId} connectionId= ${obj.__connectionId__} sessionData=${sessionData}`);
228
+ const ret = yield callback(obj);
229
+ const updatedSessionData = serialize(obj, classes);
230
+ if (updatedSessionData !== result.sessionData) {
231
+ if (this.logLevel.calls)
232
+ this.log(`saving session data for ${interfaceName} with sessionId=${sessionId} connectionId= ${obj.__connectionId__} sessionData=${updatedSessionData}`);
233
+ yield saveSessionData(sessionId, interfaceName, updatedSessionData, undefined);
234
+ }
235
+ return ret;
236
+ });
237
+ }
238
+ }
239
+ export function getSessionData(sessionId, interfaceName = "") {
240
+ return __awaiter(this, void 0, void 0, function* () {
241
+ if (sessionId) {
242
+ const data = yield ddbDocClient.get({
243
+ TableName: 'classifySessionStore',
244
+ Key: { sessionId },
245
+ ConsistentRead: true,
246
+ ProjectionExpression: `interface_${interfaceName}, connectionId, updated`
247
+ });
248
+ return data.Item;
249
+ }
250
+ return undefined;
251
+ });
252
+ }
253
+ export function saveSessionData(sessionId, interfaceName, sessionData, connectionId) {
254
+ return __awaiter(this, void 0, void 0, function* () {
255
+ const updateExpressionComponents = ['updated = :time'];
256
+ const expressionAttributeValues = { ':time': new Date().getTime() };
257
+ if (sessionData && interfaceName) {
258
+ updateExpressionComponents.push(`interface_${interfaceName} = :data`);
259
+ expressionAttributeValues[`:data`] = sessionData;
260
+ }
261
+ if (connectionId) {
262
+ updateExpressionComponents.push('connectionId = :connectionId');
263
+ expressionAttributeValues[':connectionId'] = connectionId;
264
+ }
265
+ // First try and out data only if the session id exists
266
+ yield ddbDocClient.update({
267
+ TableName: 'classifySessionStore',
268
+ Key: { sessionId },
269
+ UpdateExpression: `set ${updateExpressionComponents.join(", ")}`,
270
+ ExpressionAttributeValues: expressionAttributeValues
271
+ });
272
+ return sessionId;
273
+ });
274
+ }
275
+ export const EndPointsLogging = {
276
+ create: true,
277
+ connect: true,
278
+ exceptions: true,
279
+ calls: true,
280
+ requests: false,
281
+ data: false,
282
+ };
@@ -0,0 +1,6 @@
1
+ import { ClassDef } from "./ClassDef";
2
+ export interface SessionData {
3
+ classDef: ClassDef<any, any>;
4
+ cargo: any;
5
+ sessionId: any;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ export declare const EndPointsLogging: {
2
+ create: boolean;
3
+ connect: boolean;
4
+ exceptions: boolean;
5
+ calls: boolean;
6
+ requests: boolean;
7
+ data: boolean;
8
+ };
@@ -0,0 +1,8 @@
1
+ export const EndPointsLogging = {
2
+ create: true,
3
+ connect: true,
4
+ exceptions: true,
5
+ calls: true,
6
+ requests: false,
7
+ data: false,
8
+ };
@@ -0,0 +1,6 @@
1
+ export interface LambdaRequest {
2
+ interfaceName: string;
3
+ methodName: string;
4
+ args: any;
5
+ sessionId: string;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ export interface LambdaResponse {
2
+ data: any;
3
+ cargo: any;
4
+ exception: string | undefined;
5
+ sessionId: string;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export type { LambdaRequest } from './LambdaRequest';
2
+ export type { LambdaResponse } from './LambdaResponse';
3
+ export { EndPointsLogging } from './EndPointsLogging';
4
+ export declare const reqBody: () => never;
@@ -0,0 +1,2 @@
1
+ export { EndPointsLogging } from './EndPointsLogging';
2
+ export const reqBody = () => { throw new Error('Request class not registered'); };
@@ -0,0 +1,7 @@
1
+ import { APIGatewayProxyEvent, Context } from 'aws-lambda';
2
+ import { ClassifyServerless } from "./index";
3
+ import { APIGatewayProxyStructuredResultV2 } from "aws-lambda/trigger/api-gateway-proxy";
4
+ export declare const classifyServerless: ClassifyServerless;
5
+ export declare const responseHandler: (event: APIGatewayProxyEvent, context: Context) => Promise<APIGatewayProxyStructuredResultV2>;
6
+ export declare const webSocketConnect: (event: APIGatewayProxyEvent, _context: Context) => Promise<APIGatewayProxyStructuredResultV2>;
7
+ export declare const webSocketDisconnect: (_event: APIGatewayProxyEvent, _context: Context) => Promise<APIGatewayProxyStructuredResultV2>;