lambder 1.0.109 → 1.0.111
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/dist/Lambder.d.ts +6 -0
- package/dist/Lambder.js +61 -1
- package/dist/LambderCaller.js +1 -1
- package/dist/LambderSession.d.ts +1 -0
- package/dist/LambderSession.js +7 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
- package/src/Lambder.ts +55 -1
- package/src/LambderCaller.ts +1 -1
- package/src/LambderSession.ts +10 -0
- package/src/index.ts +2 -1
package/dist/Lambder.d.ts
CHANGED
|
@@ -82,6 +82,12 @@ export default class Lambder {
|
|
|
82
82
|
addHook(hookEvent: 'beforeRender', hookFn: HookBeforeRenderFunction, priority?: number): Promise<void>;
|
|
83
83
|
addHook(hookEvent: 'afterRender', hookFn: HookAfterRenderFunction, priority?: number): Promise<void>;
|
|
84
84
|
addHook(hookEvent: 'fallback', hookFn: HookFallbackFunction, priority?: number): Promise<void>;
|
|
85
|
+
getSessionController(ctx: LambderRenderContext): {
|
|
86
|
+
startSession: (userKey: string, data?: any, ttlInSeconds?: number) => Promise<LambderSessionContext>;
|
|
87
|
+
editSession: (newData: any) => Promise<LambderSessionContext>;
|
|
88
|
+
deleteSession: () => Promise<void>;
|
|
89
|
+
deleteSessionAll: () => Promise<void>;
|
|
90
|
+
};
|
|
85
91
|
getResponseBuilder(): LambderResponseBuilder;
|
|
86
92
|
private getResolver;
|
|
87
93
|
render(event: APIGatewayProxyEvent, lambdaContext: Context): Promise<LambderResolverResponse>;
|
package/dist/Lambder.js
CHANGED
|
@@ -46,7 +46,7 @@ export default class Lambder {
|
|
|
46
46
|
utils;
|
|
47
47
|
lambderSession;
|
|
48
48
|
sessionTokenCookieKey = "LMDRSESSIONTKID";
|
|
49
|
-
sessionCsrfCookieKey = "
|
|
49
|
+
sessionCsrfCookieKey = "LMDRSESSIONCSTK";
|
|
50
50
|
constructor({ publicPath, apiPath, ejsPath, apiVersion }) {
|
|
51
51
|
this.publicPath = publicPath || "/incorrect-path-not-found";
|
|
52
52
|
this.ejsPath = ejsPath || "/incorrect-ejs-path-not-found";
|
|
@@ -213,6 +213,40 @@ export default class Lambder {
|
|
|
213
213
|
this.hookList[hookEvent].sort((a, b) => a.priority - b.priority);
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
|
+
getSessionController(ctx) {
|
|
217
|
+
return {
|
|
218
|
+
startSession: async (userKey, data, ttlInSeconds) => {
|
|
219
|
+
if (!this.lambderSession)
|
|
220
|
+
throw "Session is not enabled. Use lambder.enableDdbSession(...) to configure.";
|
|
221
|
+
ctx.session = await this.lambderSession.createSession(userKey, data, ttlInSeconds);
|
|
222
|
+
return ctx.session;
|
|
223
|
+
},
|
|
224
|
+
editSession: async (newData) => {
|
|
225
|
+
if (!this.lambderSession)
|
|
226
|
+
throw "Session is not enabled. Use lambder.enableDdbSession(...) to configure.";
|
|
227
|
+
if (!ctx.session)
|
|
228
|
+
throw "Session not found.";
|
|
229
|
+
ctx.session = await this.lambderSession.editSession(ctx.session, newData);
|
|
230
|
+
return ctx.session;
|
|
231
|
+
},
|
|
232
|
+
deleteSession: async () => {
|
|
233
|
+
if (!this.lambderSession)
|
|
234
|
+
throw "Session is not enabled. Use lambder.enableDdbSession(...) to configure.";
|
|
235
|
+
if (!ctx.session)
|
|
236
|
+
throw "Session not found.";
|
|
237
|
+
await this.lambderSession.deleteSession(ctx.session);
|
|
238
|
+
ctx.session = null;
|
|
239
|
+
},
|
|
240
|
+
deleteSessionAll: async () => {
|
|
241
|
+
if (!this.lambderSession)
|
|
242
|
+
throw "Session is not enabled. Use lambder.enableDdbSession(...) to configure.";
|
|
243
|
+
if (!ctx.session)
|
|
244
|
+
throw "Session not found.";
|
|
245
|
+
await this.lambderSession.deleteSessionAll(ctx.session);
|
|
246
|
+
ctx.session = null;
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
}
|
|
216
250
|
getResponseBuilder() {
|
|
217
251
|
return new LambderResponseBuilder({
|
|
218
252
|
isCorsEnabled: this.isCorsEnabled,
|
|
@@ -244,6 +278,7 @@ export default class Lambder {
|
|
|
244
278
|
return resolver.cors();
|
|
245
279
|
const firstMatchedAction = this.actionList.find(action => action.conditionFn(ctx));
|
|
246
280
|
if (firstMatchedAction) {
|
|
281
|
+
// Run beforeRender hooks
|
|
247
282
|
for (const hook of this.hookList["beforeRender"]) {
|
|
248
283
|
const hookCtx = await hook.hookFn(ctx, resolver);
|
|
249
284
|
if (hookCtx instanceof Error) {
|
|
@@ -251,7 +286,9 @@ export default class Lambder {
|
|
|
251
286
|
}
|
|
252
287
|
ctx = hookCtx;
|
|
253
288
|
}
|
|
289
|
+
// Run matched action
|
|
254
290
|
let response = await firstMatchedAction.actionFn(ctx, resolver);
|
|
291
|
+
// Run afterRender hooks
|
|
255
292
|
for (const hook of this.hookList["afterRender"]) {
|
|
256
293
|
const hookResponse = await hook.hookFn(ctx, resolver, response);
|
|
257
294
|
if (hookResponse instanceof Error) {
|
|
@@ -259,6 +296,29 @@ export default class Lambder {
|
|
|
259
296
|
}
|
|
260
297
|
response = hookResponse;
|
|
261
298
|
}
|
|
299
|
+
// Apply session cookie if needed.
|
|
300
|
+
if ((ctx.session?.sessionToken ?? null) !== (ctx?.cookie?.[this.sessionTokenCookieKey] ?? null)) {
|
|
301
|
+
// Add session cookies
|
|
302
|
+
if (ctx.session?.sessionToken) {
|
|
303
|
+
response.multiValueHeaders = {
|
|
304
|
+
...(response.multiValueHeaders || {}),
|
|
305
|
+
"Set-Cookie": [
|
|
306
|
+
`${this.sessionTokenCookieKey}=${ctx.session.sessionToken}; Expires=${new Date(ctx.session.expiresAt * 1000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
307
|
+
`${this.sessionCsrfCookieKey}=${ctx.session.csrfToken}; Expires=${new Date(ctx.session.expiresAt * 1000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
308
|
+
],
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
// Delete session cookies
|
|
313
|
+
response.multiValueHeaders = {
|
|
314
|
+
...(response.multiValueHeaders || {}),
|
|
315
|
+
"Set-Cookie": [
|
|
316
|
+
`${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
317
|
+
`${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
318
|
+
],
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
}
|
|
262
322
|
resolve(response);
|
|
263
323
|
}
|
|
264
324
|
else {
|
package/dist/LambderCaller.js
CHANGED
|
@@ -38,7 +38,7 @@ export default class LambderCaller {
|
|
|
38
38
|
activeFetchList: this.fetchTrackerList.filter(v => !v.done)
|
|
39
39
|
});
|
|
40
40
|
const version = this.apiVersion;
|
|
41
|
-
const token = Cookies.get("
|
|
41
|
+
const token = Cookies.get("LMDRSESSIONCSTK") || "";
|
|
42
42
|
const siteHost = window.location.hostname;
|
|
43
43
|
let data = await fetch(this.apiPath, {
|
|
44
44
|
method: 'POST', mode: 'same-origin', cache: 'no-cache',
|
package/dist/LambderSession.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export default class LambderSession {
|
|
|
28
28
|
private ddbQueryAllByPartitionKey;
|
|
29
29
|
private ddbDeleteAllByPartitionKey;
|
|
30
30
|
createSession(userKey: string, data?: any, ttlInSeconds?: number): Promise<LambderSessionContext>;
|
|
31
|
+
editSession(session: LambderSessionContext, newData?: any): Promise<LambderSessionContext>;
|
|
31
32
|
getSession(sessionToken: string): Promise<LambderSessionContext | null>;
|
|
32
33
|
isSessionValid(session: any, sessionToken: any, csrfToken: any, skipCsrfTokenCheck?: boolean): boolean;
|
|
33
34
|
deleteSession(session: Record<string, any>): Promise<boolean>;
|
package/dist/LambderSession.js
CHANGED
|
@@ -80,6 +80,13 @@ export default class LambderSession {
|
|
|
80
80
|
await this.ddbPutItem(session);
|
|
81
81
|
return session;
|
|
82
82
|
}
|
|
83
|
+
async editSession(session, newData) {
|
|
84
|
+
if (!session)
|
|
85
|
+
throw "Invalid session";
|
|
86
|
+
session.data = newData;
|
|
87
|
+
await this.ddbPutItem(session);
|
|
88
|
+
return session;
|
|
89
|
+
}
|
|
83
90
|
async getSession(sessionToken) {
|
|
84
91
|
const [userKeyHash, sessionSortKey] = sessionToken.split(":");
|
|
85
92
|
if (!userKeyHash || !sessionSortKey)
|
package/dist/index.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ export default Lambder;
|
|
|
3
3
|
export { default as LambderCaller } from "./LambderCaller.js";
|
|
4
4
|
export { default as LambderResponseBuilder } from "./LambderResponseBuilder.js";
|
|
5
5
|
export { default as LambderResolver } from "./LambderResolver.js";
|
|
6
|
+
export { default as LambderSession } from "./LambderSession.js";
|
package/dist/index.js
CHANGED
|
@@ -3,3 +3,4 @@ export default Lambder;
|
|
|
3
3
|
export { default as LambderCaller } from "./LambderCaller.js";
|
|
4
4
|
export { default as LambderResponseBuilder } from "./LambderResponseBuilder.js";
|
|
5
5
|
export { default as LambderResolver } from "./LambderResolver.js";
|
|
6
|
+
export { default as LambderSession } from "./LambderSession.js";
|
package/package.json
CHANGED
package/src/Lambder.ts
CHANGED
|
@@ -92,7 +92,7 @@ export default class Lambder {
|
|
|
92
92
|
|
|
93
93
|
private lambderSession?: LambderSession;
|
|
94
94
|
private sessionTokenCookieKey = "LMDRSESSIONTKID";
|
|
95
|
-
private sessionCsrfCookieKey = "
|
|
95
|
+
private sessionCsrfCookieKey = "LMDRSESSIONCSTK";
|
|
96
96
|
|
|
97
97
|
constructor(
|
|
98
98
|
{ publicPath, apiPath, ejsPath, apiVersion }:
|
|
@@ -288,6 +288,34 @@ export default class Lambder {
|
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
public getSessionController(ctx: LambderRenderContext){
|
|
292
|
+
return {
|
|
293
|
+
startSession: async (userKey: string, data?: any, ttlInSeconds?: number): Promise<LambderSessionContext> => {
|
|
294
|
+
if(!this.lambderSession) throw "Session is not enabled. Use lambder.enableDdbSession(...) to configure.";
|
|
295
|
+
ctx.session = await this.lambderSession.createSession(userKey, data, ttlInSeconds);
|
|
296
|
+
return ctx.session;
|
|
297
|
+
},
|
|
298
|
+
editSession: async (newData: any): Promise<LambderSessionContext> => {
|
|
299
|
+
if(!this.lambderSession) throw "Session is not enabled. Use lambder.enableDdbSession(...) to configure.";
|
|
300
|
+
if(!ctx.session) throw "Session not found.";
|
|
301
|
+
ctx.session = await this.lambderSession.editSession(ctx.session, newData);
|
|
302
|
+
return ctx.session;
|
|
303
|
+
},
|
|
304
|
+
deleteSession: async () => {
|
|
305
|
+
if(!this.lambderSession) throw "Session is not enabled. Use lambder.enableDdbSession(...) to configure.";
|
|
306
|
+
if(!ctx.session) throw "Session not found.";
|
|
307
|
+
await this.lambderSession.deleteSession(ctx.session);
|
|
308
|
+
ctx.session = null
|
|
309
|
+
},
|
|
310
|
+
deleteSessionAll: async () => {
|
|
311
|
+
if(!this.lambderSession) throw "Session is not enabled. Use lambder.enableDdbSession(...) to configure.";
|
|
312
|
+
if(!ctx.session) throw "Session not found.";
|
|
313
|
+
await this.lambderSession.deleteSessionAll(ctx.session);
|
|
314
|
+
ctx.session = null
|
|
315
|
+
},
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
291
319
|
public getResponseBuilder(){
|
|
292
320
|
return new LambderResponseBuilder({
|
|
293
321
|
isCorsEnabled: this.isCorsEnabled,
|
|
@@ -328,21 +356,47 @@ export default class Lambder {
|
|
|
328
356
|
|
|
329
357
|
const firstMatchedAction = this.actionList.find(action => action.conditionFn(ctx));
|
|
330
358
|
if(firstMatchedAction){
|
|
359
|
+
// Run beforeRender hooks
|
|
331
360
|
for(const hook of this.hookList["beforeRender"]){
|
|
332
361
|
const hookCtx = await hook.hookFn(ctx, resolver);
|
|
333
362
|
if(hookCtx instanceof Error){ throw hookCtx; }
|
|
334
363
|
ctx = hookCtx;
|
|
335
364
|
}
|
|
365
|
+
// Run matched action
|
|
336
366
|
let response = await firstMatchedAction.actionFn(ctx, resolver);
|
|
367
|
+
// Run afterRender hooks
|
|
337
368
|
for(const hook of this.hookList["afterRender"]){
|
|
338
369
|
const hookResponse = await hook.hookFn(ctx, resolver, response);
|
|
339
370
|
if(hookResponse instanceof Error){ throw hookResponse; }
|
|
340
371
|
response = hookResponse;
|
|
341
372
|
}
|
|
373
|
+
// Apply session cookie if needed.
|
|
374
|
+
if((ctx.session?.sessionToken ?? null) !== (ctx?.cookie?.[this.sessionTokenCookieKey] ?? null)){
|
|
375
|
+
// Add session cookies
|
|
376
|
+
if(ctx.session?.sessionToken){
|
|
377
|
+
response.multiValueHeaders = {
|
|
378
|
+
...(response.multiValueHeaders || {}),
|
|
379
|
+
"Set-Cookie": [
|
|
380
|
+
`${this.sessionTokenCookieKey}=${ctx.session.sessionToken}; Expires=${new Date(ctx.session.expiresAt * 1000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
381
|
+
`${this.sessionCsrfCookieKey}=${ctx.session.csrfToken}; Expires=${new Date(ctx.session.expiresAt * 1000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
}else{
|
|
385
|
+
// Delete session cookies
|
|
386
|
+
response.multiValueHeaders = {
|
|
387
|
+
...(response.multiValueHeaders || {}),
|
|
388
|
+
"Set-Cookie": [
|
|
389
|
+
`${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
390
|
+
`${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
391
|
+
],
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
342
395
|
resolve(response);
|
|
343
396
|
}else{
|
|
344
397
|
return this.handleNoMatchedAction(ctx, resolver);
|
|
345
398
|
}
|
|
399
|
+
|
|
346
400
|
} catch(err){
|
|
347
401
|
const wrappedError = err instanceof Error ? err : new Error("Error: " + String(err));
|
|
348
402
|
reject(wrappedError);
|
package/src/LambderCaller.ts
CHANGED
|
@@ -101,7 +101,7 @@ export default class LambderCaller {
|
|
|
101
101
|
activeFetchList: this.fetchTrackerList.filter(v=>!v.done)
|
|
102
102
|
});
|
|
103
103
|
const version = this.apiVersion;
|
|
104
|
-
const token = Cookies.get("
|
|
104
|
+
const token = Cookies.get("LMDRSESSIONCSTK") || "";
|
|
105
105
|
const siteHost = window.location.hostname;
|
|
106
106
|
let data = await fetch(this.apiPath, {
|
|
107
107
|
method: 'POST', mode: 'same-origin', cache: 'no-cache',
|
package/src/LambderSession.ts
CHANGED
|
@@ -116,6 +116,16 @@ export default class LambderSession{
|
|
|
116
116
|
return session;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
public async editSession(
|
|
120
|
+
session: LambderSessionContext,
|
|
121
|
+
newData?: any
|
|
122
|
+
): Promise<LambderSessionContext> {
|
|
123
|
+
if(!session) throw "Invalid session";
|
|
124
|
+
session.data = newData;
|
|
125
|
+
await this.ddbPutItem(session);
|
|
126
|
+
return session;
|
|
127
|
+
}
|
|
128
|
+
|
|
119
129
|
public async getSession(sessionToken: string): Promise<LambderSessionContext|null>{
|
|
120
130
|
const [ userKeyHash, sessionSortKey ] = sessionToken.split(":");
|
|
121
131
|
if(!userKeyHash || !sessionSortKey) return null;
|
package/src/index.ts
CHANGED
|
@@ -3,4 +3,5 @@ import Lambder from './Lambder.js';
|
|
|
3
3
|
export default Lambder;
|
|
4
4
|
export { default as LambderCaller } from "./LambderCaller.js";
|
|
5
5
|
export { default as LambderResponseBuilder } from "./LambderResponseBuilder.js";
|
|
6
|
-
export { default as LambderResolver } from "./LambderResolver.js";
|
|
6
|
+
export { default as LambderResolver } from "./LambderResolver.js";
|
|
7
|
+
export { default as LambderSession } from "./LambderSession.js";
|