@aesop-fables/triginta 0.7.5 → 0.8.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.
@@ -0,0 +1,34 @@
1
+ import { IServiceContainer, IServiceModule } from '@aesop-fables/containr';
2
+ import { ISqsRecordMatcher } from './sqs/RecordMatchers';
3
+ import { BootstrappedHttpLambdaContext } from './http/HttpLambda';
4
+ import { BootstrappedSqsLambdaContext } from './sqs/SqsLambda';
5
+ import { BootstrappedS3LambdaContext } from './s3/S3Lambda';
6
+ declare type Placeholder = object;
7
+ interface AwsServices {
8
+ http: Placeholder;
9
+ s3: Placeholder;
10
+ sqs: Placeholder;
11
+ }
12
+ declare type ConfiguredServices<T> = {
13
+ [Property in keyof AwsServices]: T;
14
+ };
15
+ interface BootstrappedTrigintaApp extends BootstrappedHttpLambdaContext, BootstrappedSqsLambdaContext, BootstrappedS3LambdaContext {
16
+ containers: ConfiguredServices<IServiceContainer>;
17
+ }
18
+ export interface AwsServiceOptions {
19
+ modules: IServiceModule[];
20
+ }
21
+ export interface TrigintaHttpOptions extends AwsServiceOptions {
22
+ }
23
+ export interface TrigintaS3Options extends AwsServiceOptions {
24
+ }
25
+ export interface TrigintaSqsOptions extends AwsServiceOptions {
26
+ matchers?: ISqsRecordMatcher[];
27
+ }
28
+ export interface TrigintaOptions {
29
+ http?: TrigintaHttpOptions;
30
+ s3?: TrigintaS3Options;
31
+ sqs?: TrigintaSqsOptions;
32
+ }
33
+ export declare function createTrigintaApp(options: TrigintaOptions): BootstrappedTrigintaApp;
34
+ export {};
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTrigintaApp = void 0;
4
+ const containr_1 = require("@aesop-fables/containr");
5
+ const http_1 = require("./http");
6
+ const HttpLambda_1 = require("./http/HttpLambda");
7
+ const localization_1 = require("./localization");
8
+ const validation_1 = require("./validation");
9
+ const SqsLambda_1 = require("./sqs/SqsLambda");
10
+ const S3Lambda_1 = require("./s3/S3Lambda");
11
+ function createTrigintaApp(options) {
12
+ const containers = {};
13
+ Object.keys(options).forEach((key) => {
14
+ var _a, _b;
15
+ const serviceKey = key;
16
+ const serviceOptions = (_a = options[key]) !== null && _a !== void 0 ? _a : {};
17
+ const { modules = [] } = (_b = options[key]) !== null && _b !== void 0 ? _b : {};
18
+ let container;
19
+ switch (serviceKey) {
20
+ case 'http':
21
+ container = (0, containr_1.createContainer)([HttpLambda_1.useTrigintaHttp, http_1.useHttpServices, localization_1.useLocalization, validation_1.useHttpValidation, ...modules]);
22
+ break;
23
+ case 's3':
24
+ container = (0, containr_1.createContainer)([S3Lambda_1.useTrigintaS3, ...modules]);
25
+ break;
26
+ case 'sqs':
27
+ const { matchers = [] } = serviceOptions;
28
+ container = (0, containr_1.createContainer)([(0, SqsLambda_1.useTrigintaSqs)({ matchers }), ...modules]);
29
+ break;
30
+ }
31
+ if (container) {
32
+ containers[serviceKey] = container;
33
+ }
34
+ });
35
+ return Object.assign(Object.assign(Object.assign(Object.assign({}, (0, HttpLambda_1.createBootstrappedHttpLambdaContext)(containers.http)), (0, SqsLambda_1.createBootstrappedSqsLambdaContext)(containers.sqs)), (0, S3Lambda_1.createBootstrappedS3LambdaContext)(containers.s3)), { containers });
36
+ }
37
+ exports.createTrigintaApp = createTrigintaApp;
package/lib/Utils.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function createServiceNamespacer(prefix: string): (key: string) => string;
package/lib/Utils.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createServiceNamespacer = void 0;
4
+ function createServiceNamespacer(prefix) {
5
+ return (key) => {
6
+ return `@aesop-fables/triginta/${prefix}/${key}`;
7
+ };
8
+ }
9
+ exports.createServiceNamespacer = createServiceNamespacer;
@@ -1,4 +1,4 @@
1
- import { IServiceContainer, IServiceModule, Newable } from '@aesop-fables/containr';
1
+ import { IServiceContainer, Newable } from '@aesop-fables/containr';
2
2
  import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2, Handler } from 'aws-lambda';
3
3
  import { IHttpEndpoint, IHttpEventHandler } from './IHttpEndpoint';
4
4
  import { IConfiguredRoute } from './IConfiguredRoute';
