@yopdev/dev-server 1.4.1-alpha.0 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/src/assert.js +1 -2
  2. package/dist/src/cloudformation-event-proxy.d.ts +13 -0
  3. package/dist/src/cloudformation-event-proxy.js +24 -0
  4. package/dist/src/cloudformation-lambda-http-proxy.d.ts +12 -0
  5. package/dist/src/cloudformation-lambda-http-proxy.js +42 -0
  6. package/dist/src/cloudformation.d.ts +28 -0
  7. package/dist/src/cloudformation.js +47 -0
  8. package/dist/src/config.d.ts +2 -0
  9. package/dist/src/container.d.ts +18 -0
  10. package/dist/src/container.js +33 -0
  11. package/dist/src/deferred.js +28 -93
  12. package/dist/src/dev-server.js +48 -48
  13. package/dist/src/dynamodb.js +25 -75
  14. package/dist/src/event-proxy.d.ts +5 -4
  15. package/dist/src/event-proxy.js +52 -113
  16. package/dist/src/factories.js +11 -64
  17. package/dist/src/http-server.d.ts +1 -1
  18. package/dist/src/http-server.js +23 -26
  19. package/dist/src/index.d.ts +14 -1
  20. package/dist/src/index.js +18 -1
  21. package/dist/src/internal-queue.d.ts +5 -2
  22. package/dist/src/internal-queue.js +44 -101
  23. package/dist/src/lambda-http-proxy.d.ts +9 -3
  24. package/dist/src/lambda-http-proxy.js +33 -79
  25. package/dist/src/localstack.js +37 -79
  26. package/dist/src/mappers.d.ts +1 -1
  27. package/dist/src/mappers.js +14 -26
  28. package/dist/src/pre-traffic-hooks.d.ts +2 -11
  29. package/dist/src/pre-traffic-hooks.js +12 -61
  30. package/dist/src/responses.d.ts +1 -1
  31. package/dist/src/responses.js +4 -1
  32. package/dist/src/s3.d.ts +7 -0
  33. package/dist/src/s3.js +20 -0
  34. package/dist/src/scheduled-tasks.d.ts +2 -13
  35. package/dist/src/scheduled-tasks.js +12 -61
  36. package/dist/src/services.d.ts +4 -2
  37. package/dist/src/services.js +13 -53
  38. package/dist/src/sns-http-proxy.js +41 -59
  39. package/dist/src/sns.js +29 -79
  40. package/dist/src/sqs.d.ts +3 -1
  41. package/dist/src/sqs.js +27 -65
  42. package/dist/src/stoppable.d.ts +1 -1
  43. package/dist/src/stoppable.js +10 -43
  44. package/dist/src/tunnel.d.ts +10 -0
  45. package/dist/src/tunnel.js +52 -0
  46. package/package.json +7 -2
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.assertNotUndefined = void 0;
4
- function assertNotUndefined(value, message) {
5
- if (message === void 0) { message = 'value is undefined'; }
4
+ function assertNotUndefined(value, message = 'value is undefined') {
6
5
  if (value === undefined)
7
6
  throw new Error(message);
8
7
  return value;
@@ -0,0 +1,13 @@
1
+ import { SQSRecord } from 'aws-lambda';
2
+ import { CloudFormationSetupConfig } from './cloudformation';
3
+ import { EventHandler } from './event-proxy';
4
+ import { DevServerConfig } from './config';
5
+ import { Startable } from './services';
6
+ import { Message } from '@aws-sdk/client-sqs';
7
+ export declare const snsEventsFromCloudFormationTemplate: (name: string, config: CloudFormationEventsProxyConfig) => Startable<EventHandler[]>;
8
+ type CloudFormationEventsProxyConfig = {
9
+ topic?: string;
10
+ mapper?: (message: Message) => SQSRecord;
11
+ prepare?: (config: DevServerConfig) => Promise<void>;
12
+ } & CloudFormationSetupConfig;
13
+ export {};
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.snsEventsFromCloudFormationTemplate = void 0;
4
+ const cloudformation_1 = require("./cloudformation");
5
+ const snsEventsFromCloudFormationTemplate = (name, config) => new CloudFormationEventsProxy(name, config);
6
+ exports.snsEventsFromCloudFormationTemplate = snsEventsFromCloudFormationTemplate;
7
+ class CloudFormationEventsProxy extends cloudformation_1.CloudFormationSetup {
8
+ constructor(name, config) {
9
+ super(name, (event) => event.Type === 'SNS', async (event, handler) => ({
10
+ name: handler.name,
11
+ handler: handler,
12
+ matcher: (_, attributes) => {
13
+ const required = Object.entries(event.Properties.FilterPolicy ?? []).flatMap((entry) => entry[1].map((value) => value + entry[0]));
14
+ if (required.length == 0)
15
+ return true;
16
+ const actual = Object.entries(attributes).flatMap((entry) => entry[1].Value + entry[0]);
17
+ return required.filter((e) => actual.includes(e)).length > 0;
18
+ },
19
+ }), config.prepare, (_name, _config, routes) => routes, config);
20
+ }
21
+ logHandler(handler) {
22
+ return `detected sns handler ${handler.name}`;
23
+ }
24
+ }
@@ -0,0 +1,12 @@
1
+ import { CloudFormationSetupConfig } from './cloudformation';
2
+ import { DevServerConfig } from './config';
3
+ import { HttpSettings } from './http-server';
4
+ import { Authorizer, Route } from './lambda-http-proxy';
5
+ import { Callback, Service, Startable } from './services';
6
+ export declare const newLambdaProxyFromCloudFormationTemplate: (name: string, settings: HttpSettings, config: CloudFormationLambdaProxyConfig, callback: Callback<string>) => Startable<Service<string>>;
7
+ type CloudFormationLambdaProxyConfig = {
8
+ authorizer?: (config: DevServerConfig) => Authorizer | undefined;
9
+ extraRoutes: Route[];
10
+ prepare?: (config: DevServerConfig) => Promise<void>;
11
+ } & CloudFormationSetupConfig;
12
+ export {};
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.newLambdaProxyFromCloudFormationTemplate = void 0;
4
+ const cloudformation_1 = require("./cloudformation");
5
+ const lambda_http_proxy_1 = require("./lambda-http-proxy");
6
+ const PATH_VARIABLE_CAPTURE = /{(.*?)}/g;
7
+ const QUERY_STRING_OR_LOCATION_REG_EXP = '(?:([?#].*))?';
8
+ const PROXY_PATH_PARAM = 'proxy';
9
+ const newLambdaProxyFromCloudFormationTemplate = (name, settings, config, callback) => new CloudFormationLambdaProxy(name, settings, config.extraRoutes, config, callback);
10
+ exports.newLambdaProxyFromCloudFormationTemplate = newLambdaProxyFromCloudFormationTemplate;
11
+ class CloudFormationLambdaProxy extends cloudformation_1.CloudFormationSetup {
12
+ constructor(name, settings, extraRoutes, config, callback) {
13
+ super(name, (event) => event.Type === 'HttpApi', async (event, handler) => Promise.resolve(this.pathWithCapturingGroups(event.Properties.Path)).then((pathWithCapturingGroups) => ({
14
+ method: new RegExp(event.Properties.Method),
15
+ path: new RegExp(`^${pathWithCapturingGroups}${QUERY_STRING_OR_LOCATION_REG_EXP}?$`),
16
+ weight: this.computeWeight(pathWithCapturingGroups),
17
+ handler: this.pathParameterCapture(new RegExp(pathWithCapturingGroups), handler),
18
+ })), config.prepare, (name, cfg, routes) => {
19
+ return (0, lambda_http_proxy_1.newLambdaHttpProxy)(`${name}:apigw`, {
20
+ settings: this.settings,
21
+ routes: this.extraRoutes.concat(routes),
22
+ authorizer: (config?.authorizer || (() => undefined))(cfg),
23
+ }, callback);
24
+ }, config);
25
+ this.settings = settings;
26
+ this.extraRoutes = extraRoutes;
27
+ this.computeWeight = (path) => this.segments(path) - this.variables(path);
28
+ this.segments = (path) => path.split('/').length;
29
+ this.variables = (path) => path.split('(?<').length;
30
+ this.pathWithCapturingGroups = (source) => [...source.matchAll(PATH_VARIABLE_CAPTURE)].reduce((prev, curr) => prev.replaceAll(curr[0], `(?<${this.normalizeCaptureGroupName(curr[1])}>.*)`), source);
31
+ this.normalizeCaptureGroupName = (original) => (original === 'proxy+' ? PROXY_PATH_PARAM : original);
32
+ this.pathParameterCapture = (pathWithCapturingGroups, handler) => async (event) => {
33
+ const pathParameters = pathWithCapturingGroups.exec(event.path)?.groups;
34
+ event.pathParameters = Object.fromEntries((Object.entries(pathParameters ?? {}))
35
+ .map(([k, v]) => [k, decodeURIComponent(v)]));
36
+ return handler(event);
37
+ };
38
+ }
39
+ logHandler(handler) {
40
+ return `detected handler for ${handler.method} on ${handler.path} with weight ${handler.weight}`;
41
+ }
42
+ }
@@ -0,0 +1,28 @@
1
+ import { DevServerConfig } from './config';
2
+ import { Startable } from './services';
3
+ export declare abstract class CloudFormationSetup<P, H, R, F> implements Startable<F> {
4
+ readonly name: string;
5
+ private readonly eventFilter;
6
+ private readonly handlerResolver;
7
+ private readonly beforeStart;
8
+ private readonly afterStart;
9
+ private readonly template;
10
+ private readonly handlers;
11
+ private readonly handlerNameResolver;
12
+ private readonly LOGGER;
13
+ constructor(name: string, eventFilter: (event: Event<P>) => boolean, handlerResolver: (event: Event<P>, handler: H) => Promise<R>, beforeStart: ((config: DevServerConfig) => Promise<void>) | undefined, afterStart: (name: string, config: DevServerConfig, routes: R[]) => F, config: CloudFormationSetupConfig);
14
+ start: (config: DevServerConfig) => Promise<F>;
15
+ private resolvedHandlers;
16
+ abstract logHandler(handler: R): string;
17
+ private parseApiEvents;
18
+ }
19
+ export type CloudFormationSetupConfig = {
20
+ template: (name: string) => string;
21
+ handlers: (name: string) => string;
22
+ handlerNameResolver: (name: string) => string;
23
+ };
24
+ type Event<P> = {
25
+ Type: string;
26
+ Properties: P;
27
+ };
28
+ export {};
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CloudFormationSetup = void 0;
4
+ const js_yaml_cloudformation_schema_1 = require("js-yaml-cloudformation-schema");
5
+ const fs_1 = require("fs");
6
+ const js_yaml_1 = require("js-yaml");
7
+ const logging_1 = require("@yopdev/logging");
8
+ class CloudFormationSetup {
9
+ constructor(name, eventFilter, handlerResolver, beforeStart, afterStart, config) {
10
+ this.name = name;
11
+ this.eventFilter = eventFilter;
12
+ this.handlerResolver = handlerResolver;
13
+ this.beforeStart = beforeStart;
14
+ this.afterStart = afterStart;
15
+ this.start = async (config) => (this.beforeStart || Promise.resolve)(config)
16
+ .then(this.resolvedHandlers)
17
+ .then(async (routes) => this.afterStart(this.name, config, routes));
18
+ this.resolvedHandlers = async () => {
19
+ const template = this.template(this.name);
20
+ this.LOGGER.info('parsing %s', template);
21
+ const definition = this.parseApiEvents(template);
22
+ const routes = Object.values(definition)
23
+ .filter((resource) => resource.Type === 'AWS::Serverless::Function')
24
+ .filter((resource) => resource.Properties.Events)
25
+ .flatMap((resource) => Object.values(resource.Properties.Events).map((event) => ({
26
+ ...event,
27
+ Handler: resource.Properties.Handler,
28
+ })))
29
+ .filter(this.eventFilter)
30
+ .map(async (event) => import(this.handlers(this.name)).then(async (handlers) => Promise.resolve(handlers[this.handlerNameResolver(event.Handler)])
31
+ .then(async (handler) => this.handlerResolver(event, handler))
32
+ .then((handler) => {
33
+ this.LOGGER.info(this.logHandler(handler));
34
+ return handler;
35
+ })));
36
+ return Promise.all(routes);
37
+ };
38
+ this.parseApiEvents = (path) => (0, js_yaml_1.load)((0, fs_1.readFileSync)(path).toString(), {
39
+ schema: js_yaml_cloudformation_schema_1.CLOUDFORMATION_SCHEMA,
40
+ }).Resources;
41
+ this.LOGGER = logging_1.LoggerFactory.create(`CFN:FUNCTION[${name}]`);
42
+ this.template = config.template;
43
+ this.handlers = config.handlers;
44
+ this.handlerNameResolver = config.handlerNameResolver;
45
+ }
46
+ }
47
+ exports.CloudFormationSetup = CloudFormationSetup;
@@ -2,6 +2,7 @@ import { Sqs } from "./sqs";
2
2
  import { Sns } from "./sns";
3
3
  import { DynamoDb } from "./dynamodb";
4
4
  import { StartedNetwork } from "testcontainers";
5
+ import { S3 } from "./s3";
5
6
  export type Config = {
6
7
  boundServicesPort?: number;
7
8
  localStackDockerImage?: string;
@@ -20,6 +21,7 @@ export type DevServerConfig = {
20
21
  network: StartedNetwork;
21
22
  sqs: Sqs;
22
23
  sns: Sns;
24
+ s3: S3;
23
25
  dynamo: DynamoDb;
24
26
  eventsProxy: {
25
27
  topic: {
@@ -0,0 +1,18 @@
1
+ import { BindMount, Environment } from 'testcontainers/build/types';
2
+ import { Callback, Service } from './services';
3
+ import { PortWithOptionalBinding } from 'testcontainers/build/utils/port';
4
+ import { Readable } from 'stream';
5
+ import { WaitStrategy } from 'testcontainers/build/wait-strategies/wait-strategy';
6
+ export declare const newContainer: (name: string, config: {
7
+ image: string;
8
+ networkAlias: string;
9
+ environment?: Environment;
10
+ bindMounts?: BindMount[];
11
+ exposedPorts?: PortWithOptionalBinding[];
12
+ logConsumer?: (stream: Readable) => unknown;
13
+ startup?: {
14
+ waitStrategy: WaitStrategy;
15
+ timeout: number;
16
+ };
17
+ endpointBuilder?: (port: number) => string;
18
+ }, callback?: Callback<string>) => Service<string>;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.newContainer = void 0;
4
+ const logging_1 = require("@yopdev/logging");
5
+ const testcontainers_1 = require("testcontainers");
6
+ const services_1 = require("./services");
7
+ const newContainer = (name, config, callback) => new services_1.Service(new Container(name, config.image, config.networkAlias, config.environment, config.bindMounts, config.exposedPorts, config.logConsumer, config.startup, config.endpointBuilder), callback);
8
+ exports.newContainer = newContainer;
9
+ class Container {
10
+ constructor(name, image, networkAlias, environment, bindMounts, exposedPorts, logConsumer, startup, endpointBuilder) {
11
+ this.name = name;
12
+ this.networkAlias = networkAlias;
13
+ this.start = async (config) => Promise.resolve(this.LOGGER.info('start'))
14
+ .then(() => this.container
15
+ .withNetwork(config.network)
16
+ .withNetworkAliases(this.networkAlias)
17
+ .start())
18
+ .then((started) => this.started = started)
19
+ .then(() => this.endpointBuilder(this.started.getFirstMappedPort()))
20
+ .tap((url) => this.LOGGER.debug(url));
21
+ this.stop = async () => this.started.stop().then(() => undefined);
22
+ this.LOGGER = logging_1.LoggerFactory.create(`CONTAINER[${name}]`);
23
+ const generic = new testcontainers_1.GenericContainer(image);
24
+ const withEnvironment = environment ? generic.withEnvironment(environment) : generic;
25
+ const withBindMounts = bindMounts ? withEnvironment.withBindMounts(bindMounts) : withEnvironment;
26
+ const withExposedPorts = exposedPorts ? withBindMounts.withExposedPorts(...exposedPorts) : withBindMounts;
27
+ const withLogConsumer = logConsumer ? withExposedPorts.withLogConsumer(logConsumer) : withExposedPorts;
28
+ this.container = startup ? withLogConsumer.withWaitStrategy(startup.waitStrategy).withStartupTimeout(startup.timeout) : withLogConsumer;
29
+ this.networkAlias = networkAlias;
30
+ this.endpointBuilder = endpointBuilder ?? ((port) => `http://localhost:${port}`);
31
+ }
32
+ }
33
+ ;
@@ -1,109 +1,44 @@
1
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
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
2
  Object.defineProperty(exports, "__esModule", { value: true });
39
3
  exports.promised = exports.lazy = void 0;
40
- var crypto_1 = require("crypto");
41
- var services_1 = require("./services");
42
- var logging_1 = require("@yopdev/logging");
43
- var lazy = function (lifecycle) { return new services_1.Service(new Lazy(lifecycle)); };
4
+ const crypto_1 = require("crypto");
5
+ const services_1 = require("./services");
6
+ const logging_1 = require("@yopdev/logging");
7
+ const lazy = (lifecycle) => new services_1.Service(new Lazy(lifecycle));
44
8
  exports.lazy = lazy;
45
- var promised = function (lifecycle) { return new services_1.Service(new Promised(lifecycle)); };
9
+ const promised = (lifecycle) => new services_1.Service(new Promised(lifecycle));
46
10
  exports.promised = promised;
47
- var Lazy = /** @class */ (function () {
48
- function Lazy(configurable) {
49
- var _this = this;
11
+ class Lazy {
12
+ constructor(configurable) {
50
13
  this.configurable = configurable;
51
- this.stop = function () { return __awaiter(_this, void 0, void 0, function () {
52
- var _this = this;
53
- return __generator(this, function (_a) {
54
- return [2 /*return*/, this.withStartedOr(function (s) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
55
- return [2 /*return*/, s.stop()];
56
- }); }); }, function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
57
- return [2 /*return*/, Promise.reject(new Error('not started'))];
58
- }); }); })];
59
- });
60
- }); };
14
+ this.stop = async () => this.withStartedOr(async (s) => s.stop(), async () => Promise.reject(new Error('not started')));
61
15
  this.started = undefined;
62
16
  this.name = (0, crypto_1.randomUUID)();
63
- this.LOGGER = logging_1.LoggerFactory.create("LAZY[".concat(this.name, "]"));
17
+ this.LOGGER = logging_1.LoggerFactory.create(`LAZY[${this.name}]`);
18
+ }
19
+ async start(config) {
20
+ const local = this.configurable(config);
21
+ this.started = local;
22
+ this.LOGGER.info('DISCOVERY:%s', local.name);
23
+ return local.start(config);
64
24
  }
