@stone-js/aws-lambda-http-adapter 0.2.0 → 0.3.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/LICENSE +1 -1
- package/README.md +1 -1
- package/dist/index.d.ts +73 -45
- package/dist/index.js +408 -350
- package/package.json +17 -17
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://opensource.org/licenses/MIT)
|
|
4
4
|
[](https://www.npmjs.com/package/@stone-js/aws-lambda-http-adapter)
|
|
5
5
|
[](https://www.npmjs.com/package/@stone-js/aws-lambda-http-adapter)
|
|
6
|
-

|
|
7
7
|
[](https://github.com/stone-foundation/stone-js-aws-lambda-http-adapter/actions/workflows/main.yml)
|
|
8
8
|
[](https://github.com/stone-foundation/stone-js-aws-lambda-http-adapter/actions/workflows/release.yml)
|
|
9
9
|
[](https://sonarcloud.io/summary/new_code?id=stone-foundation_stone-js-aws-lambda-http-adapter)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IRawResponseWrapper, RawResponseOptions, AdapterContext, IAdapterEventBuilder, Adapter, IBlueprint, IAdapterErrorHandler, AdapterErrorContext, AdapterEventBuilderType, AdapterResolver, AdapterConfig,
|
|
1
|
+
import { IRawResponseWrapper, RawResponseOptions, AdapterContext, IAdapterEventBuilder, Adapter, IBlueprint, IAdapterErrorHandler, AdapterErrorContext, AdapterEventBuilderType, AdapterResolver, AdapterConfig, StoneBlueprint, AppConfig, ClassType, IntegrationError, ErrorOptions, BlueprintContext, NextMiddleware, MetaMiddleware } from '@stone-js/core';
|
|
2
2
|
import { IncomingHttpEvent, IncomingHttpEventOptions, OutgoingHttpResponse, HttpConfig } from '@stone-js/http-core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -59,6 +59,16 @@ declare class RawHttpResponseWrapper implements IRawResponseWrapper<RawHttpRespo
|
|
|
59
59
|
* ```
|
|
60
60
|
*/
|
|
61
61
|
respond(): RawHttpResponse;
|
|
62
|
+
/**
|
|
63
|
+
* Normalizes the headers to a consistent format.
|
|
64
|
+
*
|
|
65
|
+
* Converts Headers or Record<string, string> to a normalized Record<string, string>
|
|
66
|
+
* with all keys in lowercase.
|
|
67
|
+
*
|
|
68
|
+
* @param headers - The headers to normalize.
|
|
69
|
+
* @returns A normalized record of headers.
|
|
70
|
+
*/
|
|
71
|
+
private normalizeHeaders;
|
|
62
72
|
}
|
|
63
73
|
|
|
64
74
|
/**
|
|
@@ -451,6 +461,24 @@ declare class BodyEventMiddleware {
|
|
|
451
461
|
* @throws {AwsLambdaHttpAdapterError} If the body parsing fails or is invalid.
|
|
452
462
|
*/
|
|
453
463
|
private getBody;
|
|
464
|
+
/**
|
|
465
|
+
* Get the normalized raw body from the event.
|
|
466
|
+
*
|
|
467
|
+
* @param rawEvent - The raw event containing the body.
|
|
468
|
+
* @param encoding - The encoding to use for the body.
|
|
469
|
+
* @returns The normalized body as a string.
|
|
470
|
+
*/
|
|
471
|
+
private getNormalizedRawBody;
|
|
472
|
+
/**
|
|
473
|
+
* Parse the body content based on the specified type and encoding.
|
|
474
|
+
*
|
|
475
|
+
* @param type - The content type of the body.
|
|
476
|
+
* @param body - The raw body content as a string.
|
|
477
|
+
* @param encoding - The encoding of the body content.
|
|
478
|
+
* @returns The parsed body content as an object, string, or Buffer.
|
|
479
|
+
* @throws {AwsLambdaHttpAdapterError} If parsing fails.
|
|
480
|
+
*/
|
|
481
|
+
private parseBodyContent;
|
|
454
482
|
}
|
|
455
483
|
/**
|
|
456
484
|
* Meta Middleware for processing the request body.
|
|
@@ -460,6 +488,50 @@ declare const MetaBodyEventMiddleware: {
|
|
|
460
488
|
isClass: boolean;
|
|
461
489
|
};
|
|
462
490
|
|
|
491
|
+
/**
|
|
492
|
+
* Class representing a FilesEventMiddleware.
|
|
493
|
+
*
|
|
494
|
+
* @author Mr. Stone <evensstone@gmail.com>
|
|
495
|
+
*/
|
|
496
|
+
declare class FilesEventMiddleware {
|
|
497
|
+
/**
|
|
498
|
+
* The blueprint for resolving configuration and dependencies.
|
|
499
|
+
*/
|
|
500
|
+
private readonly blueprint;
|
|
501
|
+
/**
|
|
502
|
+
* Create a FilesEventMiddleware.
|
|
503
|
+
*
|
|
504
|
+
* @param {blueprint} options - Options for creating the FilesEventMiddleware.
|
|
505
|
+
*/
|
|
506
|
+
constructor({ blueprint }: {
|
|
507
|
+
blueprint: IBlueprint;
|
|
508
|
+
});
|
|
509
|
+
/**
|
|
510
|
+
* Handles the incoming event, processes it, and invokes the next middleware in the pipeline.
|
|
511
|
+
*
|
|
512
|
+
* @param context - The adapter context containing the raw event, execution context, and other data.
|
|
513
|
+
* @param next - The next middleware to be invoked in the pipeline.
|
|
514
|
+
* @returns A promise that resolves to the destination type after processing.
|
|
515
|
+
*
|
|
516
|
+
* @throws {AwsLambdaHttpAdapterError} If required components such as the rawEvent or IncomingEventBuilder are not provided.
|
|
517
|
+
*/
|
|
518
|
+
handle(context: AwsLambdaHttpAdapterContext, next: NextMiddleware<AwsLambdaHttpAdapterContext, AwsLambdaHttpAdapterResponseBuilder>): Promise<AwsLambdaHttpAdapterResponseBuilder>;
|
|
519
|
+
/**
|
|
520
|
+
* Normalize the incoming event to an IncomingMessage.
|
|
521
|
+
*
|
|
522
|
+
* @param rawEvent - The raw event to be normalized.
|
|
523
|
+
* @returns The normalized event.
|
|
524
|
+
*/
|
|
525
|
+
private normalizeEvent;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Meta Middleware for processing files uploads.
|
|
529
|
+
*/
|
|
530
|
+
declare const MetaFilesEventMiddleware: {
|
|
531
|
+
module: typeof FilesEventMiddleware;
|
|
532
|
+
isClass: boolean;
|
|
533
|
+
};
|
|
534
|
+
|
|
463
535
|
/**
|
|
464
536
|
* Middleware for handling incoming events and transforming them into Stone.js events.
|
|
465
537
|
*
|
|
@@ -567,50 +639,6 @@ declare const MetaIncomingEventMiddleware: {
|
|
|
567
639
|
isClass: boolean;
|
|
568
640
|
};
|
|
569
641
|
|
|
570
|
-
/**
|
|
571
|
-
* Class representing a FilesEventMiddleware.
|
|
572
|
-
*
|
|
573
|
-
* @author Mr. Stone <evensstone@gmail.com>
|
|
574
|
-
*/
|
|
575
|
-
declare class FilesEventMiddleware {
|
|
576
|
-
/**
|
|
577
|
-
* The blueprint for resolving configuration and dependencies.
|
|
578
|
-
*/
|
|
579
|
-
private readonly blueprint;
|
|
580
|
-
/**
|
|
581
|
-
* Create a FilesEventMiddleware.
|
|
582
|
-
*
|
|
583
|
-
* @param {blueprint} options - Options for creating the FilesEventMiddleware.
|
|
584
|
-
*/
|
|
585
|
-
constructor({ blueprint }: {
|
|
586
|
-
blueprint: IBlueprint;
|
|
587
|
-
});
|
|
588
|
-
/**
|
|
589
|
-
* Handles the incoming event, processes it, and invokes the next middleware in the pipeline.
|
|
590
|
-
*
|
|
591
|
-
* @param context - The adapter context containing the raw event, execution context, and other data.
|
|
592
|
-
* @param next - The next middleware to be invoked in the pipeline.
|
|
593
|
-
* @returns A promise that resolves to the destination type after processing.
|
|
594
|
-
*
|
|
595
|
-
* @throws {AwsLambdaHttpAdapterError} If required components such as the rawEvent or IncomingEventBuilder are not provided.
|
|
596
|
-
*/
|
|
597
|
-
handle(context: AwsLambdaHttpAdapterContext, next: NextMiddleware<AwsLambdaHttpAdapterContext, AwsLambdaHttpAdapterResponseBuilder>): Promise<AwsLambdaHttpAdapterResponseBuilder>;
|
|
598
|
-
/**
|
|
599
|
-
* Normalize the incoming event to an IncomingMessage.
|
|
600
|
-
*
|
|
601
|
-
* @param rawEvent - The raw event to be normalized.
|
|
602
|
-
* @returns The normalized event.
|
|
603
|
-
*/
|
|
604
|
-
private normalizeEvent;
|
|
605
|
-
}
|
|
606
|
-
/**
|
|
607
|
-
* Meta Middleware for processing files uploads.
|
|
608
|
-
*/
|
|
609
|
-
declare const MetaFilesEventMiddleware: {
|
|
610
|
-
module: typeof FilesEventMiddleware;
|
|
611
|
-
isClass: boolean;
|
|
612
|
-
};
|
|
613
|
-
|
|
614
642
|
/**
|
|
615
643
|
* Middleware for handling server responses and transforming them into the appropriate HTTP responses.
|
|
616
644
|
*
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,47 @@
|
|
|
1
|
-
import { IntegrationError, Adapter, AdapterEventBuilder,
|
|
2
|
-
import { IncomingHttpEvent, HTTP_INTERNAL_SERVER_ERROR, BinaryFileResponse, OutgoingHttpResponse, CookieCollection, isIpTrusted, getHostname, getProtocol, httpCoreBlueprint, isMultipart, getCharset, getType, getFilesUploads } from '@stone-js/http-core';
|
|
1
|
+
import { defaultLoggerResolver, IntegrationError, Adapter, AdapterEventBuilder, isNotEmpty, defaultKernelResolver, classDecoratorLegacyWrapper, addBlueprint } from '@stone-js/core';
|
|
3
2
|
import mime from 'mime';
|
|
4
3
|
import accepts from 'accepts';
|
|
5
4
|
import statuses from 'statuses';
|
|
6
|
-
import {
|
|
5
|
+
import { HTTP_INTERNAL_SERVER_ERROR, IncomingHttpEvent, BinaryFileResponse, OutgoingHttpResponse, isMultipart, getFilesUploads, CookieCollection, isIpTrusted, getHostname, getProtocol, getCharset, httpCoreBlueprint } from '@stone-js/http-core';
|
|
7
6
|
import { File } from '@stone-js/filesystem';
|
|
8
7
|
import proxyAddr from 'proxy-addr';
|
|
9
8
|
import bytes from 'bytes';
|
|
10
9
|
import typeIs from 'type-is';
|
|
10
|
+
import { getString } from '@stone-js/env';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Class representing an AwsLambdaHttpErrorHandler.
|
|
14
|
+
*/
|
|
15
|
+
class AwsLambdaHttpErrorHandler {
|
|
16
|
+
logger;
|
|
17
|
+
/**
|
|
18
|
+
* Create an NodeHttpErrorHandler.
|
|
19
|
+
*
|
|
20
|
+
* @param options - NodeHttpErrorHandler options.
|
|
21
|
+
*/
|
|
22
|
+
constructor({ blueprint }) {
|
|
23
|
+
this.logger = blueprint.get('stone.logger.resolver', defaultLoggerResolver)(blueprint);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Handle an error.
|
|
27
|
+
*
|
|
28
|
+
* @param error - The error to handle.
|
|
29
|
+
* @param context - The context of the adapter.
|
|
30
|
+
* @returns The raw response builder.
|
|
31
|
+
*/
|
|
32
|
+
handle(error, context) {
|
|
33
|
+
this.logger.error(error.message, { error });
|
|
34
|
+
const statusCode = error.cause?.status ?? HTTP_INTERNAL_SERVER_ERROR;
|
|
35
|
+
const type = accepts(context.rawEvent).type(['json', 'html']);
|
|
36
|
+
const contentType = mime.getType(type !== false ? type : 'txt') ?? context.rawEvent.headers['content-type'] ?? 'text/plain';
|
|
37
|
+
const headers = new Headers({ 'Content-Type': contentType });
|
|
38
|
+
return context
|
|
39
|
+
.rawResponseBuilder
|
|
40
|
+
.add('headers', headers)
|
|
41
|
+
.add('statusCode', statusCode)
|
|
42
|
+
.add('statusMessage', statuses.message[statusCode]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
11
45
|
|
|
12
46
|
/**
|
|
13
47
|
* Wrapper for HTTP raw responses in AWS Lambda.
|
|
@@ -73,9 +107,22 @@ class RawHttpResponseWrapper {
|
|
|
73
107
|
respond() {
|
|
74
108
|
return {
|
|
75
109
|
...this.options,
|
|
76
|
-
statusCode: this.options.statusCode ?? 500
|
|
110
|
+
statusCode: this.options.statusCode ?? 500,
|
|
111
|
+
headers: this.normalizeHeaders(this.options.headers)
|
|
77
112
|
};
|
|
78
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Normalizes the headers to a consistent format.
|
|
116
|
+
*
|
|
117
|
+
* Converts Headers or Record<string, string> to a normalized Record<string, string>
|
|
118
|
+
* with all keys in lowercase.
|
|
119
|
+
*
|
|
120
|
+
* @param headers - The headers to normalize.
|
|
121
|
+
* @returns A normalized record of headers.
|
|
122
|
+
*/
|
|
123
|
+
normalizeHeaders(headers) {
|
|
124
|
+
return Object.fromEntries(new Headers(headers ?? {}));
|
|
125
|
+
}
|
|
79
126
|
}
|
|
80
127
|
|
|
81
128
|
/**
|
|
@@ -208,40 +255,6 @@ class AwsLambdaHttpAdapter extends Adapter {
|
|
|
208
255
|
}
|
|
209
256
|
}
|
|
210
257
|
|
|
211
|
-
/**
|
|
212
|
-
* Class representing an AwsLambdaHttpErrorHandler.
|
|
213
|
-
*/
|
|
214
|
-
class AwsLambdaHttpErrorHandler {
|
|
215
|
-
logger;
|
|
216
|
-
/**
|
|
217
|
-
* Create an NodeHttpErrorHandler.
|
|
218
|
-
*
|
|
219
|
-
* @param options - NodeHttpErrorHandler options.
|
|
220
|
-
*/
|
|
221
|
-
constructor({ blueprint }) {
|
|
222
|
-
this.logger = blueprint.get('stone.logger.resolver', defaultLoggerResolver)(blueprint);
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Handle an error.
|
|
226
|
-
*
|
|
227
|
-
* @param error - The error to handle.
|
|
228
|
-
* @param context - The context of the adapter.
|
|
229
|
-
* @returns The raw response builder.
|
|
230
|
-
*/
|
|
231
|
-
handle(error, context) {
|
|
232
|
-
this.logger.error(error.message, { error });
|
|
233
|
-
const statusCode = error.cause?.status ?? HTTP_INTERNAL_SERVER_ERROR;
|
|
234
|
-
const type = accepts(context.rawEvent).type(['json', 'html']);
|
|
235
|
-
const contentType = mime.getType(type !== false ? type : 'txt') ?? context.rawEvent.headers['content-type'] ?? 'text/plain';
|
|
236
|
-
const headers = new Headers({ 'Content-Type': contentType });
|
|
237
|
-
return context
|
|
238
|
-
.rawResponseBuilder
|
|
239
|
-
.add('headers', headers)
|
|
240
|
-
.add('statusCode', statusCode)
|
|
241
|
-
.add('statusMessage', statuses.message[statusCode]);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
258
|
/**
|
|
246
259
|
* A constant representing the AWS Lambda HTTP platform identifier.
|
|
247
260
|
*
|
|
@@ -263,154 +276,6 @@ const awsLambdaHttpAdapterResolver = (blueprint) => {
|
|
|
263
276
|
return AwsLambdaHttpAdapter.create(blueprint);
|
|
264
277
|
};
|
|
265
278
|
|
|
266
|
-
function getDefaultExportFromCjs (x) {
|
|
267
|
-
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
var cjs;
|
|
271
|
-
var hasRequiredCjs;
|
|
272
|
-
|
|
273
|
-
function requireCjs () {
|
|
274
|
-
if (hasRequiredCjs) return cjs;
|
|
275
|
-
hasRequiredCjs = 1;
|
|
276
|
-
|
|
277
|
-
var isMergeableObject = function isMergeableObject(value) {
|
|
278
|
-
return isNonNullObject(value)
|
|
279
|
-
&& !isSpecial(value)
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
function isNonNullObject(value) {
|
|
283
|
-
return !!value && typeof value === 'object'
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function isSpecial(value) {
|
|
287
|
-
var stringValue = Object.prototype.toString.call(value);
|
|
288
|
-
|
|
289
|
-
return stringValue === '[object RegExp]'
|
|
290
|
-
|| stringValue === '[object Date]'
|
|
291
|
-
|| isReactElement(value)
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25
|
|
295
|
-
var canUseSymbol = typeof Symbol === 'function' && Symbol.for;
|
|
296
|
-
var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;
|
|
297
|
-
|
|
298
|
-
function isReactElement(value) {
|
|
299
|
-
return value.$$typeof === REACT_ELEMENT_TYPE
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
function emptyTarget(val) {
|
|
303
|
-
return Array.isArray(val) ? [] : {}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function cloneUnlessOtherwiseSpecified(value, options) {
|
|
307
|
-
return (options.clone !== false && options.isMergeableObject(value))
|
|
308
|
-
? deepmerge(emptyTarget(value), value, options)
|
|
309
|
-
: value
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
function defaultArrayMerge(target, source, options) {
|
|
313
|
-
return target.concat(source).map(function(element) {
|
|
314
|
-
return cloneUnlessOtherwiseSpecified(element, options)
|
|
315
|
-
})
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
function getMergeFunction(key, options) {
|
|
319
|
-
if (!options.customMerge) {
|
|
320
|
-
return deepmerge
|
|
321
|
-
}
|
|
322
|
-
var customMerge = options.customMerge(key);
|
|
323
|
-
return typeof customMerge === 'function' ? customMerge : deepmerge
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
function getEnumerableOwnPropertySymbols(target) {
|
|
327
|
-
return Object.getOwnPropertySymbols
|
|
328
|
-
? Object.getOwnPropertySymbols(target).filter(function(symbol) {
|
|
329
|
-
return Object.propertyIsEnumerable.call(target, symbol)
|
|
330
|
-
})
|
|
331
|
-
: []
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
function getKeys(target) {
|
|
335
|
-
return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function propertyIsOnObject(object, property) {
|
|
339
|
-
try {
|
|
340
|
-
return property in object
|
|
341
|
-
} catch(_) {
|
|
342
|
-
return false
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Protects from prototype poisoning and unexpected merging up the prototype chain.
|
|
347
|
-
function propertyIsUnsafe(target, key) {
|
|
348
|
-
return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
|
|
349
|
-
&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
|
|
350
|
-
&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
function mergeObject(target, source, options) {
|
|
354
|
-
var destination = {};
|
|
355
|
-
if (options.isMergeableObject(target)) {
|
|
356
|
-
getKeys(target).forEach(function(key) {
|
|
357
|
-
destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
getKeys(source).forEach(function(key) {
|
|
361
|
-
if (propertyIsUnsafe(target, key)) {
|
|
362
|
-
return
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {
|
|
366
|
-
destination[key] = getMergeFunction(key, options)(target[key], source[key], options);
|
|
367
|
-
} else {
|
|
368
|
-
destination[key] = cloneUnlessOtherwiseSpecified(source[key], options);
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
return destination
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function deepmerge(target, source, options) {
|
|
375
|
-
options = options || {};
|
|
376
|
-
options.arrayMerge = options.arrayMerge || defaultArrayMerge;
|
|
377
|
-
options.isMergeableObject = options.isMergeableObject || isMergeableObject;
|
|
378
|
-
// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
|
|
379
|
-
// implementations can use it. The caller may not replace it.
|
|
380
|
-
options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
|
|
381
|
-
|
|
382
|
-
var sourceIsArray = Array.isArray(source);
|
|
383
|
-
var targetIsArray = Array.isArray(target);
|
|
384
|
-
var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
|
|
385
|
-
|
|
386
|
-
if (!sourceAndTargetTypesMatch) {
|
|
387
|
-
return cloneUnlessOtherwiseSpecified(source, options)
|
|
388
|
-
} else if (sourceIsArray) {
|
|
389
|
-
return options.arrayMerge(target, source, options)
|
|
390
|
-
} else {
|
|
391
|
-
return mergeObject(target, source, options)
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
deepmerge.all = function deepmergeAll(array, options) {
|
|
396
|
-
if (!Array.isArray(array)) {
|
|
397
|
-
throw new Error('first argument should be an array')
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
return array.reduce(function(prev, next) {
|
|
401
|
-
return deepmerge(prev, next, options)
|
|
402
|
-
}, {})
|
|
403
|
-
};
|
|
404
|
-
|
|
405
|
-
var deepmerge_1 = deepmerge;
|
|
406
|
-
|
|
407
|
-
cjs = deepmerge_1;
|
|
408
|
-
return cjs;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
var cjsExports = requireCjs();
|
|
412
|
-
var deepmerge = /*@__PURE__*/getDefaultExportFromCjs(cjsExports);
|
|
413
|
-
|
|
414
279
|
/**
|
|
415
280
|
* Middleware to dynamically set response resolver for adapter.
|
|
416
281
|
*
|
|
@@ -444,20 +309,19 @@ const metaAdapterBlueprintMiddleware = [
|
|
|
444
309
|
];
|
|
445
310
|
|
|
446
311
|
/**
|
|
447
|
-
*
|
|
312
|
+
* Class representing a FilesEventMiddleware.
|
|
448
313
|
*
|
|
449
|
-
*
|
|
450
|
-
* headers, cookies, and more, and forwards them to the next middleware in the pipeline.
|
|
314
|
+
* @author Mr. Stone <evensstone@gmail.com>
|
|
451
315
|
*/
|
|
452
|
-
class
|
|
316
|
+
class FilesEventMiddleware {
|
|
453
317
|
/**
|
|
454
318
|
* The blueprint for resolving configuration and dependencies.
|
|
455
319
|
*/
|
|
456
320
|
blueprint;
|
|
457
321
|
/**
|
|
458
|
-
* Create
|
|
322
|
+
* Create a FilesEventMiddleware.
|
|
459
323
|
*
|
|
460
|
-
* @param {blueprint} options - Options
|
|
324
|
+
* @param {blueprint} options - Options for creating the FilesEventMiddleware.
|
|
461
325
|
*/
|
|
462
326
|
constructor({ blueprint }) {
|
|
463
327
|
this.blueprint = blueprint;
|
|
@@ -467,28 +331,101 @@ class IncomingEventMiddleware {
|
|
|
467
331
|
*
|
|
468
332
|
* @param context - The adapter context containing the raw event, execution context, and other data.
|
|
469
333
|
* @param next - The next middleware to be invoked in the pipeline.
|
|
470
|
-
* @returns A promise that resolves to the
|
|
471
|
-
*
|
|
334
|
+
* @returns A promise that resolves to the destination type after processing.
|
|
335
|
+
*
|
|
336
|
+
* @throws {AwsLambdaHttpAdapterError} If required components such as the rawEvent or IncomingEventBuilder are not provided.
|
|
472
337
|
*/
|
|
473
338
|
async handle(context, next) {
|
|
474
|
-
if (
|
|
339
|
+
if (context.rawEvent === undefined || context.incomingEventBuilder?.add === undefined) {
|
|
475
340
|
throw new AwsLambdaHttpAdapterError('The context is missing required components.');
|
|
476
341
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
.add('
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
342
|
+
if (isMultipart(this.normalizeEvent(context.rawEvent))) {
|
|
343
|
+
const options = this.blueprint.get('stone.http.files.upload', {});
|
|
344
|
+
const response = await getFilesUploads(this.normalizeEvent(context.rawEvent), options);
|
|
345
|
+
const method = response.fields.$method$;
|
|
346
|
+
context
|
|
347
|
+
.incomingEventBuilder
|
|
348
|
+
.add('files', response.files)
|
|
349
|
+
.add('body', response.fields);
|
|
350
|
+
// In fullstack forms, the method is spoofed and sent as a hidden field
|
|
351
|
+
isNotEmpty(method) && context.incomingEventBuilder.add('method', method);
|
|
352
|
+
}
|
|
353
|
+
return await next(context);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Normalize the incoming event to an IncomingMessage.
|
|
357
|
+
*
|
|
358
|
+
* @param rawEvent - The raw event to be normalized.
|
|
359
|
+
* @returns The normalized event.
|
|
360
|
+
*/
|
|
361
|
+
normalizeEvent(rawEvent) {
|
|
362
|
+
let body = rawEvent.body;
|
|
363
|
+
if (typeof rawEvent.body === 'string') {
|
|
364
|
+
body = rawEvent.isBase64Encoded === true
|
|
365
|
+
? Buffer.from(rawEvent.body, 'base64')
|
|
366
|
+
: Buffer.from(rawEvent.body, 'utf-8');
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
body,
|
|
370
|
+
headers: {
|
|
371
|
+
'content-type': rawEvent.headers['content-type'] ?? rawEvent.headers['Content-Type'],
|
|
372
|
+
'content-length': rawEvent.headers['content-length'] ?? rawEvent.headers['Content-Length'],
|
|
373
|
+
'transfer-encoding': rawEvent.headers['transfer-encoding'] ?? rawEvent.headers['Transfer-Encoding']
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Meta Middleware for processing files uploads.
|
|
380
|
+
*/
|
|
381
|
+
const MetaFilesEventMiddleware = { module: FilesEventMiddleware, isClass: true };
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Middleware for handling incoming events and transforming them into Stone.js events.
|
|
385
|
+
*
|
|
386
|
+
* This class processes incoming HTTP requests, extracting relevant data such as URL, IP addresses,
|
|
387
|
+
* headers, cookies, and more, and forwards them to the next middleware in the pipeline.
|
|
388
|
+
*/
|
|
389
|
+
class IncomingEventMiddleware {
|
|
390
|
+
/**
|
|
391
|
+
* The blueprint for resolving configuration and dependencies.
|
|
392
|
+
*/
|
|
393
|
+
blueprint;
|
|
394
|
+
/**
|
|
395
|
+
* Create an IncomingEventMiddleware instance.
|
|
396
|
+
*
|
|
397
|
+
* @param {blueprint} options - Options containing the blueprint for resolving configuration and dependencies.
|
|
398
|
+
*/
|
|
399
|
+
constructor({ blueprint }) {
|
|
400
|
+
this.blueprint = blueprint;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Handles the incoming event, processes it, and invokes the next middleware in the pipeline.
|
|
404
|
+
*
|
|
405
|
+
* @param context - The adapter context containing the raw event, execution context, and other data.
|
|
406
|
+
* @param next - The next middleware to be invoked in the pipeline.
|
|
407
|
+
* @returns A promise that resolves to the processed context.
|
|
408
|
+
* @throws {AwsLambdaHttpAdapterError} If required components are missing in the context.
|
|
409
|
+
*/
|
|
410
|
+
async handle(context, next) {
|
|
411
|
+
if ((context.rawEvent === undefined) || ((context.incomingEventBuilder?.add) === undefined)) {
|
|
412
|
+
throw new AwsLambdaHttpAdapterError('The context is missing required components.');
|
|
413
|
+
}
|
|
414
|
+
const proxyOptions = this.getProxyOptions();
|
|
415
|
+
const cookieOptions = this.getCookieOptions();
|
|
416
|
+
const url = this.extractUrl(context.rawEvent, proxyOptions);
|
|
417
|
+
const ipAddresses = this.extractIpAddresses(context.rawEvent, proxyOptions);
|
|
418
|
+
context
|
|
419
|
+
.incomingEventBuilder
|
|
420
|
+
.add('url', url)
|
|
421
|
+
.add('ips', ipAddresses)
|
|
422
|
+
.add('source', this.getSource(context))
|
|
423
|
+
.add('headers', context.rawEvent.headers)
|
|
424
|
+
// If not defined by other middleware
|
|
425
|
+
// In fullstack forms, the method is spoofed and sent as a hidden field
|
|
426
|
+
.addIf('method', this.getMethod(context.rawEvent))
|
|
427
|
+
.add('queryString', context.rawEvent.queryStringParameters)
|
|
428
|
+
.add('protocol', this.getProtocol(context.rawEvent, proxyOptions))
|
|
492
429
|
.add('cookies', CookieCollection.create(context.rawEvent.headers.cookie, cookieOptions, this.getCookieSecret()))
|
|
493
430
|
.add('ip', proxyAddr(this.toNodeMessage(context.rawEvent), isIpTrusted(proxyOptions.trustedIp, proxyOptions.untrustedIp)));
|
|
494
431
|
return await next(context);
|
|
@@ -654,77 +591,6 @@ class ServerResponseMiddleware {
|
|
|
654
591
|
*/
|
|
655
592
|
const MetaServerResponseMiddleware = { module: ServerResponseMiddleware, isClass: true };
|
|
656
593
|
|
|
657
|
-
/**
|
|
658
|
-
* Default blueprint configuration for the AWS Lambda Http Adapter.
|
|
659
|
-
*
|
|
660
|
-
* This blueprint defines the initial configuration for the AWS Lambda Http adapter
|
|
661
|
-
* within the Stone.js framework. It includes:
|
|
662
|
-
* - An alias for the AWS Lambda platform (`AWS_LAMBDA_HTTP_PLATFORM`).
|
|
663
|
-
* - A default resolver function (currently a placeholder).
|
|
664
|
-
* - Middleware, hooks, and state flags (`current`, `default`, `preferred`).
|
|
665
|
-
*/
|
|
666
|
-
const awsLambdaHttpAdapterBlueprint = {
|
|
667
|
-
stone: {
|
|
668
|
-
...httpCoreBlueprint.stone,
|
|
669
|
-
blueprint: {
|
|
670
|
-
middleware: metaAdapterBlueprintMiddleware
|
|
671
|
-
},
|
|
672
|
-
adapters: [
|
|
673
|
-
{
|
|
674
|
-
current: false,
|
|
675
|
-
variant: 'server',
|
|
676
|
-
platform: AWS_LAMBDA_HTTP_PLATFORM,
|
|
677
|
-
middleware: [
|
|
678
|
-
MetaIncomingEventMiddleware,
|
|
679
|
-
MetaServerResponseMiddleware
|
|
680
|
-
],
|
|
681
|
-
resolver: awsLambdaHttpAdapterResolver,
|
|
682
|
-
eventHandlerResolver: defaultKernelResolver,
|
|
683
|
-
errorHandlers: {
|
|
684
|
-
default: { module: AwsLambdaHttpErrorHandler, isClass: true }
|
|
685
|
-
},
|
|
686
|
-
default: isNotEmpty(getString('AWS_LAMBDA_FUNCTION_NAME', ''))
|
|
687
|
-
}
|
|
688
|
-
]
|
|
689
|
-
}
|
|
690
|
-
};
|
|
691
|
-
|
|
692
|
-
/**
|
|
693
|
-
* A Stone.js decorator that integrates the AWS Lambda HTTP Adapter with a class.
|
|
694
|
-
*
|
|
695
|
-
* This decorator modifies the class to seamlessly enable AWS Lambda HTTP as the
|
|
696
|
-
* execution environment for a Stone.js application. By applying this decorator,
|
|
697
|
-
* the class is automatically configured with the necessary blueprint for AWS Lambda HTTP.
|
|
698
|
-
*
|
|
699
|
-
* @template T - The type of the class being decorated. Defaults to `ClassType`.
|
|
700
|
-
* @param options - Optional configuration to customize the AWS Lambda HTTP Adapter.
|
|
701
|
-
*
|
|
702
|
-
* @returns A class decorator that applies the AWS Lambda HTTP adapter configuration.
|
|
703
|
-
*
|
|
704
|
-
* @example
|
|
705
|
-
* ```typescript
|
|
706
|
-
* import { AwsLambdaHttp } from '@stone-js/aws-lambda-http-adapter';
|
|
707
|
-
*
|
|
708
|
-
* @AwsLambdaHttp({
|
|
709
|
-
* alias: 'MyAwsLambdaHttpAdapter',
|
|
710
|
-
* current: true,
|
|
711
|
-
* })
|
|
712
|
-
* class App {
|
|
713
|
-
* // Your application logic here
|
|
714
|
-
* }
|
|
715
|
-
* ```
|
|
716
|
-
*/
|
|
717
|
-
const AwsLambdaHttp = (options = {}) => {
|
|
718
|
-
return classDecoratorLegacyWrapper((target, context) => {
|
|
719
|
-
if (awsLambdaHttpAdapterBlueprint.stone?.adapters?.[0] !== undefined) {
|
|
720
|
-
// Merge provided options with the default AWS Lambda HTTP adapter blueprint.
|
|
721
|
-
awsLambdaHttpAdapterBlueprint.stone.adapters[0] = deepmerge(awsLambdaHttpAdapterBlueprint.stone.adapters[0], options);
|
|
722
|
-
}
|
|
723
|
-
// Add the modified blueprint to the target class.
|
|
724
|
-
addBlueprint(target, context, awsLambdaHttpAdapterBlueprint);
|
|
725
|
-
});
|
|
726
|
-
};
|
|
727
|
-
|
|
728
594
|
/**
|
|
729
595
|
* Class representing a BodyEventMiddleware.
|
|
730
596
|
*
|
|
@@ -800,90 +666,282 @@ class BodyEventMiddleware {
|
|
|
800
666
|
const { defaultType, defaultCharset, limit: rawLimit } = this.blueprint.get('stone.http.body', defaultOptions);
|
|
801
667
|
const limit = bytes.parse(rawLimit) ?? 100000;
|
|
802
668
|
const encoding = getCharset(message, defaultCharset);
|
|
803
|
-
const type =
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
const stringifiedBody = typeof rawEvent.body === 'string'
|
|
808
|
-
? rawEvent.body
|
|
809
|
-
: (typeof rawEvent.body === 'object' && rawEvent.body !== null
|
|
810
|
-
? JSON.stringify(rawEvent.body)
|
|
811
|
-
: '');
|
|
812
|
-
if (Buffer.byteLength(stringifiedBody, encoding) > limit) {
|
|
813
|
-
throw new AwsLambdaHttpAdapterError('The context is missing required components.');
|
|
669
|
+
const type = typeIs(message, ['urlencoded', 'json', 'text', 'bin']) ?? defaultType;
|
|
670
|
+
const rawBodyContent = this.getNormalizedRawBody(rawEvent, encoding);
|
|
671
|
+
if (Buffer.byteLength(rawBodyContent, encoding) > limit) {
|
|
672
|
+
throw new AwsLambdaHttpAdapterError('Body payload exceeds configured limit.');
|
|
814
673
|
}
|
|
815
|
-
return
|
|
674
|
+
return this.parseBodyContent(type, rawBodyContent, encoding);
|
|
816
675
|
}
|
|
817
|
-
}
|
|
818
|
-
/**
|
|
819
|
-
* Meta Middleware for processing the request body.
|
|
820
|
-
*/
|
|
821
|
-
const MetaBodyEventMiddleware = { module: BodyEventMiddleware, isClass: true };
|
|
822
|
-
|
|
823
|
-
/**
|
|
824
|
-
* Class representing a FilesEventMiddleware.
|
|
825
|
-
*
|
|
826
|
-
* @author Mr. Stone <evensstone@gmail.com>
|
|
827
|
-
*/
|
|
828
|
-
class FilesEventMiddleware {
|
|
829
|
-
/**
|
|
830
|
-
* The blueprint for resolving configuration and dependencies.
|
|
831
|
-
*/
|
|
832
|
-
blueprint;
|
|
833
676
|
/**
|
|
834
|
-
*
|
|
677
|
+
* Get the normalized raw body from the event.
|
|
835
678
|
*
|
|
836
|
-
* @param
|
|
679
|
+
* @param rawEvent - The raw event containing the body.
|
|
680
|
+
* @param encoding - The encoding to use for the body.
|
|
681
|
+
* @returns The normalized body as a string.
|
|
837
682
|
*/
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
*
|
|
844
|
-
* @param context - The adapter context containing the raw event, execution context, and other data.
|
|
845
|
-
* @param next - The next middleware to be invoked in the pipeline.
|
|
846
|
-
* @returns A promise that resolves to the destination type after processing.
|
|
847
|
-
*
|
|
848
|
-
* @throws {AwsLambdaHttpAdapterError} If required components such as the rawEvent or IncomingEventBuilder are not provided.
|
|
849
|
-
*/
|
|
850
|
-
async handle(context, next) {
|
|
851
|
-
if (context.rawEvent === undefined || context.incomingEventBuilder?.add === undefined) {
|
|
852
|
-
throw new AwsLambdaHttpAdapterError('The context is missing required components.');
|
|
683
|
+
getNormalizedRawBody(rawEvent, encoding) {
|
|
684
|
+
if (typeof rawEvent.body === 'string') {
|
|
685
|
+
return rawEvent.isBase64Encoded === true
|
|
686
|
+
? Buffer.from(rawEvent.body, 'base64').toString(encoding)
|
|
687
|
+
: rawEvent.body;
|
|
853
688
|
}
|
|
854
|
-
if (
|
|
855
|
-
|
|
856
|
-
const response = await getFilesUploads(this.normalizeEvent(context.rawEvent), options);
|
|
857
|
-
const method = response.fields.$method$;
|
|
858
|
-
context
|
|
859
|
-
.incomingEventBuilder
|
|
860
|
-
.add('files', response.files)
|
|
861
|
-
.add('body', response.fields);
|
|
862
|
-
// In fullstack forms, the method is spoofed and sent as a hidden field
|
|
863
|
-
isNotEmpty(method) && context.incomingEventBuilder.add('method', method);
|
|
689
|
+
if (typeof rawEvent.body === 'object' && rawEvent.body !== null) {
|
|
690
|
+
return JSON.stringify(rawEvent.body);
|
|
864
691
|
}
|
|
865
|
-
return
|
|
692
|
+
return '';
|
|
866
693
|
}
|
|
867
694
|
/**
|
|
868
|
-
*
|
|
695
|
+
* Parse the body content based on the specified type and encoding.
|
|
869
696
|
*
|
|
870
|
-
* @param
|
|
871
|
-
* @
|
|
697
|
+
* @param type - The content type of the body.
|
|
698
|
+
* @param body - The raw body content as a string.
|
|
699
|
+
* @param encoding - The encoding of the body content.
|
|
700
|
+
* @returns The parsed body content as an object, string, or Buffer.
|
|
701
|
+
* @throws {AwsLambdaHttpAdapterError} If parsing fails.
|
|
872
702
|
*/
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
'
|
|
879
|
-
|
|
703
|
+
parseBodyContent(type, body, encoding) {
|
|
704
|
+
try {
|
|
705
|
+
switch (type) {
|
|
706
|
+
case 'json':
|
|
707
|
+
return isNotEmpty(body) ? JSON.parse(body) : {};
|
|
708
|
+
case 'text':
|
|
709
|
+
return body;
|
|
710
|
+
case 'urlencoded':
|
|
711
|
+
return new URLSearchParams(body);
|
|
712
|
+
case 'bin':
|
|
713
|
+
return Buffer.from(body, encoding);
|
|
714
|
+
default:
|
|
715
|
+
return {};
|
|
880
716
|
}
|
|
881
|
-
}
|
|
717
|
+
}
|
|
718
|
+
catch (error) {
|
|
719
|
+
throw new AwsLambdaHttpAdapterError('Failed to parse request body.', { cause: error });
|
|
720
|
+
}
|
|
882
721
|
}
|
|
883
722
|
}
|
|
884
723
|
/**
|
|
885
|
-
* Meta Middleware for processing
|
|
724
|
+
* Meta Middleware for processing the request body.
|
|
886
725
|
*/
|
|
887
|
-
const
|
|
726
|
+
const MetaBodyEventMiddleware = { module: BodyEventMiddleware, isClass: true };
|
|
727
|
+
|
|
728
|
+
function getDefaultExportFromCjs (x) {
|
|
729
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
var cjs;
|
|
733
|
+
var hasRequiredCjs;
|
|
734
|
+
|
|
735
|
+
function requireCjs () {
|
|
736
|
+
if (hasRequiredCjs) return cjs;
|
|
737
|
+
hasRequiredCjs = 1;
|
|
738
|
+
|
|
739
|
+
var isMergeableObject = function isMergeableObject(value) {
|
|
740
|
+
return isNonNullObject(value)
|
|
741
|
+
&& !isSpecial(value)
|
|
742
|
+
};
|
|
743
|
+
|
|
744
|
+
function isNonNullObject(value) {
|
|
745
|
+
return !!value && typeof value === 'object'
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function isSpecial(value) {
|
|
749
|
+
var stringValue = Object.prototype.toString.call(value);
|
|
750
|
+
|
|
751
|
+
return stringValue === '[object RegExp]'
|
|
752
|
+
|| stringValue === '[object Date]'
|
|
753
|
+
|| isReactElement(value)
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25
|
|
757
|
+
var canUseSymbol = typeof Symbol === 'function' && Symbol.for;
|
|
758
|
+
var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;
|
|
759
|
+
|
|
760
|
+
function isReactElement(value) {
|
|
761
|
+
return value.$$typeof === REACT_ELEMENT_TYPE
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function emptyTarget(val) {
|
|
765
|
+
return Array.isArray(val) ? [] : {}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
function cloneUnlessOtherwiseSpecified(value, options) {
|
|
769
|
+
return (options.clone !== false && options.isMergeableObject(value))
|
|
770
|
+
? deepmerge(emptyTarget(value), value, options)
|
|
771
|
+
: value
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function defaultArrayMerge(target, source, options) {
|
|
775
|
+
return target.concat(source).map(function(element) {
|
|
776
|
+
return cloneUnlessOtherwiseSpecified(element, options)
|
|
777
|
+
})
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
function getMergeFunction(key, options) {
|
|
781
|
+
if (!options.customMerge) {
|
|
782
|
+
return deepmerge
|
|
783
|
+
}
|
|
784
|
+
var customMerge = options.customMerge(key);
|
|
785
|
+
return typeof customMerge === 'function' ? customMerge : deepmerge
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
function getEnumerableOwnPropertySymbols(target) {
|
|
789
|
+
return Object.getOwnPropertySymbols
|
|
790
|
+
? Object.getOwnPropertySymbols(target).filter(function(symbol) {
|
|
791
|
+
return Object.propertyIsEnumerable.call(target, symbol)
|
|
792
|
+
})
|
|
793
|
+
: []
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
function getKeys(target) {
|
|
797
|
+
return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
function propertyIsOnObject(object, property) {
|
|
801
|
+
try {
|
|
802
|
+
return property in object
|
|
803
|
+
} catch(_) {
|
|
804
|
+
return false
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// Protects from prototype poisoning and unexpected merging up the prototype chain.
|
|
809
|
+
function propertyIsUnsafe(target, key) {
|
|
810
|
+
return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
|
|
811
|
+
&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
|
|
812
|
+
&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
function mergeObject(target, source, options) {
|
|
816
|
+
var destination = {};
|
|
817
|
+
if (options.isMergeableObject(target)) {
|
|
818
|
+
getKeys(target).forEach(function(key) {
|
|
819
|
+
destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
getKeys(source).forEach(function(key) {
|
|
823
|
+
if (propertyIsUnsafe(target, key)) {
|
|
824
|
+
return
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {
|
|
828
|
+
destination[key] = getMergeFunction(key, options)(target[key], source[key], options);
|
|
829
|
+
} else {
|
|
830
|
+
destination[key] = cloneUnlessOtherwiseSpecified(source[key], options);
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
return destination
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
function deepmerge(target, source, options) {
|
|
837
|
+
options = options || {};
|
|
838
|
+
options.arrayMerge = options.arrayMerge || defaultArrayMerge;
|
|
839
|
+
options.isMergeableObject = options.isMergeableObject || isMergeableObject;
|
|
840
|
+
// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
|
|
841
|
+
// implementations can use it. The caller may not replace it.
|
|
842
|
+
options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
|
|
843
|
+
|
|
844
|
+
var sourceIsArray = Array.isArray(source);
|
|
845
|
+
var targetIsArray = Array.isArray(target);
|
|
846
|
+
var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
|
|
847
|
+
|
|
848
|
+
if (!sourceAndTargetTypesMatch) {
|
|
849
|
+
return cloneUnlessOtherwiseSpecified(source, options)
|
|
850
|
+
} else if (sourceIsArray) {
|
|
851
|
+
return options.arrayMerge(target, source, options)
|
|
852
|
+
} else {
|
|
853
|
+
return mergeObject(target, source, options)
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
deepmerge.all = function deepmergeAll(array, options) {
|
|
858
|
+
if (!Array.isArray(array)) {
|
|
859
|
+
throw new Error('first argument should be an array')
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
return array.reduce(function(prev, next) {
|
|
863
|
+
return deepmerge(prev, next, options)
|
|
864
|
+
}, {})
|
|
865
|
+
};
|
|
866
|
+
|
|
867
|
+
var deepmerge_1 = deepmerge;
|
|
868
|
+
|
|
869
|
+
cjs = deepmerge_1;
|
|
870
|
+
return cjs;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
var cjsExports = requireCjs();
|
|
874
|
+
var deepmerge = /*@__PURE__*/getDefaultExportFromCjs(cjsExports);
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Default blueprint configuration for the AWS Lambda Http Adapter.
|
|
878
|
+
*
|
|
879
|
+
* This blueprint defines the initial configuration for the AWS Lambda Http adapter
|
|
880
|
+
* within the Stone.js framework. It includes:
|
|
881
|
+
* - An alias for the AWS Lambda platform (`AWS_LAMBDA_HTTP_PLATFORM`).
|
|
882
|
+
* - A default resolver function (currently a placeholder).
|
|
883
|
+
* - Middleware, hooks, and state flags (`current`, `default`, `preferred`).
|
|
884
|
+
*/
|
|
885
|
+
const awsLambdaHttpAdapterBlueprint = {
|
|
886
|
+
stone: {
|
|
887
|
+
...httpCoreBlueprint.stone,
|
|
888
|
+
blueprint: {
|
|
889
|
+
middleware: metaAdapterBlueprintMiddleware
|
|
890
|
+
},
|
|
891
|
+
adapters: [
|
|
892
|
+
{
|
|
893
|
+
current: false,
|
|
894
|
+
variant: 'server',
|
|
895
|
+
platform: AWS_LAMBDA_HTTP_PLATFORM,
|
|
896
|
+
middleware: [
|
|
897
|
+
MetaIncomingEventMiddleware,
|
|
898
|
+
MetaServerResponseMiddleware
|
|
899
|
+
],
|
|
900
|
+
resolver: awsLambdaHttpAdapterResolver,
|
|
901
|
+
eventHandlerResolver: defaultKernelResolver,
|
|
902
|
+
errorHandlers: {
|
|
903
|
+
default: { module: AwsLambdaHttpErrorHandler, isClass: true }
|
|
904
|
+
},
|
|
905
|
+
default: isNotEmpty(getString('AWS_LAMBDA_FUNCTION_NAME', ''))
|
|
906
|
+
}
|
|
907
|
+
]
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* A Stone.js decorator that integrates the AWS Lambda HTTP Adapter with a class.
|
|
913
|
+
*
|
|
914
|
+
* This decorator modifies the class to seamlessly enable AWS Lambda HTTP as the
|
|
915
|
+
* execution environment for a Stone.js application. By applying this decorator,
|
|
916
|
+
* the class is automatically configured with the necessary blueprint for AWS Lambda HTTP.
|
|
917
|
+
*
|
|
918
|
+
* @template T - The type of the class being decorated. Defaults to `ClassType`.
|
|
919
|
+
* @param options - Optional configuration to customize the AWS Lambda HTTP Adapter.
|
|
920
|
+
*
|
|
921
|
+
* @returns A class decorator that applies the AWS Lambda HTTP adapter configuration.
|
|
922
|
+
*
|
|
923
|
+
* @example
|
|
924
|
+
* ```typescript
|
|
925
|
+
* import { AwsLambdaHttp } from '@stone-js/aws-lambda-http-adapter';
|
|
926
|
+
*
|
|
927
|
+
* @AwsLambdaHttp({
|
|
928
|
+
* alias: 'MyAwsLambdaHttpAdapter',
|
|
929
|
+
* current: true,
|
|
930
|
+
* })
|
|
931
|
+
* class App {
|
|
932
|
+
* // Your application logic here
|
|
933
|
+
* }
|
|
934
|
+
* ```
|
|
935
|
+
*/
|
|
936
|
+
const AwsLambdaHttp = (options = {}) => {
|
|
937
|
+
return classDecoratorLegacyWrapper((target, context) => {
|
|
938
|
+
if (awsLambdaHttpAdapterBlueprint.stone?.adapters?.[0] !== undefined) {
|
|
939
|
+
// Merge provided options with the default AWS Lambda HTTP adapter blueprint.
|
|
940
|
+
awsLambdaHttpAdapterBlueprint.stone.adapters[0] = deepmerge(awsLambdaHttpAdapterBlueprint.stone.adapters[0], options);
|
|
941
|
+
}
|
|
942
|
+
// Add the modified blueprint to the target class.
|
|
943
|
+
addBlueprint(target, context, awsLambdaHttpAdapterBlueprint);
|
|
944
|
+
});
|
|
945
|
+
};
|
|
888
946
|
|
|
889
947
|
export { AWS_LAMBDA_HTTP_PLATFORM, AwsLambdaHttp, AwsLambdaHttpAdapter, AwsLambdaHttpAdapterError, AwsLambdaHttpErrorHandler, BodyEventMiddleware, FilesEventMiddleware, IncomingEventMiddleware, MetaBodyEventMiddleware, MetaFilesEventMiddleware, MetaIncomingEventMiddleware, MetaServerResponseMiddleware, RawHttpResponseWrapper, ServerResponseMiddleware, SetAwsLambdaHttpResponseResolverMiddleware, awsLambdaHttpAdapterBlueprint, awsLambdaHttpAdapterResolver, metaAdapterBlueprintMiddleware };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stone-js/aws-lambda-http-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Official AWS Lambda HTTP adapter for Stone.js. Run your Stone.js apps on AWS Lambda behind API Gateway with full Continuum lifecycle support.",
|
|
5
5
|
"author": "Mr. Stone <evensstone@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,16 +62,16 @@
|
|
|
62
62
|
"prepare": "husky"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@stone-js/core": "^0.
|
|
66
|
-
"@stone-js/env": "^0.1.
|
|
67
|
-
"@stone-js/filesystem": "^0.1.
|
|
68
|
-
"@stone-js/http-core": "^0.1.
|
|
65
|
+
"@stone-js/core": "^0.2.1",
|
|
66
|
+
"@stone-js/env": "^0.1.2",
|
|
67
|
+
"@stone-js/filesystem": "^0.1.2",
|
|
68
|
+
"@stone-js/http-core": "^0.1.4"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"accepts": "^1.3.8",
|
|
72
72
|
"bytes": "^3.1.2",
|
|
73
73
|
"content-type": "^1.0.5",
|
|
74
|
-
"mime": "^4.0
|
|
74
|
+
"mime": "^4.1.0",
|
|
75
75
|
"proxy-addr": "^2.0.7",
|
|
76
76
|
"statuses": "^2.0.1",
|
|
77
77
|
"type-is": "^2.0.1"
|
|
@@ -82,27 +82,27 @@
|
|
|
82
82
|
"@rollup/plugin-commonjs": "^28.0.2",
|
|
83
83
|
"@rollup/plugin-multi-entry": "^6.0.1",
|
|
84
84
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
85
|
-
"@rollup/plugin-typescript": "^12.
|
|
85
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
86
86
|
"@types/accepts": "^1.3.7",
|
|
87
87
|
"@types/bytes": "^3.1.5",
|
|
88
88
|
"@types/content-type": "^1.1.8",
|
|
89
|
-
"@types/node": "^24.
|
|
89
|
+
"@types/node": "^24.9.2",
|
|
90
90
|
"@types/proxy-addr": "^2.0.3",
|
|
91
91
|
"@types/statuses": "^2.0.5",
|
|
92
92
|
"@types/type-is": "^1.6.7",
|
|
93
|
-
"@vitest/coverage-v8": "^3.2.
|
|
93
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
94
94
|
"husky": "^9.1.7",
|
|
95
|
-
"rimraf": "^6.0
|
|
96
|
-
"rollup": "^4.
|
|
95
|
+
"rimraf": "^6.1.0",
|
|
96
|
+
"rollup": "^4.52.5",
|
|
97
97
|
"rollup-plugin-delete": "^3.0.1",
|
|
98
|
-
"rollup-plugin-dts": "^6.2.
|
|
99
|
-
"rollup-plugin-node-externals": "^8.
|
|
98
|
+
"rollup-plugin-dts": "^6.2.3",
|
|
99
|
+
"rollup-plugin-node-externals": "^8.1.1",
|
|
100
100
|
"ts-standard": "^12.0.2",
|
|
101
101
|
"tslib": "^2.8.1",
|
|
102
|
-
"typedoc": "^0.28.
|
|
103
|
-
"typedoc-plugin-markdown": "^4.
|
|
104
|
-
"typescript": "^5.
|
|
105
|
-
"vitest": "^3.2.
|
|
102
|
+
"typedoc": "^0.28.14",
|
|
103
|
+
"typedoc-plugin-markdown": "^4.9.0",
|
|
104
|
+
"typescript": "^5.9.3",
|
|
105
|
+
"vitest": "^3.2.4"
|
|
106
106
|
},
|
|
107
107
|
"ts-standard": {
|
|
108
108
|
"globals": [
|