@@ -25,8 +25,8 @@ export declare class HttpLambdaFactory implements IHttpLambdaFactory {
25
25
  createEventHandler<Output>(newable: Newable<IHttpEventHandler<Output>>): Handler<APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2>;
26
26
  createHandler<Input, Output>(newable: Newable<IHttpEndpoint<Input, Output> | IHttpEventHandler<Output>>): Handler<APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2>;
27
27
  }
28
- export declare const useTrigintaHttp: IServiceModule;
29
- export declare class HttpLambda {
30
- static initialize(modules?: IServiceModule[]): BootstrappedHttpLambdaContext;
31
- static getContainer(): IServiceContainer;
32
- }
28
+ export declare const useTrigintaHttp: import("@aesop-fables/containr").IServiceModule;
29
+ export declare function createBootstrappedHttpLambdaContext(container: IServiceContainer): {
30
+ createHttpEventLambda<Output>(newable: Newable<IHttpEventHandler<Output>>): Handler<APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2>;
31
+ createHttpLambda<Input, Output_1>(newable: Newable<IHttpEndpoint<Input, Output_1> | IHttpEventHandler<Output_1>>): Handler<APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2>;
32
+ };
@@ -24,7 +24,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
24
24
  return (mod && mod.__esModule) ? mod : { "default": mod };
25
25
  };
26
26
  Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.HttpLambda = exports.useTrigintaHttp = exports.HttpLambdaFactory = exports.HttpResponseGenerator = void 0;
27
+ exports.createBootstrappedHttpLambdaContext = exports.useTrigintaHttp = exports.HttpLambdaFactory = exports.HttpResponseGenerator = void 0;
28
28
  /* eslint-disable @typescript-eslint/ban-types */
29
29
  /* eslint-disable @typescript-eslint/no-explicit-any */
30
30
  /* eslint-disable @typescript-eslint/no-unused-vars */
@@ -32,9 +32,6 @@ const containr_1 = require("@aesop-fables/containr");
32
32
  const core_1 = __importDefault(require("@middy/core"));
33
33
  const Decorators_1 = require("../Decorators");
34
34
  const HttpLambdaServices_1 = require("./HttpLambdaServices");