65
- Lazy.prototype.start = function (config) {
66
- return __awaiter(this, void 0, void 0, function () {
67
- var local;
68
- return __generator(this, function (_a) {
69
- local = this.configurable(config);
70
- this.started = local;
71
- this.LOGGER.info('DISCOVERY:%s', local.name);
72
- return [2 /*return*/, local.start(config)];
73
- });
74
- });
75
- };
76
- Lazy.prototype.withStartedOr = function (task, fallback) {
77
- var local = this.started;
25
+ withStartedOr(task, fallback) {
26
+ const local = this.started;
78
27
  if (local !== undefined)
79
28
  task(local);
80
29
  else
81
30
  fallback();
82
- };
83
- return Lazy;
84
- }());
85
- var Promised = /** @class */ (function () {
86
- function Promised(configurable) {
87
- var _this = this;
31
+ }
32
+ }
33
+ class Promised {
34
+ constructor(configurable) {
88
35
  this.configurable = configurable;
89
- this.start = function (config) { return __awaiter(_this, void 0, void 0, function () {
90
- var _this = this;
91
- return __generator(this, function (_a) {
92
- return [2 /*return*/, this.configurable(config)
93
- .then(function (service) { return _this.service = service; })
94
- .then(function (service) { return _this.LOGGER.info('DISCOVERY:%s', service.name); })
95
- .then(function () { return _this.service.start(config); })];
96
- });
97
- }); };
98
- this.stop = function () { return __awaiter(_this, void 0, void 0, function () {
99
- var _this = this;
100
- return __generator(this, function (_a) {
101
- return [2 /*return*/, Promise.resolve(this.LOGGER.info('stopped'))
102
- .then(function () { return _this.service.stop(); })];
103
- });
104
- }); };
36
+ this.start = async (config) => this.configurable(config)
37
+ .then((service) => this.service = service)
38
+ .then((service) => this.LOGGER.info('DISCOVERY:%s', service.name))
39
+ .then(() => this.service.start(config));
40
+ this.stop = async () => this.service.stop();
105
41
  this.name = (0, crypto_1.randomUUID)();
106
- this.LOGGER = logging_1.LoggerFactory.create("PROMISED[".concat(this.name, "]"));
42
+ this.LOGGER = logging_1.LoggerFactory.create(`PROMISED[${this.name}]`);
107
43
  }
108
- return Promised;
109
- }());
44
+ }
@@ -1,56 +1,56 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DevServer = void 0;
4
- var testcontainers_1 = require("testcontainers");
5
- var localstack_1 = require("./localstack");
6
- var sqs_1 = require("./sqs");
7
- var dynamodb_1 = require("./dynamodb");
8
- var logging_1 = require("@yopdev/logging");
9
- var sns_1 = require("./sns");
10
- var DevServer = /** @class */ (function () {
11
- function DevServer(name, service, config) {
12
- var _this = this;
4
+ const testcontainers_1 = require("testcontainers");
5
+ const localstack_1 = require("./localstack");
6
+ const sqs_1 = require("./sqs");
7
+ const dynamodb_1 = require("./dynamodb");
8
+ const logging_1 = require("@yopdev/logging");
9
+ const sns_1 = require("./sns");
10
+ const tunnel_1 = require("./tunnel");
11
+ const s3_1 = require("./s3");
12
+ class DevServer {
13
+ constructor(name, service, config) {
13
14
  this.name = name;
14
15
  this.service = service;
15
16
  this.config = config;
16
- this.start = function () {
17
- return Promise.resolve(new testcontainers_1.Network(new testcontainers_1.RandomUuid()).start())
18
- .then(function (network) { return ({
19
- localStack: _this.localStack = new localstack_1.LocalStack(network, _this.config),
20
- network: network
21
- }); })
22
- .then(function (infra) { return infra.localStack.start().then(function (config) { return ({
23
- aws: config,
24
- network: infra.network
25
- }); }); })
26
- .then(function (infra) { return Promise
27
- .resolve(new sns_1.Sns(infra.aws))
28
- .then(function (sns) { return sns
29
- .createTopic(_this.eventProxyTopic)
30
- .then(function (eventProxyTopicArn) { return ({
31
- raw: infra.aws,
32
- network: infra.network,
33
- sqs: new sqs_1.Sqs(infra.aws),
34
- sns: new sns_1.Sns(infra.aws),
35
- dynamo: new dynamodb_1.DynamoDb(infra.aws),
36
- eventsProxy: {
37
- topic: {
38
- arn: eventProxyTopicArn
39
- }
40
- },
41
- }); }); }); })
42
- .then(function (config) { _this.LOGGER.debug('starting. config is %o', config); return config; })
43
- .then(function (aws) { return _this.service.start(aws); })
44
- .then(function () { return _this.LOGGER.info('started'); })
45
- .then(function () { return _this; });
46
- };
47
- this.stop = function () { return _this.service.stop()
48
- .then(function () { var _a; return (_a = _this.localStack) === null || _a === void 0 ? void 0 : _a.stop(); })
49
- .then(function () { return _this.LOGGER.info('stopped'); }); };
50
- this.LOGGER = logging_1.LoggerFactory.create("DEVSERVER[".concat(name, "]"));
51
- var encodedName = Buffer.from(name).toString('hex').substring(0, 64);
52
- this.eventProxyTopic = "EventProxyTopic".concat(encodedName);
17
+ this.start = () => Promise.resolve(new testcontainers_1.Network(new testcontainers_1.RandomUuid()).start())
18
+ .then((network) => ({
19
+ localStack: this.localStack = new localstack_1.LocalStack(network, this.config),
20
+ network: network
21
+ }))
22
+ .then((infra) => infra.localStack.start().then((config) => ({
23
+ aws: config,
24
+ network: infra.network
25
+ })))
26
+ .then((infra) => Promise
27
+ .resolve(new sns_1.Sns(infra.aws))
28
+ .then((sns) => sns
29
+ .createTopic(this.eventProxyTopic)
30
+ .then((eventProxyTopicArn) => ({
31
+ raw: infra.aws,
32
+ network: infra.network,
33
+ sqs: new sqs_1.Sqs(infra.aws),
34
+ sns: new sns_1.Sns(infra.aws),
35
+ s3: new s3_1.S3(infra.aws),
36
+ dynamo: new dynamodb_1.DynamoDb(infra.aws),
37
+ eventsProxy: {
38
+ topic: {
39
+ arn: eventProxyTopicArn
40
+ }
41
+ },
42
+ }))))
43
+ .tap((config) => this.LOGGER.debug('config is %o', config))
44
+ .then((aws) => this.service.start(aws))
45
+ .then(() => this.LOGGER.info('started'))
46
+ .then(() => this);
47
+ this.stop = () => this.service.stop()
48
+ .then(tunnel_1.terminate)
49
+ .then(() => this.localStack?.stop())
50
+ .then(() => this.LOGGER.info('stopped'));
51
+ this.LOGGER = logging_1.LoggerFactory.create(`DEVSERVER[${name}]`);
52
+ const encodedName = Buffer.from(name).toString('hex').substring(0, 64);
53
+ this.eventProxyTopic = `EventProxyTopic${encodedName}`;
53
54
  }
54
- return DevServer;
55
- }());
55
+ }
56
56
  exports.DevServer = DevServer;
@@ -1,85 +1,35 @@
1
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
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
2
  Object.defineProperty(exports, "__esModule", { value: true });
39
3
  exports.DynamoDb = exports.newDynamoDbTable = void 0;
40
- var client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
41
- var logging_1 = require("@yopdev/logging");
42
- var services_1 = require("./services");
43
- var newDynamoDbTable = function (name, config, callback) { return new services_1.Service(new DynamoDbTableCreator(name, config.command), callback); };
4
+ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
5
+ const logging_1 = require("@yopdev/logging");
6
+ const services_1 = require("./services");
7
+ const assert_1 = require("./assert");
8
+ const newDynamoDbTable = (name, config, callback) => new services_1.Service(new DynamoDbTableCreator(name, config.command), callback);
44
9
  exports.newDynamoDbTable = newDynamoDbTable;
45
- var DynamoDbTableCreator = /** @class */ (function () {
46
- function DynamoDbTableCreator(name, command) {
47
- var _this = this;
10
+ class DynamoDbTableCreator {
11
+ constructor(name, command) {
48
12
  this.name = name;
49
13
  this.command = command;
50
- this.start = function (config) { return __awaiter(_this, void 0, void 0, function () {
51
- var _this = this;
52
- return __generator(this, function (_a) {
53
- return [2 /*return*/, config.dynamo.createTable(this.command)
54
- .then(function () { return _this.LOGGER.info('created'); })
55
- .then(function () { return _this.name; })];
56
- });
57
- }); };
58
- this.stop = function () { return Promise.resolve()
59
- .then(function () { return _this.LOGGER.info('stopped'); }); };
60
- this.LOGGER = logging_1.LoggerFactory.create("TABLE[".concat(name, "]"));
14
+ this.start = async (config) => config.dynamo.createTable(this.command)
15
+ .tap((output) => this.LOGGER.debug(output))
16
+ .then(() => this.name);
17
+ this.stop = () => Promise.resolve();
18
+ this.LOGGER = logging_1.LoggerFactory.create(`TABLE[${name}]`);
61
19
  }
62
- return DynamoDbTableCreator;
63
- }());
64
- var LOGGER = logging_1.LoggerFactory.create('DYNAMODB');
65
- var DynamoDb = /** @class */ (function () {
66
- function DynamoDb(config) {
67
- var _this = this;
68
- this.createTable = function (factory) { return __awaiter(_this, void 0, void 0, function () {
69
- return __generator(this, function (_a) {
70
- return [2 /*return*/, this.client
71
- .send(factory) //
72
- .then(function (table) { var _a; LOGGER.info('table created %s', (_a = table.TableDescription) === null || _a === void 0 ? void 0 : _a.TableName); return table; })
73
- .catch(function (reason) {
74
- LOGGER.error('failed to create table');
75
- if (reason.name !== 'ResourceInUseException')
76
- return Promise.reject(reason);
77
- })];
78
- });
79
- }); };
20
+ }
21
+ const LOGGER = logging_1.LoggerFactory.create('DYNAMODB');
22
+ class DynamoDb {
23
+ constructor(config) {
24
+ this.createTable = async (factory) => this.client
25
+ .send(factory) //
26
+ .tap((table) => LOGGER.debug('created %s', (0, assert_1.assertNotUndefined)(table.TableDescription).TableName))
27
+ .catch((reason) => {
28
+ LOGGER.error('failed to create table');
29
+ if (reason.name !== 'ResourceInUseException')
30
+ return Promise.reject(reason);
31
+ });
80
32
  this.client = new client_dynamodb_1.DynamoDBClient(config);
81
- LOGGER.debug('initialized');
82
33
  }
83
- return DynamoDb;
84
- }());
34
+ }
85
35
  exports.DynamoDb = DynamoDb;
@@ -1,12 +1,13 @@
1
- import { SQSEvent } from 'aws-lambda';
2
- import { MessageAttributeValue } from '@aws-sdk/client-sqs';
1
+ import { SNSMessageAttributes, SQSEvent, SQSRecord } from 'aws-lambda';
2
+ import { Message } from '@aws-sdk/client-sqs';
3
3
  import { Service } from './services';
4
4
  export declare const newEventsProxy: (name: string, config: {
5
5
  handlers: EventHandler[];
6
6
  topic?: string;
7
- }) => Service<any>;
7
+ mapper?: (message: Message) => SQSRecord;
8
+ }) => Service<void>;
8
9
  export type EventHandler = {
9
10
  name: string;
10
11
  handler: (event: SQSEvent) => Promise<unknown>;
11
- matcher: (subject: string, attributes: Record<string, MessageAttributeValue>) => boolean;
12
+ matcher: (subject: string, attributes: SNSMessageAttributes) => boolean;
12
13
  };