@lafken/common 0.12.29 → 0.13.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.
@@ -2,3 +2,4 @@ export * from './field';
2
2
  export * from './lambda';
3
3
  export * from './payload';
4
4
  export * from './resource';
5
+ export * from './streaming';
@@ -18,3 +18,4 @@ __exportStar(require("./field"), exports);
18
18
  __exportStar(require("./lambda"), exports);
19
19
  __exportStar(require("./payload"), exports);
20
20
  __exportStar(require("./resource"), exports);
21
+ __exportStar(require("./streaming"), exports);
@@ -5,3 +5,4 @@ export declare const reflectArgumentMethod: (target: Function, methodName: strin
5
5
  export declare const createLambdaDecorator: <T, M>({ getLambdaMetadata, descriptorValue, validateEvent, argumentParser, }: CreateLambdaDecoratorProps<T, M>) => (props?: T) => (target: any, methodName: string, descriptor: PropertyDescriptor) => any;
6
6
  export declare const createEventDecorator: ({ enableInLambdaInvocation, prefix }: CreateEventDecoratorProps) => (eventField: AllowedTypes) => (target: any, methodName: string, _number: number) => void;
7
7
  export declare const Context: () => (target: any, methodName: string, _number: number) => void;
8
+ export declare const ResponseStreaming: () => (target: any, methodName: string, _number: number) => void;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Context = exports.createEventDecorator = exports.createLambdaDecorator = exports.reflectArgumentMethod = void 0;
3
+ exports.ResponseStreaming = exports.Context = exports.createEventDecorator = exports.createLambdaDecorator = exports.reflectArgumentMethod = void 0;
4
4
  require("reflect-metadata");
5
5
  const utils_1 = require("../../utils");
6
6
  const field_1 = require("../field");
@@ -8,6 +8,7 @@ const lambda_types_1 = require("./lambda.types");
8
8
  const argumentsByType = {
9
9
  [lambda_types_1.LambdaArgumentTypes.event]: ({ event }) => event,
10
10
  [lambda_types_1.LambdaArgumentTypes.context]: ({ context }) => context,
11
+ [lambda_types_1.LambdaArgumentTypes.responseStream]: ({ responseStream }) => responseStream,
11
12
  };
12
13
  const reflectArgumentMethod = (target, methodName, type) => {
13
14
  const properties = Reflect.getMetadata(lambda_types_1.LambdaReflectKeys.arguments, target) || {};
@@ -29,11 +30,22 @@ const createLambdaDecorator = ({ getLambdaMetadata, descriptorValue, validateEve
29
30
  ...argumentsByType,
30
31
  ...argumentParser,
31
32
  };
32
- descriptor.value = async function (event, context) {
33
+ descriptor.value = async function (...args) {
34
+ const [event, responseStreamOrContext, lambdaContext] = args;
33
35
  if (!(0, utils_1.isBuildEnvironment)() && event && validateEvent) {
34
36
  validateEvent(target, methodName, event);
35
37
  }
36
- const methodArguments = (lambdaArguments?.[methodName] || []).map((argumentType) => mapArgumentMethod[argumentType]({ event, context, methodName, target }));
38
+ const responseStream = typeof responseStreamOrContext?.write === 'function'
39
+ ? responseStreamOrContext
40
+ : undefined;
41
+ const context = responseStream === undefined ? responseStreamOrContext : lambdaContext;
42
+ const methodArguments = (lambdaArguments?.[methodName] || []).map((argumentType) => mapArgumentMethod[argumentType]({
43
+ event,
44
+ context,
45
+ methodName,
46
+ target,
47
+ responseStream,
48
+ }));
37
49
  const response = await originalValue.apply(this, methodArguments);
38
50
  return response;
39
51
  };
@@ -62,3 +74,7 @@ const Context = () => (target, methodName, _number) => {
62
74
  (0, exports.reflectArgumentMethod)(target, methodName, lambda_types_1.LambdaArgumentTypes.context);
63
75
  };
64
76
  exports.Context = Context;
77
+ const ResponseStreaming = () => (target, methodName, _number) => {
78
+ (0, exports.reflectArgumentMethod)(target, methodName, lambda_types_1.LambdaArgumentTypes.responseStream);
79
+ };
80
+ exports.ResponseStreaming = ResponseStreaming;
@@ -303,7 +303,8 @@ export declare enum LambdaReflectKeys {
303
303
  }
304
304
  export declare enum LambdaArgumentTypes {
305
305
  event = "event",
306
- context = "context"
306
+ context = "context",
307
+ responseStream = "responseStream"
307
308
  }
308
309
  export type CallbackParam = (error: boolean | null, response?: any) => void;
309
310
  export type LambdaArguments = Record<string, LambdaArgumentTypes[]>;
@@ -312,6 +313,7 @@ export type LambdaArgumentsType = Record<LambdaArgumentTypes, ({ event, context,
312
313
  context: any;
313
314
  methodName: string;
314
315
  target: any;
316
+ responseStream?: any;
315
317
  }) => any>;
316
318
  export interface CreateLambdaDecoratorProps<T, M> {
317
319
  getLambdaMetadata: (params: T, methodName: string) => M;
@@ -12,4 +12,5 @@ var LambdaArgumentTypes;
12
12
  (function (LambdaArgumentTypes) {
13
13
  LambdaArgumentTypes["event"] = "event";
14
14
  LambdaArgumentTypes["context"] = "context";
15
+ LambdaArgumentTypes["responseStream"] = "responseStream";
15
16
  })(LambdaArgumentTypes || (exports.LambdaArgumentTypes = LambdaArgumentTypes = {}));
@@ -0,0 +1,2 @@
1
+ export * from './streaming';
2
+ export * from './streaming.types';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./streaming"), exports);
18
+ __exportStar(require("./streaming.types"), exports);
@@ -0,0 +1,34 @@
1
+ import 'reflect-metadata';
2
+ /**
3
+ * Method decorator factory that marks a Lambda handler as a response-streaming
4
+ * handler.
5
+ *
6
+ * It only records, per method name, that the handler is a streaming one under
7
+ * `StreamingReflectKeys.streaming` on the class prototype (during synth). The
8
+ * actual `awslambda.streamifyResponse` wrapping is applied later by the build
9
+ * step, when the handler is exported as the Lambda entry point, so the
10
+ * streaming marker ends up on the final exported function (a decorator wrap
11
+ * would be dropped by `Function.prototype.bind` when the handler is bound to
12
+ * its instance at export time).
13
+ *
14
+ * The decorated method's runtime signature is `(event, responseStream, context)`
15
+ * instead of the usual `(event, context)`. When combined with a method decorator
16
+ * built from `createLambdaDecorator` (e.g. `Get`/`Handler`), that decorator's
17
+ * generated wrapper tells both signatures apart by checking whether the second
18
+ * argument exposes a `write` function: if it does it is treated as the response
19
+ * stream and forwarded to any parameter decorated with `ResponseStreaming()`,
20
+ * and `context` is read from the third argument; otherwise the second argument
21
+ * is the `context`. The check is structural rather than `instanceof Stream`
22
+ * because the runtime hands over its own stream implementation, which does not
23
+ * necessarily inherit from the `stream` module of this bundle.
24
+ *
25
+ * @example
26
+ * @Streaming()
27
+ * @Handler()
28
+ * myHandler(@ResponseStreaming() responseStream: Writable, @Context() context: any) {
29
+ * responseStream.write('chunk');
30
+ * responseStream.end();
31
+ * }
32
+ */
33
+ export declare const createStreamingDecorator: () => () => (target: any, methodName: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
34
+ export declare const Streaming: () => (target: any, methodName: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Streaming = exports.createStreamingDecorator = void 0;
4
+ require("reflect-metadata");
5
+ const utils_1 = require("../../utils");
6
+ const streaming_types_1 = require("./streaming.types");
7
+ /**
8
+ * Method decorator factory that marks a Lambda handler as a response-streaming
9
+ * handler.
10
+ *
11
+ * It only records, per method name, that the handler is a streaming one under
12
+ * `StreamingReflectKeys.streaming` on the class prototype (during synth). The
13
+ * actual `awslambda.streamifyResponse` wrapping is applied later by the build
14
+ * step, when the handler is exported as the Lambda entry point, so the
15
+ * streaming marker ends up on the final exported function (a decorator wrap
16
+ * would be dropped by `Function.prototype.bind` when the handler is bound to
17
+ * its instance at export time).
18
+ *
19
+ * The decorated method's runtime signature is `(event, responseStream, context)`
20
+ * instead of the usual `(event, context)`. When combined with a method decorator
21
+ * built from `createLambdaDecorator` (e.g. `Get`/`Handler`), that decorator's
22
+ * generated wrapper tells both signatures apart by checking whether the second
23
+ * argument exposes a `write` function: if it does it is treated as the response
24
+ * stream and forwarded to any parameter decorated with `ResponseStreaming()`,
25
+ * and `context` is read from the third argument; otherwise the second argument
26
+ * is the `context`. The check is structural rather than `instanceof Stream`
27
+ * because the runtime hands over its own stream implementation, which does not
28
+ * necessarily inherit from the `stream` module of this bundle.
29
+ *
30
+ * @example
31
+ * @Streaming()
32
+ * @Handler()
33
+ * myHandler(@ResponseStreaming() responseStream: Writable, @Context() context: any) {
34
+ * responseStream.write('chunk');
35
+ * responseStream.end();
36
+ * }
37
+ */
38
+ const createStreamingDecorator = () => () => (target, methodName, descriptor) => {
39
+ if ((0, utils_1.isBuildEnvironment)()) {
40
+ const streamingMethods = Reflect.getMetadata(streaming_types_1.StreamingReflectKeys.streaming, target) || {};
41
+ Reflect.defineMetadata(streaming_types_1.StreamingReflectKeys.streaming, { ...streamingMethods, [methodName]: true }, target);
42
+ }
43
+ return descriptor;
44
+ };
45
+ exports.createStreamingDecorator = createStreamingDecorator;
46
+ exports.Streaming = (0, exports.createStreamingDecorator)();
@@ -0,0 +1,4 @@
1
+ export declare enum StreamingReflectKeys {
2
+ streaming = "streaming:handlers"
3
+ }
4
+ export type StreamingMethods = Record<string, boolean>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StreamingReflectKeys = void 0;
4
+ var StreamingReflectKeys;
5
+ (function (StreamingReflectKeys) {
6
+ StreamingReflectKeys["streaming"] = "streaming:handlers";
7
+ })(StreamingReflectKeys || (exports.StreamingReflectKeys = StreamingReflectKeys = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lafken/common",
3
- "version": "0.12.29",
3
+ "version": "0.13.1",
4
4
  "private": false,
5
5
  "description": "Lafken utilities - TypeScript decorator factories and metadata reflection for infrastructure-as-code decorators",
6
6
  "keywords": [
@@ -28,16 +28,17 @@
28
28
  "lib"
29
29
  ],
30
30
  "dependencies": {
31
- "reflect-metadata": "0.2.2"
31
+ "@types/aws-lambda": "^8.10.162",
32
+ "reflect-metadata": "^0.2.2"
32
33
  },
33
34
  "devDependencies": {
34
- "@swc/core": "^1.15.40",
35
+ "@swc/core": "^1.15.43",
35
36
  "@swc/helpers": "^0.5.23",
36
- "@vitest/runner": "^4.1.8",
37
+ "@vitest/runner": "^4.1.10",
37
38
  "cdktn-vitest": "^1.0.0",
38
- "typescript": "6.0.3",
39
+ "typescript": "7.0.2",
39
40
  "unplugin-swc": "^1.5.9",
40
- "vitest": "^4.1.8"
41
+ "vitest": "^4.1.10"
41
42
  },
42
43
  "engines": {
43
44
  "node": ">=20.19"