35
- const _1 = require(".");
36
- const localization_1 = require("../localization");
37
- const validation_1 = require("../validation");
38
35
  let HttpResponseGenerator = class HttpResponseGenerator {
39
36
  constructor(configuredRoute) {
40
37
  this.configuredRoute = configuredRoute;
@@ -71,7 +68,7 @@ HttpResponseGenerator = __decorate([
71
68
  __metadata("design:paramtypes", [Object])
72
69
  ], HttpResponseGenerator);
73
70
  exports.HttpResponseGenerator = HttpResponseGenerator;
74
- class HttpLambdaFactory {
71
+ let HttpLambdaFactory = class HttpLambdaFactory {
75
72
  constructor(container) {
76
73
  this.container = container;
77
74
  }
@@ -109,13 +106,8 @@ class HttpLambdaFactory {
109
106
  before(request) {
110
107
  return __awaiter(this, void 0, void 0, function* () {
111
108
  const injectContextualServices = (0, containr_1.createServiceModule)('injectContextualServices', (services) => {
112
- services.register(HttpLambdaServices_1.HttpLambdaServices.CurrentRoute, route);
113
- services.register(HttpLambdaServices_1.HttpLambdaServices.CurrentEvent, request.event);
114
- services.register(HttpLambdaServices_1.HttpLambdaServices.RequestContext, (current) => {
115
- return {
116
- container: current,
117
- };
118
- });
109
+ services.singleton(HttpLambdaServices_1.HttpLambdaServices.CurrentRoute, route);
110
+ services.singleton(HttpLambdaServices_1.HttpLambdaServices.CurrentEvent, request.event);
119
111
  });
120
112
  const childContainer = container.createChildContainer('httpLambda', [injectContextualServices]);
121
113
  request.context['container'] = childContainer;
@@ -131,36 +123,33 @@ class HttpLambdaFactory {
131
123
  });
132
124
  return midHandler;
133
125
  }
134
- }
126
+ };
127
+ HttpLambdaFactory = __decorate([
128
+ __param(0, (0, containr_1.injectContainer)()),
129
+ __metadata("design:paramtypes", [Object])
130
+ ], HttpLambdaFactory);
135
131
  exports.HttpLambdaFactory = HttpLambdaFactory;
136
132
  exports.useTrigintaHttp = (0, containr_1.createServiceModule)('triginta/http', (services) => {
137
- services.use(HttpLambdaServices_1.HttpLambdaServices.HttpResponseGenerator, HttpResponseGenerator);
138
- services.register(HttpLambdaServices_1.HttpLambdaServices.HttpLambdaFactory, (container) => new HttpLambdaFactory(container));
133
+ services.autoResolve(HttpLambdaServices_1.HttpLambdaServices.HttpResponseGenerator, HttpResponseGenerator, containr_1.Scopes.Transient);
134
+ services.autoResolve(HttpLambdaServices_1.HttpLambdaServices.HttpLambdaFactory, HttpLambdaFactory, containr_1.Scopes.Transient);
139
135
  });
140
- let _currentContainer;
141
- class HttpLambda {
142
- static initialize(modules = []) {
143
- const container = (0, containr_1.createContainer)([
144
- exports.useTrigintaHttp,
145
- _1.useHttpServices,
146
- localization_1.useLocalization,
147
- validation_1.useHttpValidation,
148
- ...modules,
149
- ]);
150
- _currentContainer = container;
151
- return {
152
- createHttpEventLambda(newable) {
153
- const factory = container.get(HttpLambdaServices_1.HttpLambdaServices.HttpLambdaFactory);
154
- return factory.createEventHandler(newable);
155
- },
156
- createHttpLambda(newable) {
157
- const factory = container.get(HttpLambdaServices_1.HttpLambdaServices.HttpLambdaFactory);
158
- return factory.createHandler(newable);
159
- },
160
- };
161
- }
162
- static getContainer() {
163
- return _currentContainer;
136
+ function validateContainer(container) {
137
+ if (typeof container === 'undefined') {
138
+ throw new Error(`HTTP container not initialized`);
164
139
  }
165
140
  }
166
- exports.HttpLambda = HttpLambda;
141
+ function createBootstrappedHttpLambdaContext(container) {
142
+ return {
143
+ createHttpEventLambda(newable) {
144
+ validateContainer(container);
145
+ const factory = container.get(HttpLambdaServices_1.HttpLambdaServices.HttpLambdaFactory);
146
+ return factory.createEventHandler(newable);
147
+ },
148
+ createHttpLambda(newable) {
149
+ validateContainer(container);
150
+ const factory = container.get(HttpLambdaServices_1.HttpLambdaServices.HttpLambdaFactory);
151
+ return factory.createHandler(newable);
152
+ },
153
+ };
154
+ }
155
+ exports.createBootstrappedHttpLambdaContext = createBootstrappedHttpLambdaContext;
package/lib/http/index.js CHANGED
@@ -4,12 +4,6 @@ exports.useHttpServices = void 0;
4
4
  const containr_1 = require("@aesop-fables/containr");
5
5
  const localization_1 = require("../localization");
6
6
  const HttpCultureContext_1 = require("./HttpCultureContext");
7
- const HttpLambdaServices_1 = require("./HttpLambdaServices");
8
7
  exports.useHttpServices = (0, containr_1.createServiceModule)('useHttpServices', (services) => {
9
- services.use(localization_1.LocalizationServices.CultureContext, HttpCultureContext_1.HttpCultureContext);
10
- services.register(HttpLambdaServices_1.HttpLambdaServices.RequestContext, (container) => {
11
- return {
12
- container,
13
- };
14
- });
8
+ services.autoResolve(localization_1.LocalizationServices.CultureContext, HttpCultureContext_1.HttpCultureContext, containr_1.Scopes.Transient);
15
9
  });
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './Bootstrapping';
1
2
  export * from './IHandler';
2
3
  export * from './http/IHttpEndpoint';
3
4
  export * from './Decorators';
@@ -16,14 +17,19 @@ export * from './sqs/SqsPublisher';
16
17
  export * from './http/IConfiguredRoute';
17
18
  export * from './TrigintaConfig';
18
19
  export * from './resolveEnvironmentSettings';
20
+ export * from './s3/IS3RecordHandler';
21
+ export * from './s3/S3Lambda';
22
+ export * from './s3/S3LambdaServices';
19
23
  export * as Localization from './localization';
20
24
  export * as Validation from './validation';
21
25
  import * as httpUtils from './http/invokeHttpHandler';
22
26
  import * as sqsUtils from './sqs/invokeSqsHandler';
27
+ import * as s3Utils from './s3/invokeS3Handler';
23
28
  /**
24
29
  * Provides helper functions for invoking lambdas in unit/integration tests.
25
30
  */
26
31
  export declare const TestUtils: {
32
+ invokeS3Handler(context: s3Utils.S3InvocationContext): Promise<void>;
27
33
  invokeSqsHandler(context: sqsUtils.SqsInvocationContext): Promise<void>;
28
34
  parseRouteParams(route: string, path: string): import("aws-lambda").APIGatewayProxyEventPathParameters;
29
35
  parsePathParameters(context: httpUtils.EventGenerationContext): Partial<import("aws-lambda").APIGatewayProxyEventV2>;
package/lib/index.js CHANGED
@@ -30,6 +30,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
30
30
  };
31
31
  Object.defineProperty(exports, "__esModule", { value: true });
32
32
  exports.TestUtils = exports.Validation = exports.Localization = exports.RouteRegistry = void 0;
33
+ __exportStar(require("./Bootstrapping"), exports);
33
34
  __exportStar(require("./IHandler"), exports);
34
35
  __exportStar(require("./http/IHttpEndpoint"), exports);
35
36
  __exportStar(require("./Decorators"), exports);
@@ -49,11 +50,15 @@ __exportStar(require("./sqs/SqsPublisher"), exports);
49
50
  __exportStar(require("./http/IConfiguredRoute"), exports);
50
51
  __exportStar(require("./TrigintaConfig"), exports);
51
52
  __exportStar(require("./resolveEnvironmentSettings"), exports);
53
+ __exportStar(require("./s3/IS3RecordHandler"), exports);
54
+ __exportStar(require("./s3/S3Lambda"), exports);
55
+ __exportStar(require("./s3/S3LambdaServices"), exports);
52
56
  exports.Localization = __importStar(require("./localization"));
53
57
  exports.Validation = __importStar(require("./validation"));
54
58
  const httpUtils = __importStar(require("./http/invokeHttpHandler"));
55
59
  const sqsUtils = __importStar(require("./sqs/invokeSqsHandler"));
60
+ const s3Utils = __importStar(require("./s3/invokeS3Handler"));
56
61
  /**
57
62
  * Provides helper functions for invoking lambdas in unit/integration tests.
58
63
  */
59
- exports.TestUtils = Object.assign(Object.assign({}, httpUtils), sqsUtils);
64
+ exports.TestUtils = Object.assign(Object.assign(Object.assign({}, httpUtils), sqsUtils), s3Utils);
@@ -0,0 +1,4 @@
1
+ import { S3Event, S3EventRecord } from 'aws-lambda';
2
+ export interface IS3RecordHandler {
3
+ handle(record: S3EventRecord, event: S3Event): Promise<void>;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,16 @@
1
+ import { IServiceContainer, IServiceModule, Newable } from '@aesop-fables/containr';
2
+ import { IS3RecordHandler } from './IS3RecordHandler';
3
+ import { S3Handler } from 'aws-lambda';
4
+ export interface BootstrappedS3LambdaContext {
5
+ createS3Handler(newable: Newable<IS3RecordHandler>): S3Handler;
6
+ }
7
+ export interface IS3LambdaFactory {
8
+ createHandler(newable: Newable<IS3RecordHandler>): S3Handler;
9
+ }
10
+ export declare const useTrigintaS3: IServiceModule;
11
+ export declare class S3LambdaFactory implements IS3LambdaFactory {
12
+ private readonly container;
13
+ constructor(container: IServiceContainer);
14
+ createHandler(newable: Newable<IS3RecordHandler>): S3Handler;
15
+ }
16
+ export declare function createBootstrappedS3LambdaContext(container: IServiceContainer): BootstrappedS3LambdaContext;
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16
+ return new (P || (P = Promise))(function (resolve, reject) {
17
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
21
+ });
22
+ };
23
+ var __importDefault = (this && this.__importDefault) || function (mod) {
24
+ return (mod && mod.__esModule) ? mod : { "default": mod };
25
+ };
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.createBootstrappedS3LambdaContext = exports.S3LambdaFactory = exports.useTrigintaS3 = void 0;
28
+ /* eslint-disable @typescript-eslint/ban-types */
29
+ /* eslint-disable @typescript-eslint/no-explicit-any */
30
+ /* eslint-disable @typescript-eslint/no-unused-vars */
31
+ const containr_1 = require("@aesop-fables/containr");
32
+ const core_1 = __importDefault(require("@middy/core"));
33
+ const Decorators_1 = require("../Decorators");
34
+ const S3LambdaServices_1 = require("./S3LambdaServices");
35
+ function embedS3Event(event) {
36
+ return (0, containr_1.createServiceModule)('@aesop-fables/triginta/s3/event', (services) => {
37
+ services.singleton(S3LambdaServices_1.S3LambdaServices.CurrentEvent, event);
38
+ });
39
+ }
40
+ function embedS3Record(record) {
41
+ return (0, containr_1.createServiceModule)('@aesop-fables/triginta/s3/record', (services) => {
42
+ services.singleton(S3LambdaServices_1.S3LambdaServices.CurrentRecord, record);
43
+ });
44
+ }
45
+ exports.useTrigintaS3 = (0, containr_1.createServiceModule)('triginta/s3', (services) => {
46
+ services.autoResolve(S3LambdaServices_1.S3LambdaServices.S3LambdaFactory, S3LambdaFactory, containr_1.Scopes.Transient);
47
+ });
48
+ let S3LambdaFactory = class S3LambdaFactory {
49
+ constructor(container) {
50
+ this.container = container;
51
+ }
52
+ createHandler(newable) {
53
+ const handler = (event) => __awaiter(this, void 0, void 0, function* () {
54
+ for (let i = 0; i < event.Records.length; i++) {
55
+ const record = event.Records[i];
56
+ const childContainer = this.container.createChildContainer('s3Lambda', [
57
+ embedS3Event(event),
58
+ embedS3Record(record),
59
+ ]);
60
+ try {
61
+ const handler = childContainer.resolve(newable);
62
+ yield handler.handle(record, event);
63
+ }
64
+ finally {
65
+ if (childContainer) {
66
+ try {
67
+ childContainer.dispose();
68
+ }
69
+ catch (_a) {
70
+ // no-op
71
+ }
72
+ }
73
+ }
74
+ }
75
+ });
76
+ const middlewareMetadata = (0, Decorators_1.getMiddleware)(newable);
77
+ if (middlewareMetadata) {
78
+ let midHandler = (0, core_1.default)(handler);
79
+ middlewareMetadata.forEach((midFunc) => {
80
+ midHandler = midHandler.use(midFunc());
81
+ });
82
+ return midHandler;
83
+ }
84
+ return handler;
85
+ }
86
+ };
87
+ S3LambdaFactory = __decorate([
88
+ __param(0, (0, containr_1.injectContainer)()),
89
+ __metadata("design:paramtypes", [Object])
90
+ ], S3LambdaFactory);
91
+ exports.S3LambdaFactory = S3LambdaFactory;
92
+ function createBootstrappedS3LambdaContext(container) {
93
+ return {
94
+ createS3Handler(newable) {
95
+ if (typeof container === 'undefined') {
96
+ throw new Error(`S3 container not initialized`);
97
+ }
98
+ const factory = container.get(S3LambdaServices_1.S3LambdaServices.S3LambdaFactory);
99
+ return factory.createHandler(newable);
100
+ },
101
+ };
102
+ }
103
+ exports.createBootstrappedS3LambdaContext = createBootstrappedS3LambdaContext;
@@ -0,0 +1,5 @@
1
+ export declare const S3LambdaServices: {
2
+ S3LambdaFactory: string;
3
+ CurrentEvent: string;
4
+ CurrentRecord: string;
5
+ };
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.S3LambdaServices = void 0;
4
+ const Utils_1 = require("../Utils");
5
+ const namedService = (0, Utils_1.createServiceNamespacer)('s3');
6
+ exports.S3LambdaServices = {
7
+ S3LambdaFactory: namedService('factory'),
8
+ CurrentEvent: namedService('event'),
9
+ CurrentRecord: namedService('record'),
10
+ };
@@ -0,0 +1,12 @@
1
+ import { S3Event } from 'aws-lambda';
2
+ import { IServiceContainer } from '@aesop-fables/containr';
3
+ export interface S3InvocationContext extends Partial<S3Event> {
4
+ handler: Function;
5
+ container: IServiceContainer;
6
+ }
7
+ /**
8
+ * Invokes a lambda by constructing it from the specified container
9
+ * @param context
10
+ * @returns
11
+ */
12
+ export declare function invokeS3Handler(context: S3InvocationContext): Promise<void>;
@@ -0,0 +1,57 @@
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.invokeS3Handler = void 0;
13
+ const S3LambdaServices_1 = require("./S3LambdaServices");
14
+ /**
15
+ * Invokes a lambda by constructing it from the specified container
16
+ * @param context
17
+ * @returns
18
+ */
19
+ function invokeS3Handler(context) {
20
+ var _a;
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ const { container } = context;
23
+ const factory = container.get(S3LambdaServices_1.S3LambdaServices.S3LambdaFactory);
24
+ const configuredHandler = factory.createHandler(context.handler);
25
+ (_a = context.Records) === null || _a === void 0 ? void 0 : _a.forEach((record) => {
26
+ if (!record.eventSource) {
27
+ record.eventSource = 'aws:s3';
28
+ }
29
+ });
30
+ const event = Object.assign(Object.assign({}, context), { handler: undefined, container: undefined });
31
+ const handlerContext = {
32
+ callbackWaitsForEmptyEventLoop: false,
33
+ functionName: 's3Lambda',
34
+ functionVersion: '0.1',
35
+ invokedFunctionArn: 'arn::test',
36
+ memoryLimitInMB: '128',
37
+ awsRequestId: '1234',
38
+ logGroupName: 'test-group',
39
+ logStreamName: 'test-stream',
40
+ getRemainingTimeInMillis: function () {
41
+ return 1000;
42
+ },
43
+ done: function (error, result) {
44
+ throw new Error('Function not implemented.');
45
+ },
46
+ fail: function (error) {
47
+ throw new Error('Function not implemented.');
48
+ },
49
+ succeed: function (messageOrObject) {
50
+ throw new Error('Function not implemented.');
51
+ },
52
+ };
53
+ const response = yield configuredHandler(event, handlerContext);
54
+ return response;
55
+ });
56
+ }
57
+ exports.invokeS3Handler = invokeS3Handler;
@@ -77,7 +77,7 @@ let SqsMessageDeserializer = class SqsMessageDeserializer {
77
77
  }
78
78
  };
79
79
  SqsMessageDeserializer = __decorate([
80
- __param(0, (0, containr_1.inject)(SqsLambdaServices_1.SqsLambdaServices.RecordMatchers)),
80
+ __param(0, (0, containr_1.injectArray)(SqsLambdaServices_1.SqsLambdaServices.RecordMatchers)),
81
81
  __param(1, (0, containr_1.inject)(SqsLambdaServices_1.SqsLambdaServices.DefaultRecordMatcher)),
82
82
  __metadata("design:paramtypes", [Array, Object])
83
83
  ], SqsMessageDeserializer);
@@ -4,8 +4,7 @@ import { ISqsMessageHandler, SqsOutput } from './ISqsMessageHandler';
4
4
  import { ISqsMessage } from './ISqsMessage';
5
5
  import { ISqsRecordMatcher } from './RecordMatchers';
6
6
  export interface BootstrappedSqsLambdaContext {
7
- container: IServiceContainer;
8
- createHandler<Message extends ISqsMessage, Output extends SqsOutput = void>(newable: Newable<ISqsMessageHandler<Message, Output>>): SQSHandler;
7
+ createSqsHandler<Message extends ISqsMessage, Output extends SqsOutput = void>(newable: Newable<ISqsMessageHandler<Message, Output>>): SQSHandler;
9
8
  }
10
9
  export interface ISqsLambdaFactory {
11
10
  createHandler<Message extends ISqsMessage, Output extends SqsOutput = void>(newable: Newable<ISqsMessageHandler<Message, Output>>): SQSHandler;
@@ -15,15 +14,12 @@ export declare class SqsLambdaFactory implements ISqsLambdaFactory {
15
14
  constructor(container: IServiceContainer);
16
15
  createHandler<Message extends ISqsMessage, Output extends SqsOutput = void>(newable: Newable<ISqsMessageHandler<Message, Output>>): SQSHandler;
17
16
  }
18
- export interface TrigintaSqsOptions {
17
+ export interface TrigintaLegacySqsOptions {
19
18
  matchers?: ISqsRecordMatcher[];
20
19
  }
21
- export declare const useTrigintaSqs: import("@aesop-fables/containr").ServiceModuleMiddlewareWithOptionsFactory<TrigintaSqsOptions>;
20
+ export declare const useTrigintaSqs: import("@aesop-fables/containr").ServiceModuleMiddlewareWithOptionsFactory<TrigintaLegacySqsOptions>;
22
21
  export interface SqsLambdaBootstrapExpression {
23
22
  matchers?: ISqsRecordMatcher[];
24
23
  modules?: IServiceModule[];
25
24
  }
26
- export declare class SqsLambda {
27
- static initialize(expression: SqsLambdaBootstrapExpression): BootstrappedSqsLambdaContext;
28
- static getContainer(): IServiceContainer;
29
- }
25
+ export declare function createBootstrappedSqsLambdaContext(container: IServiceContainer): BootstrappedSqsLambdaContext;
@@ -1,4 +1,16 @@
1
1
  "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
2
14
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
15
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
16
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -12,7 +24,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
24
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
25
  };
14
26
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.SqsLambda = exports.useTrigintaSqs = exports.SqsLambdaFactory = void 0;
27
+ exports.createBootstrappedSqsLambdaContext = exports.useTrigintaSqs = exports.SqsLambdaFactory = void 0;
16
28
  /* eslint-disable @typescript-eslint/ban-types */
17
29
  /* eslint-disable @typescript-eslint/no-explicit-any */
18
30
  /* eslint-disable @typescript-eslint/no-unused-vars */
@@ -25,15 +37,15 @@ const SqsPublisher_1 = require("./SqsPublisher");
25
37
  const MessagePublisher_1 = require("./MessagePublisher");
26
38
  function embedSqsEvent(event) {
27
39
  return (0, containr_1.createServiceModule)('@aesop-fables/triginta/sqs/event', (services) => {
28
- services.register(SqsLambdaServices_1.SqsLambdaServices.CurrentEvent, event);
40
+ services.singleton(SqsLambdaServices_1.SqsLambdaServices.CurrentEvent, event);
29
41
  });
30
42
  }
31
43
  function embedSqsRecord(record) {
32
44
  return (0, containr_1.createServiceModule)('@aesop-fables/triginta/sqs/record', (services) => {
33
- services.register(SqsLambdaServices_1.SqsLambdaServices.CurrentRecord, record);
45
+ services.singleton(SqsLambdaServices_1.SqsLambdaServices.CurrentRecord, record);
34
46
  });
35
47
  }
36
- class SqsLambdaFactory {
48
+ let SqsLambdaFactory = class SqsLambdaFactory {
37
49
  constructor(container) {
38
50
  this.container = container;
39
51
  }
@@ -73,49 +85,33 @@ class SqsLambdaFactory {
73
85
  }
74
86
  return handler;
75
87
  }
76
- }
88
+ };
89
+ SqsLambdaFactory = __decorate([
90
+ __param(0, (0, containr_1.injectContainer)()),
91
+ __metadata("design:paramtypes", [Object])
92
+ ], SqsLambdaFactory);
77
93
  exports.SqsLambdaFactory = SqsLambdaFactory;
78
- // Here until we fix containr's array stuff
79
- // I think we might want to just use a different inject call for arrays
80
- class NoOpMatcher {
81
- matches() {
82
- return false;
83
- }
84
- deserializeMessage() {
85
- throw new Error('Method not implemented.');
86
- }
87
- }
88
94
  exports.useTrigintaSqs = (0, containr_1.createServiceModuleWithOptions)('triginta/sqs', (services, options) => {
89
- services.register(SqsLambdaServices_1.SqsLambdaServices.SqsLambdaFactory, (container) => new SqsLambdaFactory(container));
95
+ services.autoResolve(SqsLambdaServices_1.SqsLambdaServices.SqsLambdaFactory, SqsLambdaFactory, containr_1.Scopes.Transient);
90
96
  const { matchers = [] } = options;
91
- if (matchers.length === 0) {
92
- matchers.push(new NoOpMatcher());
93
- }
94
97
  matchers.forEach((matcher) => {
95
- services.addDependency(SqsLambdaServices_1.SqsLambdaServices.RecordMatchers, matcher);
98
+ services.array(SqsLambdaServices_1.SqsLambdaServices.RecordMatchers, matcher);
96
99
  });
97
- services.register(SqsLambdaServices_1.SqsLambdaServices.SqsSettings, {});
98
- services.use(SqsLambdaServices_1.SqsLambdaServices.DefaultRecordMatcher, RecordMatchers_1.DefaultSqsRecordMatcher);
99
- services.use(SqsLambdaServices_1.SqsLambdaServices.MessageDeserializer, RecordMatchers_1.SqsMessageDeserializer);
100
- services.use(SqsLambdaServices_1.SqsLambdaServices.SqsPublisher, SqsPublisher_1.SqsPublisher);
101
- services.use(SqsLambdaServices_1.SqsLambdaServices.MessagePublisher, MessagePublisher_1.MessagePublisher);
100
+ services.singleton(SqsLambdaServices_1.SqsLambdaServices.SqsSettings, {});
101
+ services.autoResolve(SqsLambdaServices_1.SqsLambdaServices.DefaultRecordMatcher, RecordMatchers_1.DefaultSqsRecordMatcher, containr_1.Scopes.Transient);
102
+ services.autoResolve(SqsLambdaServices_1.SqsLambdaServices.MessageDeserializer, RecordMatchers_1.SqsMessageDeserializer, containr_1.Scopes.Transient);
103
+ services.autoResolve(SqsLambdaServices_1.SqsLambdaServices.SqsPublisher, SqsPublisher_1.SqsPublisher, containr_1.Scopes.Transient);
104
+ services.autoResolve(SqsLambdaServices_1.SqsLambdaServices.MessagePublisher, MessagePublisher_1.MessagePublisher, containr_1.Scopes.Transient);
102
105
  });
103
- let _currentContainer;
104
- class SqsLambda {
105
- static initialize(expression) {
106
- const { matchers, modules = [] } = expression;
107
- const container = (0, containr_1.createContainer)([(0, exports.useTrigintaSqs)({ matchers }), ...modules]);
108
- _currentContainer = container;
109
- return {
110
- container,
111
- createHandler(newable) {
112
- const factory = container.get(SqsLambdaServices_1.SqsLambdaServices.SqsLambdaFactory);
113
- return factory.createHandler(newable);
114
- },
115
- };
116
- }
117
- static getContainer() {
118
- return _currentContainer;
119
- }
106
+ function createBootstrappedSqsLambdaContext(container) {
107
+ return {
108
+ createSqsHandler(newable) {
109
+ if (typeof container === 'undefined') {
110
+ throw new Error(`SQS container not initialized`);
111
+ }
112
+ const factory = container.get(SqsLambdaServices_1.SqsLambdaServices.SqsLambdaFactory);
113
+ return factory.createHandler(newable);
114
+ },
115
+ };
120
116
  }
121
- exports.SqsLambda = SqsLambda;
117
+ exports.createBootstrappedSqsLambdaContext = createBootstrappedSqsLambdaContext;
@@ -1,14 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SqsLambdaServices = void 0;
4
+ const Utils_1 = require("../Utils");
5
+ const namedService = (0, Utils_1.createServiceNamespacer)('sqs');
4
6
  exports.SqsLambdaServices = {
5
- SqsLambdaFactory: 'SqsLambdaFactory',
6
- DefaultRecordMatcher: 'DefaultRecordMatcher',
7
- MessageDeserializer: 'MessageDeserializer',
8
- RecordMatchers: 'RecordMatchers',
9
- MessagePublisher: 'MessagePublisher',
10
- SqsPublisher: 'SqsPublisher',
11
- SqsSettings: 'SqsSettings',
12
- CurrentEvent: 'SqsCurrentEvent',
13
- CurrentRecord: 'SqsCurrentRecord',
7
+ SqsLambdaFactory: namedService('SqsLambdaFactory'),
8
+ DefaultRecordMatcher: namedService('DefaultRecordMatcher'),
9
+ MessageDeserializer: namedService('MessageDeserializer'),
10
+ RecordMatchers: namedService('RecordMatchers'),
11
+ MessagePublisher: namedService('MessagePublisher'),
12
+ SqsPublisher: namedService('SqsPublisher'),
13
+ SqsSettings: namedService('SqsSettings'),
14
+ CurrentEvent: namedService('SqsCurrentEvent'),
15
+ CurrentRecord: namedService('SqsCurrentRecord'),
14
16
  };
@@ -23,13 +23,13 @@ class ValidationContext {
23
23
  }
24
24
  isEmpty() {
25
25
  const value = this.value();
26
- if (typeof value === 'undefined' || !value) {
26
+ if (typeof value === 'undefined' || value === null) {
27
27
  return true;
28
28
  }
29
29
  if (typeof value === 'string') {
30
30
  return value.length === 0 || value.trim().length === 0;
31
31
  }
32
- return value === 0;
32
+ return false;
33
33
  }
34
34
  }
35
35
  exports.ValidationContext = ValidationContext;
@@ -1,9 +1,9 @@
1
- import { IRequestContext } from '../http/IRequestContext';
1
+ import { IServiceContainer } from '@aesop-fables/containr';
2
2
  import { IConfiguredValidationRule } from './IConfiguredValidationRule';
3
3
  import { IValidator } from './IValidator';
4
4
  import { IValidatorFactory } from './IValidatorFactory';
5
5
  export declare class ValidatorFactory implements IValidatorFactory {
6
- private readonly context;
7
- constructor(context: IRequestContext);
6
+ private readonly container;
7
+ constructor(container: IServiceContainer);
8
8
  create(rules: IConfiguredValidationRule[]): IValidator;
9
9
  }
@@ -14,18 +14,17 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.ValidatorFactory = void 0;
16
16
  const containr_1 = require("@aesop-fables/containr");
17
- const HttpLambdaServices_1 = require("../http/HttpLambdaServices");
18
17
  const Validator_1 = require("./Validator");
19
18
  let ValidatorFactory = class ValidatorFactory {
20
- constructor(context) {
21
- this.context = context;
19
+ constructor(container) {
20
+ this.container = container;
22
21
  }
23
22
  create(rules) {
24
- return new Validator_1.Validator(this.context.container, rules);
23
+ return new Validator_1.Validator(this.container, rules);
25
24
  }
26
25
  };
27
26
  ValidatorFactory = __decorate([
28
- __param(0, (0, containr_1.inject)(HttpLambdaServices_1.HttpLambdaServices.RequestContext)),
27
+ __param(0, (0, containr_1.injectContainer)()),
29
28
  __metadata("design:paramtypes", [Object])
30
29
  ], ValidatorFactory);
31
30
  exports.ValidatorFactory = ValidatorFactory;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aesop-fables/triginta",
3
- "version": "0.7.5",
3
+ "version": "0.8.1",
4
4
  "description": "A lightweight framework that wraps the basic infrastructure usages of AWS Lambda (SQS, Kinesis, etc.).",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -24,18 +24,18 @@
24
24
  "postversion": "git push && git push --tags"
25
25
  },
26
26
  "devDependencies": {
27
- "@aesop-fables/containr": "^0.2.5",
28
- "@aesop-fables/containr-testing": "^0.2.3",
27
+ "@aesop-fables/containr": "^0.3.4",
28
+ "@aesop-fables/containr-testing": "^0.3.0",
29
29
  "@middy/core": "^4.2.7",
30
- "@middy/http-error-handler": "^4.2.3",
30
+ "@middy/http-error-handler": "^4.4.3",
31
31
  "@middy/http-json-body-parser": "^4.2.3",
32
32
  "@middy/util": "^4.3.1",
33
33
  "@types/aws-lambda": "^8.10.109",
34
34
  "@types/jest": "^29.5.0",
35
- "@types/node": "^18.11.11",
36
- "@typescript-eslint/eslint-plugin": "^5.45.1",
37
- "@typescript-eslint/parser": "5.59.2",
38
- "aws-sdk": "^2.1363.0",
35
+ "@types/node": "^18.16.16",
36
+ "@typescript-eslint/eslint-plugin": "^5.59.8",
37
+ "@typescript-eslint/parser": "5.59.8",
38
+ "aws-sdk": "^2.1386.0",
39
39
  "esbuild": "^0.17.8",
40
40
  "eslint": "8.40.0",
41
41
  "eslint-config-prettier": "^8.5.0",