@yopdev/dev-server 1.1.0

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,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.newLambdaHttpProxy = void 0;
4
+ var logging_1 = require("@yopdev/logging");
5
+ var http_server_1 = require("./http-server");
6
+ var mappers_1 = require("./mappers");
7
+ var responses_1 = require("./responses");
8
+ var services_1 = require("./services");
9
+ var newLambdaHttpProxy = function (name, config, service) { return new services_1.Service(new LambdaHttpProxy(name, config.settings, config.handler), service); };
10
+ exports.newLambdaHttpProxy = newLambdaHttpProxy;
11
+ var LambdaHttpProxy = /** @class */ (function () {
12
+ function LambdaHttpProxy(name, settings, handler) {
13
+ var _this = this;
14
+ this.name = name;
15
+ this.start = function () { return _this.server.start(); };
16
+ this.stop = function () { return _this.server.stop()
17
+ .then(function () { return _this.LOGGER.info('stopped'); }); };
18
+ this.handler = function (lambdaHandler) {
19
+ return function (request, body, response) {
20
+ return lambdaHandler((0, mappers_1.mapToLambdaEvent)(request, body))
21
+ .then(function (lambda) {
22
+ var _a, _b, _c, _d, _e, _f;
23
+ return (0, responses_1.writeResponse)(response, lambda.statusCode, lambda.body, (_c = (_b = (_a = lambda.headers) === null || _a === void 0 ? void 0 : _a['Content-Type']) === null || _b === void 0 ? void 0 : _b.toString()) !== null && _c !== void 0 ? _c : undefined, (_f = (_e = (_d = lambda.headers) === null || _d === void 0 ? void 0 : _d['Location']) === null || _e === void 0 ? void 0 : _e.toString()) !== null && _f !== void 0 ? _f : undefined);
24
+ })
25
+ .catch(function (e) {
26
+ _this.LOGGER.error(e, 'request failed to execute');
27
+ (0, responses_1.internalServerError)(response, e.body);
28
+ });
29
+ };
30
+ };
31
+ this.server = new http_server_1.HttpServer(name, settings, this.handler(handler));
32
+ this.LOGGER = logging_1.LoggerFactory.create("HTTP->LAMBDA[".concat(this.name, "]"));
33
+ }
34
+ return LambdaHttpProxy;
35
+ }());
@@ -0,0 +1,10 @@
1
+ import { StartedNetwork } from "testcontainers";
2
+ import { AwsConfig, Config } from "./config";
3
+ import { Stoppable } from "./services";
4
+ export declare class LocalStack implements Stoppable {
5
+ private readonly _start;
6
+ private started;
7
+ constructor(config: Config, network: StartedNetwork);
8
+ start: () => Promise<AwsConfig>;
9
+ stop: () => Promise<void>;
10
+ }
@@ -0,0 +1,93 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.LocalStack = void 0;
40
+ var logging_1 = require("@yopdev/logging");
41
+ var testcontainers_1 = require("testcontainers");
42
+ var LOGGER = logging_1.LoggerFactory.create('LOCALSTACK');
43
+ var NETWORK_ALIAS = 'localstack';
44
+ var PROTOCOL = 'http';
45
+ var DEFAULT_DOCKER_IMAGE = 'localstack/localstack:stable';
46
+ var LocalStack = /** @class */ (function () {
47
+ function LocalStack(config, network) {
48
+ var _this = this;
49
+ this.start = function () { return __awaiter(_this, void 0, void 0, function () {
50
+ return __generator(this, function (_a) {
51
+ return [2 /*return*/, this._start()
52
+ .then(function (endpoint) { return ({
53
+ region: 'us-east-1',
54
+ endpoint: endpoint,
55
+ credentials: {
56
+ accessKeyId: 'dummy',
57
+ secretAccessKey: 'dummy'
58
+ }
59
+ }); })];
60
+ });
61
+ }); };
62
+ this.stop = function () { return Promise.resolve(_this.started)
63
+ .then(function (container) { return container ? container.stop().then(function () { return 'stopped'; }) : 'not started'; })
64
+ .then(function (status) { return LOGGER.info(status); }); };
65
+ var container = new testcontainers_1.GenericContainer(config.localStackDockerImage || DEFAULT_DOCKER_IMAGE);
66
+ var localStatePath = config.localStateBindMount;
67
+ var withLocalState = localStatePath !== undefined ?
68
+ container
69
+ .withEnvironment({ PERSISTENCE: '1' })
70
+ .withBindMounts([{
71
+ source: localStatePath,
72
+ target: '/var/lib/localstack',
73
+ mode: 'rw',
74
+ }])
75
+ : container;
76
+ var ready = withLocalState
77
+ .withExposedPorts(config.useRandomPorts ?
78
+ config.servicesPort :
79
+ {
80
+ container: config.servicesPort,
81
+ host: config.servicesPort
82
+ })
83
+ .withNetwork(network)
84
+ .withNetworkAliases(NETWORK_ALIAS);
85
+ this._start = function () { return ready
86
+ .start()
87
+ .then(function (container) { return _this.started = container; })
88
+ .then(function (container) { return "".concat(PROTOCOL, "://").concat(container.getHost(), ":").concat(container.getMappedPort(config.servicesPort)); }); };
89
+ LOGGER.debug('initialized');
90
+ }
91
+ return LocalStack;
92
+ }());
93
+ exports.LocalStack = LocalStack;
@@ -0,0 +1,6 @@
1
+ /// <reference types="node" />
2
+ import { Message } from "@aws-sdk/client-sqs";
3
+ import { APIGatewayProxyEvent, SQSRecord } from "aws-lambda";
4
+ import { IncomingMessage } from "http";
5
+ export declare const mapToLambdaSqsRecord: (message: Message) => SQSRecord;
6
+ export declare function mapToLambdaEvent(req: IncomingMessage, requestBody: string): APIGatewayProxyEvent;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mapToLambdaEvent = exports.mapToLambdaSqsRecord = void 0;
4
+ var logging_1 = require("@yopdev/logging");
5
+ var url_1 = require("url");
6
+ var LOGGER = logging_1.LoggerFactory.create('MAPPERS');
7
+ var mapToLambdaSqsRecord = function (message) {
8
+ if (!message.Body)
9
+ throw new Error("message Body must be present: ".concat(message.Body));
10
+ return {
11
+ messageId: 'N/A',
12
+ receiptHandle: 'N/A',
13
+ body: message.Body,
14
+ attributes: {
15
+ ApproximateReceiveCount: 'N/A',
16
+ SentTimestamp: 'N/A',
17
+ SenderId: 'N/A',
18
+ ApproximateFirstReceiveTimestamp: 'N/A',
19
+ },
20
+ messageAttributes: {},
21
+ md5OfBody: 'N/A',
22
+ eventSource: 'N/A',
23
+ eventSourceARN: 'N/A',
24
+ awsRegion: 'N/A',
25
+ };
26
+ };
27
+ exports.mapToLambdaSqsRecord = mapToLambdaSqsRecord;
28
+ function mapToLambdaEvent(req, requestBody) {
29
+ if (!req.url || !req.method)
30
+ throw new Error('url and method are required');
31
+ var url = new url_1.URL(decodeURIComponent(req.url), "http://".concat(req.headers.host));
32
+ var qsp = {};
33
+ url.searchParams.forEach(function (v, k) { return (qsp[k] = v); });
34
+ var claims = extractClaims(req);
35
+ var headers = {};
36
+ if (req.headers['content-type'])
37
+ headers['Content-Type'] = req.headers['content-type'];
38
+ if (req.headers['accept'])
39
+ headers['Accept'] = req.headers['accept'];
40
+ return {
41
+ httpMethod: req.method,
42
+ body: requestBody,
43
+ headers: headers,
44
+ path: url.pathname,
45
+ pathParameters: null,
46
+ queryStringParameters: qsp,
47
+ resource: '',
48
+ multiValueHeaders: {},
49
+ isBase64Encoded: false,
50
+ multiValueQueryStringParameters: null,
51
+ stageVariables: null,
52
+ requestContext: {
53
+ accountId: '',
54
+ apiId: '',
55
+ authorizer: { claims: claims },
56
+ httpMethod: '',
57
+ identity: {
58
+ accessKey: '',
59
+ accountId: '',
60
+ apiKey: '',
61
+ apiKeyId: '',
62
+ caller: '',
63
+ clientCert: {
64
+ clientCertPem: '',
65
+ issuerDN: '',
66
+ serialNumber: '',
67
+ subjectDN: '',
68
+ validity: { notAfter: '', notBefore: '' },
69
+ },
70
+ cognitoAuthenticationProvider: '',
71
+ cognitoAuthenticationType: '',
72
+ cognitoIdentityId: '',
73
+ cognitoIdentityPoolId: '',
74
+ principalOrgId: '',
75
+ sourceIp: '',
76
+ user: '',
77
+ userAgent: '',
78
+ userArn: '',
79
+ },
80
+ path: '',
81
+ protocol: '',
82
+ requestId: '',
83
+ requestTimeEpoch: 1428582896000,
84
+ resourceId: '',
85
+ resourcePath: '',
86
+ stage: '',
87
+ },
88
+ };
89
+ }
90
+ exports.mapToLambdaEvent = mapToLambdaEvent;
91
+ function extractClaims(req) {
92
+ var _a;
93
+ var jwt = (_a = req.headers['authorization']) === null || _a === void 0 ? void 0 : _a.replace('Bearer ', '');
94
+ try {
95
+ return jwt ? JSON.parse(atob(jwt.split('.')[1])) : null;
96
+ }
97
+ catch (e) {
98
+ LOGGER.warn('Invalid token, claims could not be extracted: %O', jwt);
99
+ return undefined;
100
+ }
101
+ }
@@ -0,0 +1,11 @@
1
+ import { Lifecycle, Service, ServiceConfig } from './services';
2
+ export declare const newPreTrafficHooks: (name: string, hooks: () => Promise<void>[], service: ServiceConfig<PreTrafficHooks>) => Service<PreTrafficHooks>;
3
+ declare class PreTrafficHooks implements Lifecycle<PreTrafficHooks> {
4
+ readonly name: string;
5
+ private readonly hooks;
6
+ private LOGGER;
7
+ constructor(name: string, hooks: () => Promise<void>[]);
8
+ start: () => Promise<this>;
9
+ stop: () => Promise<void>;
10
+ }
11
+ export {};
@@ -0,0 +1,68 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.newPreTrafficHooks = void 0;
40
+ var logging_1 = require("@yopdev/logging");
41
+ var services_1 = require("./services");
42
+ var newPreTrafficHooks = function (name, hooks, service) { return new services_1.Service(new PreTrafficHooks(name, hooks), service); };
43
+ exports.newPreTrafficHooks = newPreTrafficHooks;
44
+ var PreTrafficHooks = /** @class */ (function () {
45
+ function PreTrafficHooks(name, hooks) {
46
+ var _this = this;
47
+ this.name = name;
48
+ this.hooks = hooks;
49
+ this.start = function () { return __awaiter(_this, void 0, void 0, function () {
50
+ var _this = this;
51
+ return __generator(this, function (_a) {
52
+ return [2 /*return*/, Promise
53
+ .all(this.hooks())
54
+ .then(function () { return _this.LOGGER.info('started'); })
55
+ .then(function () { return _this; })];
56
+ });
57
+ }); };
58
+ this.stop = function () { return __awaiter(_this, void 0, void 0, function () {
59
+ var _this = this;
60
+ return __generator(this, function (_a) {
61
+ return [2 /*return*/, Promise.resolve()
62
+ .then(function () { return _this.LOGGER.info('stopped'); })];
63
+ });
64
+ }); };
65
+ this.LOGGER = logging_1.LoggerFactory.create("PRETRAFFIC[".concat(name, "]"));
66
+ }
67
+ return PreTrafficHooks;
68
+ }());
@@ -0,0 +1,4 @@
1
+ /// <reference types="node" />
2
+ import { ServerResponse } from 'http';
3
+ export declare function internalServerError(res: ServerResponse, body: string): void;
4
+ export declare function writeResponse(res: ServerResponse, statusCode: number, body: string, contentType?: string, location?: string): void;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeResponse = exports.internalServerError = void 0;
4
+ function internalServerError(res, body) {
5
+ return writeResponse(res, 500, body);
6
+ }
7
+ exports.internalServerError = internalServerError;
8
+ function writeResponse(res, statusCode, body, contentType, location) {
9
+ res.setHeader('Access-Control-Allow-Origin', '*');
10
+ res.setHeader('Access-Control-Allow-Methods', '*');
11
+ res.setHeader('Access-Control-Allow-Headers', '*');
12
+ if (contentType)
13
+ res.setHeader('Content-Type', contentType);
14
+ if (location)
15
+ res.setHeader('Location', location);
16
+ res.statusCode = statusCode;
17
+ res.end(body);
18
+ }
19
+ exports.writeResponse = writeResponse;
@@ -0,0 +1,17 @@
1
+ /// <reference types="node" />
2
+ import { Lifecycle, Service, ServiceConfig } from './services';
3
+ export declare const newScheduledTasks: (name: string, schedules: Rate[], service: ServiceConfig<ScheduledTasks>) => Service<ScheduledTasks>;
4
+ declare class ScheduledTasks implements Lifecycle<ScheduledTasks> {
5
+ readonly name: string;
6
+ private readonly schedules;
7
+ private LOGGER;
8
+ constructor(name: string, schedules: Rate[]);
9
+ intervals: NodeJS.Timeout[];
10
+ start: () => Promise<this>;
11
+ stop: () => Promise<void>;
12
+ }
13
+ export type Rate = {
14
+ frequency: number;
15
+ task: () => Promise<unknown>;
16
+ };
17
+ export {};
@@ -0,0 +1,69 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.newScheduledTasks = void 0;
40
+ var logging_1 = require("@yopdev/logging");
41
+ var timers_1 = require("timers");
42
+ var services_1 = require("./services");
43
+ var newScheduledTasks = function (name, schedules, service) { return new services_1.Service(new ScheduledTasks(name, schedules), service); };
44
+ exports.newScheduledTasks = newScheduledTasks;
45
+ var ScheduledTasks = /** @class */ (function () {
46
+ function ScheduledTasks(name, schedules) {
47
+ var _this = this;
48
+ this.name = name;
49
+ this.schedules = schedules;
50
+ this.intervals = [];
51
+ this.start = function () { return __awaiter(_this, void 0, void 0, function () {
52
+ var _this = this;
53
+ return __generator(this, function (_a) {
54
+ return [2 /*return*/, Promise.resolve(this.schedules.forEach(function (schedule) { return _this.intervals.push(setInterval(schedule.task, schedule.frequency * 1000)); }))
55
+ .then(function () { return _this.LOGGER.info('started'); })
56
+ .then(function () { return _this; })];
57
+ });
58
+ }); };
59
+ this.stop = function () { return __awaiter(_this, void 0, void 0, function () {
60
+ var _this = this;
61
+ return __generator(this, function (_a) {
62
+ return [2 /*return*/, Promise.resolve(this.intervals.forEach(function (interval) { return (0, timers_1.clearInterval)(interval); }))
63
+ .then(function () { return _this.LOGGER.info('stopped'); })];
64
+ });
65
+ }); };
66
+ this.LOGGER = logging_1.LoggerFactory.create("SCHEDULER[".concat(name, "]"));
67
+ }
68
+ return ScheduledTasks;
69
+ }());
@@ -0,0 +1,24 @@
1
+ import { DevServerConfig } from "./config";
2
+ export interface Lifecycle<I> extends Stoppable {
3
+ name: string;
4
+ start: (config: DevServerConfig) => Promise<I>;
5
+ }
6
+ export interface Stoppable {
7
+ stop(): Promise<void>;
8
+ }
9
+ export interface Callbackable<I> {
10
+ callback?: ((instance: I) => Promise<void>);
11
+ }
12
+ export declare class Service<I> implements Lifecycle<I> {
13
+ private readonly config;
14
+ readonly name: string;
15
+ readonly start: (config: DevServerConfig) => Promise<I>;
16
+ readonly stop: () => Promise<void>;
17
+ private LOGGER;
18
+ constructor(service: Lifecycle<I>, config: ServiceConfig<I>);
19
+ private callback;
20
+ private dependsOnOrNothing;
21
+ }
22
+ export type ServiceConfig<I> = {
23
+ dependsOn?: Lifecycle<any>;
24
+ } & Callbackable<I>;
@@ -0,0 +1,75 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.Service = void 0;
40
+ var logging_1 = require("@yopdev/logging");
41
+ var Service = /** @class */ (function () {
42
+ function Service(service, config) {
43
+ var _this = this;
44
+ this.config = config;
45
+ this.callback = function (instance) { return __awaiter(_this, void 0, void 0, function () {
46
+ var _this = this;
47
+ return __generator(this, function (_a) {
48
+ return [2 /*return*/, (this.config.callback || (function () { return _this.LOGGER.debug('no callback', _this.name); }))(instance)];
49
+ });
50
+ }); };
51
+ this.dependsOnOrNothing = function () {
52
+ var _a;
53
+ return (_a = _this.config.dependsOn) !== null && _a !== void 0 ? _a : {
54
+ name: _this.name,
55
+ start: function () { return Promise.resolve(_this.LOGGER.trace('no start dependency for %s', _this.name)); },
56
+ stop: function () { return Promise.resolve(_this.LOGGER.trace('no stop dependency for %s', _this.name)); }
57
+ };
58
+ };
59
+ this.name = service.name;
60
+ this.LOGGER = logging_1.LoggerFactory.create("SERVICE[".concat(this.name, "]"));
61
+ this.start = function (config) { return _this.dependsOnOrNothing()
62
+ .start(config)
63
+ .then(function () { return service.start(config); })
64
+ .then(function (started) { return _this
65
+ .callback(started)
66
+ .then(function () { return _this.LOGGER.info('started'); })
67
+ .then(function () { return started; }); }); };
68
+ this.stop = function () { return service
69
+ .stop()
70
+ .then(function () { return _this.dependsOnOrNothing().stop(); })
71
+ .then(function () { return _this.LOGGER.info('stopped'); }); };
72
+ }
73
+ return Service;
74
+ }());
75
+ exports.Service = Service;
@@ -0,0 +1,26 @@
1
+ import { HttpSettings } from "./http-server";
2
+ import { IncomingMessage, ServerResponse } from "http";
3
+ import { Lifecycle, Service, ServiceConfig } from "./services";
4
+ import { DevServerConfig } from "./config";
5
+ export declare const newSnsHttpProxy: (name: string, config: {
6
+ settings: HttpSettings;
7
+ method: string;
8
+ subject: string | undefined;
9
+ }, service: ServiceConfig<string>) => Service<string>;
10
+ export declare class SnsHttpProxy implements Lifecycle<string> {
11
+ readonly name: string;
12
+ private readonly settings;
13
+ private readonly method;
14
+ private readonly subject?;
15
+ private LOGGER;
16
+ private server;
17
+ private config;
18
+ constructor(name: string, settings: HttpSettings, method: string, subject?: string);
19
+ start: (config: DevServerConfig) => Promise<string>;
20
+ stop: () => Promise<void>;
21
+ handler: (method: string, subject?: string) => (request: IncomingMessage, body: string, response: ServerResponse) => Promise<void>;
22
+ extractMessage: (method: string, request: IncomingMessage, body: string) => string;
23
+ private onlyWhenStarted;
24
+ private extractQueryString;
25
+ private extractMessageAttributes;
26
+ }
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.SnsHttpProxy = exports.newSnsHttpProxy = void 0;
15
+ var logging_1 = require("@yopdev/logging");
16
+ var http_server_1 = require("./http-server");
17
+ var responses_1 = require("./responses");
18
+ var services_1 = require("./services");
19
+ var assert_1 = require("./assert");
20
+ var newSnsHttpProxy = function (name, config, service) { return new services_1.Service(new SnsHttpProxy(name, config.settings, config.method, config.subject), service); };
21
+ exports.newSnsHttpProxy = newSnsHttpProxy;
22
+ var SnsHttpProxy = /** @class */ (function () {
23
+ function SnsHttpProxy(name, settings, method, subject) {
24
+ var _this = this;
25
+ this.name = name;
26
+ this.settings = settings;
27
+ this.method = method;
28
+ this.subject = subject;
29
+ this.start = function (config) { return Promise.resolve(_this.server)
30
+ .then(function (server) { return server.start(); })
31
+ .then(function (endpoint) {
32
+ _this.config = {
33
+ topic: config.topic.arn,
34
+ sns: config.sns
35
+ };
36
+ return endpoint;
37
+ })
38
+ .then(function (endpoint) { return endpoint; }); };
39
+ this.stop = function () { return _this.onlyWhenStarted(_this.server).stop()
40
+ .then(function () { return _this.LOGGER.info('stopped'); }); };
41
+ this.handler = function (method, subject) {
42
+ return function (request, body, response) {
43
+ return Promise.resolve(((0, assert_1.assertNotUndefined)(_this.config)))
44
+ .then(function (config) {
45
+ return config.sns
46
+ .publish({ arn: config.topic }, _this.extractMessage(method, request, body), subject, _this.extractMessageAttributes(request))
47
+ .then(function () { return (0, responses_1.writeResponse)(response, 200, ''); })
48
+ .catch(function (e) {
49
+ _this.LOGGER.error(e, 'request failed to execute');
50
+ (0, responses_1.internalServerError)(response, e.body);
51
+ });
52
+ });
53
+ };
54
+ };
55
+ this.extractMessage = function (method, request, body) {
56
+ switch (method) {
57
+ case 'GET':
58
+ return _this.extractQueryString(request) || '';
59
+ case 'POST':
60
+ return body;
61
+ default:
62
+ throw new Error();
63
+ }
64
+ };
65
+ this.onlyWhenStarted = function (server) { return (0, assert_1.assertNotUndefined)(server, 'not started'); };
66
+ this.extractQueryString = function (request) { var _a, _b; return (_a = request.url) === null || _a === void 0 ? void 0 : _a.substring(((_b = request.url) === null || _b === void 0 ? void 0 : _b.indexOf('?')) + 1); };
67
+ this.extractMessageAttributes = function (request) {
68
+ var initialValue = {};
69
+ return Object.keys(request.headers).reduce(function (obj, item) {
70
+ var _a;
71
+ return __assign(__assign({}, obj), (_a = {}, _a[item] = {
72
+ DataType: 'String',
73
+ StringValue: request.headers[item],
74
+ }, _a));
75
+ }, initialValue);
76
+ };
77
+ this.server = new http_server_1.HttpServer(this.name, this.settings, this.handler(this.method, this.subject));
78
+ this.LOGGER = logging_1.LoggerFactory.create("HTTP->SNS[".concat(name, "]"));
79
+ }
80
+ return SnsHttpProxy;
81
+ }());
82
+ exports.SnsHttpProxy = SnsHttpProxy;