@yopdev/dev-server 1.8.0-alpha.1 → 2.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/assert.js +1 -2
- package/dist/src/cloudformation-event-proxy.d.ts +13 -0
- package/dist/src/cloudformation-event-proxy.js +25 -0
- package/dist/src/cloudformation-lambda-http-proxy.d.ts +16 -0
- package/dist/src/cloudformation-lambda-http-proxy.js +45 -0
- package/dist/src/cloudformation.d.ts +28 -0
- package/dist/src/cloudformation.js +46 -0
- package/dist/src/container.js +23 -70
- package/dist/src/deferred.js +30 -90
- package/dist/src/dev-server.d.ts +1 -0
- package/dist/src/dev-server.js +51 -51
- package/dist/src/dynamodb.js +25 -74
- package/dist/src/event-proxy.d.ts +3 -1
- package/dist/src/event-proxy.js +52 -108
- package/dist/src/factories.js +11 -64
- package/dist/src/http-server.js +23 -25
- package/dist/src/index.d.ts +5 -4
- package/dist/src/index.js +8 -46
- package/dist/src/internal-queue.d.ts +5 -2
- package/dist/src/internal-queue.js +42 -99
- package/dist/src/lambda-http-proxy.d.ts +13 -5
- package/dist/src/lambda-http-proxy.js +33 -78
- package/dist/src/localstack.js +37 -79
- package/dist/src/mappers.d.ts +3 -2
- package/dist/src/mappers.js +29 -26
- package/dist/src/pre-traffic-hooks.d.ts +2 -11
- package/dist/src/pre-traffic-hooks.js +11 -56
- package/dist/src/responses.d.ts +3 -2
- package/dist/src/responses.js +4 -1
- package/dist/src/s3.d.ts +2 -2
- package/dist/src/s3.js +15 -64
- package/dist/src/scheduled-tasks.js +11 -56
- package/dist/src/services.d.ts +5 -2
- package/dist/src/services.js +18 -54
- package/dist/src/sns-http-proxy.js +41 -59
- package/dist/src/sns.js +29 -79
- package/dist/src/sqs.d.ts +3 -1
- package/dist/src/sqs.js +27 -65
- package/dist/src/stoppable.js +11 -50
- package/dist/src/tunnel.js +41 -68
- package/package.json +5 -1
package/dist/src/assert.js
CHANGED
|
@@ -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,25 @@
|
|
|
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, config);
|
|
20
|
+
this.afterStart = (_name, _config, routes) => routes;
|
|
21
|
+
}
|
|
22
|
+
logHandler(handler) {
|
|
23
|
+
return `detected sns handler ${handler.name}`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { CloudFormationSetupConfig } from './cloudformation';
|
|
3
|
+
import { DevServerConfig } from './config';
|
|
4
|
+
import { HttpSettings } from './http-server';
|
|
5
|
+
import { APIGatewayEventRequestContextV2WithGenericAuthorizer, Route } from './lambda-http-proxy';
|
|
6
|
+
import { Callback, Service, Startable } from './services';
|
|
7
|
+
import { IncomingMessage } from 'http';
|
|
8
|
+
export declare const newLambdaProxyFromCloudFormationTemplate: <C, A>(name: string, settings: HttpSettings, config: CloudFormationLambdaProxyConfig<C, A>, callback: Callback<string>) => Startable<Service<string>>;
|
|
9
|
+
type CloudFormationLambdaProxyConfig<C, A> = {
|
|
10
|
+
authorizer?: (config: DevServerConfig) => A | undefined;
|
|
11
|
+
extraRoutes: Route<C, A>[];
|
|
12
|
+
prepare?: (config: DevServerConfig) => Promise<void>;
|
|
13
|
+
context?: () => C;
|
|
14
|
+
mapper?: (request: IncomingMessage, body: string) => Promise<APIGatewayEventRequestContextV2WithGenericAuthorizer<A>>;
|
|
15
|
+
} & CloudFormationSetupConfig;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
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, config.context),
|
|
18
|
+
})), config.prepare, config);
|
|
19
|
+
this.settings = settings;
|
|
20
|
+
this.extraRoutes = extraRoutes;
|
|
21
|
+
this.callback = callback;
|
|
22
|
+
this.afterStart = (name, cfg, routes) => (0, lambda_http_proxy_1.newLambdaHttpProxy)(`${name}:apigw`, {
|
|
23
|
+
settings: this.settings,
|
|
24
|
+
routes: this.extraRoutes.concat(routes),
|
|
25
|
+
authorizer: (this.authorizer || (() => undefined))(cfg),
|
|
26
|
+
mapper: this.mapper,
|
|
27
|
+
}, this.callback);
|
|
28
|
+
this.computeWeight = (path) => this.segments(path) - this.variables(path);
|
|
29
|
+
this.segments = (path) => path.split('/').length;
|
|
30
|
+
this.variables = (path) => path.split('(?<').length;
|
|
31
|
+
this.pathWithCapturingGroups = (source) => [...source.matchAll(PATH_VARIABLE_CAPTURE)].reduce((prev, curr) => prev.replaceAll(curr[0], `(?<${this.normalizeCaptureGroupName(curr[1])}>.*)`), source);
|
|
32
|
+
this.normalizeCaptureGroupName = (original) => (original === 'proxy+' ? PROXY_PATH_PARAM : original);
|
|
33
|
+
this.pathParameterCapture = (pathWithCapturingGroups, handler, context) => async (event) => {
|
|
34
|
+
const pathParameters = pathWithCapturingGroups.exec(event.rawPath)?.groups;
|
|
35
|
+
event.pathParameters = Object.fromEntries((Object.entries(pathParameters ?? {}))
|
|
36
|
+
.map(([k, v]) => [k, decodeURIComponent(v)]));
|
|
37
|
+
return handler(event, context?.());
|
|
38
|
+
};
|
|
39
|
+
this.mapper = config?.mapper;
|
|
40
|
+
this.authorizer = config?.authorizer;
|
|
41
|
+
}
|
|
42
|
+
logHandler(handler) {
|
|
43
|
+
return `detected handler for ${handler.method} on ${handler.path} with weight ${handler.weight}`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -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 template;
|
|
9
|
+
private readonly handlers;
|
|
10
|
+
private readonly handlerNameResolver;
|
|
11
|
+
private readonly LOGGER;
|
|
12
|
+
constructor(name: string, eventFilter: (event: Event<P>) => boolean, handlerResolver: (event: Event<P>, handler: H) => Promise<R>, beforeStart: ((config: DevServerConfig) => Promise<void>) | undefined, config: CloudFormationSetupConfig);
|
|
13
|
+
start: (config: DevServerConfig) => Promise<F>;
|
|
14
|
+
protected abstract afterStart: (name: string, config: DevServerConfig, routes: R[]) => 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,46 @@
|
|
|
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, config) {
|
|
10
|
+
this.name = name;
|
|
11
|
+
this.eventFilter = eventFilter;
|
|
12
|
+
this.handlerResolver = handlerResolver;
|
|
13
|
+
this.beforeStart = beforeStart;
|
|
14
|
+
this.start = async (config) => (this.beforeStart || Promise.resolve)(config)
|
|
15
|
+
.then(this.resolvedHandlers)
|
|
16
|
+
.then(async (routes) => this.afterStart(this.name, config, routes));
|
|
17
|
+
this.resolvedHandlers = async () => {
|
|
18
|
+
const template = this.template(this.name);
|
|
19
|
+
this.LOGGER.info('parsing %s', template);
|
|
20
|
+
const definition = this.parseApiEvents(template);
|
|
21
|
+
const routes = Object.values(definition)
|
|
22
|
+
.filter((resource) => resource.Type === 'AWS::Serverless::Function')
|
|
23
|
+
.filter((resource) => resource.Properties.Events)
|
|
24
|
+
.flatMap((resource) => Object.values(resource.Properties.Events).map((event) => ({
|
|
25
|
+
...event,
|
|
26
|
+
Handler: resource.Properties.Handler,
|
|
27
|
+
})))
|
|
28
|
+
.filter(this.eventFilter)
|
|
29
|
+
.map(async (event) => import(this.handlers(this.name)).then(async (handlers) => Promise.resolve(handlers[this.handlerNameResolver(event.Handler)])
|
|
30
|
+
.then(async (handler) => this.handlerResolver(event, handler))
|
|
31
|
+
.then((handler) => {
|
|
32
|
+
this.LOGGER.info(this.logHandler(handler));
|
|
33
|
+
return handler;
|
|
34
|
+
})));
|
|
35
|
+
return Promise.all(routes);
|
|
36
|
+
};
|
|
37
|
+
this.parseApiEvents = (path) => (0, js_yaml_1.load)((0, fs_1.readFileSync)(path).toString(), {
|
|
38
|
+
schema: js_yaml_cloudformation_schema_1.CLOUDFORMATION_SCHEMA,
|
|
39
|
+
}).Resources;
|
|
40
|
+
this.LOGGER = logging_1.LoggerFactory.create(`CFN:FUNCTION[${name}]`);
|
|
41
|
+
this.template = config.template;
|
|
42
|
+
this.handlers = config.handlers;
|
|
43
|
+
this.handlerNameResolver = config.handlerNameResolver;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.CloudFormationSetup = CloudFormationSetup;
|
package/dist/src/container.js
CHANGED
|
@@ -1,80 +1,33 @@
|
|
|
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.newContainer = void 0;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return new services_1.Service(new Container(name, config.image, config.networkAlias, config.environment, config.bindMounts, config.exposedPorts, config.logConsumer, config.startup, config.endpointBuilder), callback);
|
|
45
|
-
};
|
|
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);
|
|
46
8
|
exports.newContainer = newContainer;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
var _this = this;
|
|
9
|
+
class Container {
|
|
10
|
+
constructor(name, image, networkAlias, environment, bindMounts, exposedPorts, logConsumer, startup, endpointBuilder) {
|
|
50
11
|
this.name = name;
|
|
51
12
|
this.networkAlias = networkAlias;
|
|
52
|
-
this.start =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}); }); };
|
|
68
|
-
this.LOGGER = logging_1.LoggerFactory.create("CONTAINER[".concat(name, "]"));
|
|
69
|
-
var generic = new testcontainers_1.GenericContainer(image);
|
|
70
|
-
var withEnvironment = environment ? generic.withEnvironment(environment) : generic;
|
|
71
|
-
var withBindMounts = bindMounts ? withEnvironment.withBindMounts(bindMounts) : withEnvironment;
|
|
72
|
-
var withExposedPorts = exposedPorts ? withBindMounts.withExposedPorts.apply(withBindMounts, exposedPorts) : withBindMounts;
|
|
73
|
-
var withLogConsumer = logConsumer ? withExposedPorts.withLogConsumer(logConsumer) : withExposedPorts;
|
|
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: async () => { this.LOGGER.warn('no container'); } }).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;
|
|
74
28
|
this.container = startup ? withLogConsumer.withWaitStrategy(startup.waitStrategy).withStartupTimeout(startup.timeout) : withLogConsumer;
|
|
75
29
|
this.networkAlias = networkAlias;
|
|
76
|
-
this.endpointBuilder = endpointBuilder
|
|
30
|
+
this.endpointBuilder = endpointBuilder ?? ((port) => `http://localhost:${port}`);
|
|
77
31
|
}
|
|
78
|
-
|
|
79
|
-
}());
|
|
32
|
+
}
|
|
80
33
|
;
|
package/dist/src/deferred.js
CHANGED
|
@@ -1,105 +1,45 @@
|
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
9
|
+
const promised = (lifecycle) => new services_1.Service(new Promised(lifecycle));
|
|
46
10
|
exports.promised = promised;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
var _this = this;
|
|
11
|
+
class Lazy {
|
|
12
|
+
constructor(configurable) {
|
|
50
13
|
this.configurable = configurable;
|
|
51
|
-
this.stop =
|
|
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(
|
|
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
|
-
|
|
66
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
function Promised(configurable) {
|
|
87
|
-
var _this = this;
|
|
88
|
-
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 () { return __generator(this, function (_a) {
|
|
99
|
-
return [2 /*return*/, this.service.stop()];
|
|
100
|
-
}); }); };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
class Promised {
|
|
34
|
+
constructor(configurable) {
|
|
101
35
|
this.name = (0, crypto_1.randomUUID)();
|
|
102
|
-
this.LOGGER = logging_1.LoggerFactory.create(
|
|
36
|
+
this.LOGGER = logging_1.LoggerFactory.create(`PROMISED[${this.name}]`);
|
|
37
|
+
let initialized;
|
|
38
|
+
this.start = async (config) => configurable(config)
|
|
39
|
+
.catch((e) => e?.cleanup?.() ?? Promise.reject(e))
|
|
40
|
+
.then((service) => initialized = service)
|
|
41
|
+
.tap((service) => this.LOGGER.info('DISCOVERY:%s', service.name))
|
|
42
|
+
.then((service) => service.start(config));
|
|
43
|
+
this.stop = async () => (initialized ?? { stop: async () => this.LOGGER.info('not started') }).stop();
|
|
103
44
|
}
|
|
104
|
-
|
|
105
|
-
}());
|
|
45
|
+
}
|
package/dist/src/dev-server.d.ts
CHANGED
package/dist/src/dev-server.js
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DevServer = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
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) {
|
|
15
14
|
this.name = name;
|
|
16
15
|
this.service = service;
|
|
17
16
|
this.config = config;
|
|
18
|
-
this.start =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
+
.catch((e) => this.shutdown()
|
|
46
|
+
.then(() => this.LOGGER.error('error starting service'))
|
|
47
|
+
.then(() => Promise.reject(e)))
|
|
48
|
+
.then(() => this.LOGGER.info('started'))
|
|
49
|
+
.then(() => this);
|
|
50
|
+
this.stop = () => this.shutdown()
|
|
51
|
+
.then(() => this.LOGGER.info('stopped'));
|
|
52
|
+
this.shutdown = async () => this.service.stop()
|
|
51
53
|
.then(tunnel_1.terminate)
|
|
52
|
-
.then(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.eventProxyTopic = "EventProxyTopic".concat(encodedName);
|
|
54
|
+
.then(() => this.localStack?.stop());
|
|
55
|
+
this.LOGGER = logging_1.LoggerFactory.create(`DEVSERVER[${name}]`);
|
|
56
|
+
const encodedName = Buffer.from(name).toString('hex').substring(0, 64);
|
|
57
|
+
this.eventProxyTopic = `EventProxyTopic${encodedName}`;
|
|
57
58
|
}
|
|
58
|
-
|
|
59
|
-
}());
|
|
59
|
+
}
|
|
60
60
|
exports.DevServer = DevServer;
|