Comparing version 0.1.4 to 0.1.5
@@ -64,2 +64,7 @@ import { RemoteCall, EventRecord } from "../core/types"; | ||
} | ||
export interface LambdaScheduleEvent { | ||
type: string; | ||
action: string; | ||
[prop: string]: string; | ||
} | ||
export interface LambdaApiEvent { | ||
@@ -121,3 +126,3 @@ resource: string; | ||
} | ||
export declare type LambdaEvent = LambdaCall & LambdaApiEvent & LambdaS3Event & LambdaDynamoEvent; | ||
export declare type LambdaEvent = LambdaCall & LambdaApiEvent & LambdaS3Event & LambdaDynamoEvent & LambdaScheduleEvent; | ||
export interface LambdaHandler { | ||
@@ -133,3 +138,4 @@ (event: LambdaEvent, context: LambdaContext, callback: LambdaCallback): boolean | void; | ||
private s3(event, context); | ||
private schedule(event, context); | ||
private dynamo(event, context); | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -28,156 +20,174 @@ const container_1 = require("../core/container"); | ||
} | ||
handler(event, context) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
logger_1.LogLevel.set(this.config().logLevel); | ||
this.log.debug("Lambda Event: %j", event); | ||
this.log.debug("Lambda Context: %j", context); | ||
if (event.httpMethod) { | ||
try { | ||
let res = yield this.rest(event, context); | ||
return container_1.HttpResponse.result(res); | ||
} | ||
catch (err) { | ||
this.log.error(err); | ||
return container_1.HttpResponse.error(err); | ||
} | ||
async handler(event, context) { | ||
logger_1.LogLevel.set(this.config.logLevel); | ||
this.log.debug("Lambda Event: %j", event); | ||
this.log.debug("Lambda Context: %j", context); | ||
if (event.httpMethod) { | ||
try { | ||
let res = await this.rest(event, context); | ||
return container_1.HttpResponse.result(res); | ||
} | ||
else if ((event.type === "remote" || event.type === "internal") && event.service && event.method) { | ||
try { | ||
return yield this.remote(event, context); | ||
} | ||
catch (err) { | ||
this.log.error(err); | ||
throw errors_1.InternalServerError.wrap(err); | ||
} | ||
catch (err) { | ||
this.log.error(err); | ||
return container_1.HttpResponse.error(err); | ||
} | ||
else if (event.Records && event.Records[0] && event.Records[0].eventSource === "aws:s3") { | ||
try { | ||
return yield this.s3(event, context); | ||
} | ||
catch (err) { | ||
this.log.error(err); | ||
throw errors_1.InternalServerError.wrap(err); | ||
} | ||
} | ||
else if ((event.type === "remote" || event.type === "internal") && event.service && event.method) { | ||
try { | ||
return await this.remote(event, context); | ||
} | ||
else if (event.Records && event.Records[0] && event.Records[0].eventSource === "aws:dynamodb") { | ||
try { | ||
return yield this.dynamo(event, context); | ||
} | ||
catch (err) { | ||
this.log.error(err); | ||
throw errors_1.InternalServerError.wrap(err); | ||
} | ||
catch (err) { | ||
this.log.error(err); | ||
throw errors_1.InternalServerError.wrap(err); | ||
} | ||
else { | ||
throw new errors_1.BadRequest("Invalid event"); | ||
} | ||
else if (event.type === "schedule" && event.action) { | ||
try { | ||
return await this.schedule(event, context); | ||
} | ||
}); | ||
} | ||
rest(event, context) { | ||
const _super = name => super[name]; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let restCall = { | ||
type: "rest", | ||
requestId: context && context.awsRequestId || utils_1.Utils.uuid(), | ||
sourceIp: (event.requestContext | ||
&& event.requestContext.identity | ||
&& event.requestContext.identity.sourceIp) || "255.255.255.255", | ||
application: undefined, | ||
service: undefined, | ||
method: undefined, | ||
httpMethod: event.httpMethod, | ||
resource: event.resource, | ||
path: event.path, | ||
pathParameters: event.pathParameters || {}, | ||
queryStringParameters: event.queryStringParameters || {}, | ||
headers: utils_1.RestUtils.canonicalHeaders(event.headers || {}), | ||
body: event.body, | ||
isBase64Encoded: event.isBase64Encoded || false | ||
}; | ||
return _super("restCall").call(this, restCall); | ||
}); | ||
} | ||
remote(event, context) { | ||
const _super = name => super[name]; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
event.requestId = context && context.awsRequestId || utils_1.Utils.uuid(); | ||
return _super("remoteCall").call(this, event); | ||
}); | ||
} | ||
s3(event, context) { | ||
const _super = name => super[name]; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.log.info("S3 Event: %j", event); | ||
let requestId = context && context.awsRequestId || utils_1.Utils.uuid(); | ||
let time = new Date().toISOString(); | ||
let calls = {}; | ||
for (let record of event.Records) { | ||
let resource = record.s3.bucket.name; | ||
let object = record.s3.object.key; | ||
let action = record.eventName; | ||
let group = `${resource}/${action}@${object}`; | ||
if (!calls[group]) | ||
calls[group] = { | ||
type: "event", | ||
source: "aws:s3", | ||
application: undefined, | ||
service: undefined, | ||
method: undefined, | ||
requestId, | ||
resource, | ||
action, | ||
time, | ||
object, | ||
records: [] | ||
}; | ||
calls[group].records.push(record); | ||
catch (err) { | ||
this.log.error(err); | ||
throw errors_1.InternalServerError.wrap(err); | ||
} | ||
// TODO: Iteration of all, combine result | ||
let result; | ||
for (let key in calls) { | ||
let call = calls[key]; | ||
this.log.info("S3 Call [%s:%s]: %j", call.resource, call.object, call); | ||
result = yield _super("eventCall").call(this, call); | ||
} | ||
else if (event.Records && event.Records[0] && event.Records[0].eventSource === "aws:s3") { | ||
try { | ||
return await this.s3(event, context); | ||
} | ||
return result; | ||
}); | ||
} | ||
dynamo(event, context) { | ||
const _super = name => super[name]; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.log.info("Dynamo Event: %j", event); | ||
let requestId = context && context.awsRequestId || utils_1.Utils.uuid(); | ||
let time = new Date().toISOString(); | ||
let calls = {}; | ||
for (let record of event.Records) { | ||
let resource = record.eventSourceARN.split("/")[1]; | ||
let object = resource; | ||
let action = record.eventName; | ||
let group = `${resource}/${action}@${object}`; | ||
if (!calls[group]) | ||
calls[group] = { | ||
type: "event", | ||
source: "aws:dynamodb", | ||
application: undefined, | ||
service: undefined, | ||
method: undefined, | ||
requestId, | ||
resource, | ||
action, | ||
time, | ||
object, | ||
records: [] | ||
}; | ||
calls[group].records.push(record); | ||
catch (err) { | ||
this.log.error(err); | ||
throw errors_1.InternalServerError.wrap(err); | ||
} | ||
// TODO: Iteration of all, combine result | ||
let result; | ||
for (let key in calls) { | ||
let call = calls[key]; | ||
this.log.info("Dynamo Call [%s]: %j", call.resource, call); | ||
result = yield _super("eventCall").call(this, call); | ||
} | ||
else if (event.Records && event.Records[0] && event.Records[0].eventSource === "aws:dynamodb") { | ||
try { | ||
return await this.dynamo(event, context); | ||
} | ||
return result; | ||
}); | ||
catch (err) { | ||
this.log.error(err); | ||
throw errors_1.InternalServerError.wrap(err); | ||
} | ||
} | ||
else { | ||
throw new errors_1.BadRequest("Invalid event"); | ||
} | ||
} | ||
async rest(event, context) { | ||
let restCall = { | ||
type: "rest", | ||
requestId: context && context.awsRequestId || utils_1.Utils.uuid(), | ||
sourceIp: (event.requestContext | ||
&& event.requestContext.identity | ||
&& event.requestContext.identity.sourceIp) || "255.255.255.255", | ||
application: undefined, | ||
service: undefined, | ||
method: undefined, | ||
httpMethod: event.httpMethod, | ||
resource: event.resource, | ||
path: event.path, | ||
pathParameters: event.pathParameters || {}, | ||
queryStringParameters: event.queryStringParameters || {}, | ||
headers: utils_1.RestUtils.canonicalHeaders(event.headers || {}), | ||
body: event.body, | ||
isBase64Encoded: event.isBase64Encoded || false | ||
}; | ||
return super.restCall(restCall); | ||
} | ||
async remote(event, context) { | ||
event.requestId = context && context.awsRequestId || utils_1.Utils.uuid(); | ||
return super.remoteCall(event); | ||
} | ||
async s3(event, context) { | ||
this.log.info("S3 Event: %j", event); | ||
let requestId = context && context.awsRequestId || utils_1.Utils.uuid(); | ||
let time = new Date().toISOString(); | ||
let calls = {}; | ||
for (let record of event.Records) { | ||
let resource = record.s3.bucket.name; | ||
let object = record.s3.object.key; | ||
let action = record.eventName; | ||
let group = `${resource}/${action}@${object}`; | ||
if (!calls[group]) | ||
calls[group] = { | ||
type: "event", | ||
source: "aws:s3", | ||
application: undefined, | ||
service: undefined, | ||
method: undefined, | ||
requestId, | ||
resource, | ||
action, | ||
time, | ||
object, | ||
records: [] | ||
}; | ||
calls[group].records.push(record); | ||
} | ||
// TODO: Iteration of all, combine result | ||
let result; | ||
for (let key in calls) { | ||
let call = calls[key]; | ||
this.log.info("S3 Call [%s:%s]: %j", call.resource, call.object, call); | ||
result = await super.eventCall(call); | ||
} | ||
return result; | ||
} | ||
async schedule(event, context) { | ||
this.log.info("Schedule Event: %j", event); | ||
let requestId = context && context.awsRequestId || utils_1.Utils.uuid(); | ||
let time = new Date().toISOString(); | ||
let call = { | ||
type: "event", | ||
source: "aws:cloudwatch", | ||
application: undefined, | ||
service: undefined, | ||
method: undefined, | ||
requestId, | ||
resource: "events", | ||
action: event.action, | ||
time, | ||
object: null, | ||
records: [ | ||
event | ||
] | ||
}; | ||
this.log.info("Schedule Call [%s:%s]: %j", call.resource, call.object, call); | ||
let result = await super.eventCall(call); | ||
return result; | ||
} | ||
async dynamo(event, context) { | ||
this.log.info("Dynamo Event: %j", event); | ||
let requestId = context && context.awsRequestId || utils_1.Utils.uuid(); | ||
let time = new Date().toISOString(); | ||
let calls = {}; | ||
for (let record of event.Records) { | ||
let resource = record.eventSourceARN.split("/")[1]; | ||
let object = resource; | ||
let action = record.eventName; | ||
let group = `${resource}/${action}@${object}`; | ||
if (!calls[group]) | ||
calls[group] = { | ||
type: "event", | ||
source: "aws:dynamodb", | ||
application: undefined, | ||
service: undefined, | ||
method: undefined, | ||
requestId, | ||
resource, | ||
action, | ||
time, | ||
object, | ||
records: [] | ||
}; | ||
calls[group].records.push(record); | ||
} | ||
// TODO: Iteration of all, combine result | ||
let result; | ||
for (let key in calls) { | ||
let call = calls[key]; | ||
this.log.info("Dynamo Call [%s]: %j", call.resource, call); | ||
result = await super.eventCall(call); | ||
} | ||
return result; | ||
} | ||
} | ||
@@ -184,0 +194,0 @@ exports.LambdaContainer = LambdaContainer; |
@@ -7,1 +7,2 @@ import { EventAdapter } from "../core/types"; | ||
export declare function DynamoDbRemove(database: string, adapter?: EventAdapter): (type: any, propertyKey: string, descriptor: PropertyDescriptor) => void; | ||
export declare function Schedule(action: string, adapter?: EventAdapter): (type: any, propertyKey: string, descriptor: PropertyDescriptor) => void; |
@@ -24,3 +24,7 @@ "use strict"; | ||
exports.DynamoDbRemove = DynamoDbRemove; | ||
function Schedule(action, adapter) { | ||
return decorators_1.Event("aws:cloudwatch", "events", action, null, adapter, decorators_1.Internal); | ||
} | ||
exports.Schedule = Schedule; | ||
//# sourceMappingURL=events.js.map |
export { LambdaContainer, LambdaCall, LambdaApiEvent, LambdaS3Event, LambdaDynamoEvent, LambdaEventRecord, LambdaS3Record, LambdaDynamoRecord, LambdaContext, LambdaCallback, LambdaHandler } from "./container"; | ||
export { LambdaError } from "./error"; | ||
export { LambdaProxy } from "./proxy"; | ||
export { S3ObjectCreated, DynamoDbInsert, DynamoDbModify, DynamoDbRemove } from "./events"; | ||
export { S3ObjectCreated, DynamoDbInsert, DynamoDbModify, DynamoDbRemove, Schedule } from "./events"; |
@@ -14,3 +14,4 @@ "use strict"; | ||
exports.DynamoDbRemove = events_1.DynamoDbRemove; | ||
exports.Schedule = events_1.Schedule; | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -21,39 +13,35 @@ const metadata_1 = require("../core/metadata"); | ||
} | ||
token(call) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.security.issueToken({ | ||
audience: call.application, | ||
subject: call.type, | ||
userId: null, | ||
role: "Application" | ||
}); | ||
async token(call) { | ||
return await this.security.issueToken({ | ||
audience: call.application, | ||
subject: call.type, | ||
userId: null, | ||
role: "Application" | ||
}); | ||
} | ||
invoke(call) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let stage = call.type === "remote" | ||
? this.config.remoteStage(call.application) | ||
: this.config.stage; | ||
let fun = metadata_1.ProxyMetadata.functionName(this); | ||
let response; | ||
try { | ||
response = yield this.lambda.invoke({ | ||
FunctionName: stage + "-" + fun, | ||
Payload: JSON.stringify(call) | ||
}).promise(); | ||
} | ||
catch (err) { | ||
throw errors_1.InternalServerError.wrap(err); | ||
} | ||
let result = JSON.parse(response.Payload.toString()); | ||
if (response.FunctionError === "Handled") { | ||
throw error_1.LambdaError.parse(result.errorMessage); | ||
} | ||
else if (response.FunctionError === "Unhandled") { | ||
throw errors_1.InternalServerError.wrap(result.errorMessage); | ||
} | ||
else { | ||
return result; | ||
} | ||
}); | ||
async invoke(call) { | ||
let stage = call.type === "remote" | ||
? this.config.remoteStage(call.application) | ||
: this.config.stage; | ||
let fun = metadata_1.ProxyMetadata.functionName(this); | ||
let response; | ||
try { | ||
response = await this.lambda.invoke({ | ||
FunctionName: stage + "-" + fun, | ||
Payload: JSON.stringify(call) | ||
}).promise(); | ||
} | ||
catch (err) { | ||
throw errors_1.InternalServerError.wrap(err); | ||
} | ||
let result = JSON.parse(response.Payload.toString()); | ||
if (response.FunctionError === "Handled") { | ||
throw error_1.LambdaError.parse(result.errorMessage); | ||
} | ||
else if (response.FunctionError === "Unhandled") { | ||
throw errors_1.InternalServerError.wrap(result.errorMessage); | ||
} | ||
else { | ||
return result; | ||
} | ||
} | ||
@@ -60,0 +48,0 @@ } |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -22,33 +14,31 @@ require("../env"); | ||
} | ||
proxy(method, params) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let startTime = this.log.time(); | ||
try { | ||
let type = "remote"; | ||
let appId = metadata_1.ProxyMetadata.application(this) || this.config.appId; | ||
if (this.config.appId === appId) | ||
type = "internal"; | ||
let call = { | ||
type, | ||
application: appId, | ||
service: metadata_1.ProxyMetadata.service(this), | ||
method: method.name, | ||
requestId: undefined, | ||
token: undefined, | ||
args: [] | ||
}; | ||
for (let i = 0; i < params.length; i++) { | ||
call.args[i] = params[i]; | ||
} | ||
call.token = yield this.token(call); | ||
let response = yield this.invoke(call); | ||
return response; | ||
async proxy(method, params) { | ||
let startTime = this.log.time(); | ||
try { | ||
let type = "remote"; | ||
let appId = metadata_1.ProxyMetadata.application(this) || this.config.appId; | ||
if (this.config.appId === appId) | ||
type = "internal"; | ||
let call = { | ||
type, | ||
application: appId, | ||
service: metadata_1.ProxyMetadata.service(this), | ||
method: method.name, | ||
requestId: undefined, | ||
token: undefined, | ||
args: [] | ||
}; | ||
for (let i = 0; i < params.length; i++) { | ||
call.args[i] = params[i]; | ||
} | ||
catch (e) { | ||
throw e; | ||
} | ||
finally { | ||
this.log.timeEnd(startTime, `${method.name}`); | ||
} | ||
}); | ||
call.token = await this.token(call); | ||
let response = await this.invoke(call); | ||
return response; | ||
} | ||
catch (e) { | ||
throw e; | ||
} | ||
finally { | ||
this.log.timeEnd(startTime, `${method.name}`); | ||
} | ||
} | ||
@@ -55,0 +45,0 @@ } |
@@ -11,10 +11,2 @@ "use strict"; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -33,52 +25,16 @@ require("../env"); | ||
} | ||
restAuth(call, permission) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let token = call.headers && (call.headers["Authorization"] || call.headers["authorization"]); | ||
if (!permission.roles.Public && !token) | ||
throw new errors_1.Unauthorized("Missing authorization token"); | ||
if (permission.roles.Public) { | ||
if (token) | ||
this.log.debug("Ignore token on public permission"); | ||
let ctx = { | ||
requestId: call.requestId, | ||
token, | ||
permission, | ||
auth: { | ||
tokenId: call.requestId, | ||
subject: "user:public", | ||
issuer: this.config.appId, | ||
audience: this.config.appId, | ||
remote: false, | ||
userId: null, | ||
role: "Public", | ||
issued: new Date(), | ||
expires: new Date(Date.now() + 60000) | ||
} | ||
}; | ||
return ctx; | ||
} | ||
return yield this.verify(call.requestId, token, permission); | ||
}); | ||
} | ||
remoteAuth(call, permission) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!permission.roles.Remote && !permission.roles.Internal) | ||
throw new errors_1.Forbidden(`Remote calls not allowed for method [${permission.method}]`); | ||
let ctx = yield this.verify(call.requestId, call.token, permission); | ||
if (ctx.auth.remote && !permission.roles.Remote) | ||
throw new errors_1.Unauthorized(`Internal call allowed only for method [${permission.method}]`); | ||
return ctx; | ||
}); | ||
} | ||
eventAuth(call, permission) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!permission.roles.Internal) | ||
throw new errors_1.Forbidden(`Internal events not allowed for method [${permission.method}]`); | ||
async restAuth(call, permission) { | ||
let token = call.headers && (call.headers["Authorization"] || call.headers["authorization"]); | ||
if (!permission.roles.Public && !token) | ||
throw new errors_1.Unauthorized("Missing authorization token"); | ||
if (permission.roles.Public) { | ||
if (token) | ||
this.log.debug("Ignore token on public permission"); | ||
let ctx = { | ||
requestId: call.requestId, | ||
token: null, | ||
token, | ||
permission, | ||
auth: { | ||
tokenId: call.requestId, | ||
subject: "event", | ||
subject: "user:public", | ||
issuer: this.config.appId, | ||
@@ -88,3 +44,3 @@ audience: this.config.appId, | ||
userId: null, | ||
role: "Internal", | ||
role: "Public", | ||
issued: new Date(), | ||
@@ -95,4 +51,34 @@ expires: new Date(Date.now() + 60000) | ||
return ctx; | ||
}); | ||
} | ||
return await this.verify(call.requestId, token, permission); | ||
} | ||
async remoteAuth(call, permission) { | ||
if (!permission.roles.Remote && !permission.roles.Internal) | ||
throw new errors_1.Forbidden(`Remote calls not allowed for method [${permission.method}]`); | ||
let ctx = await this.verify(call.requestId, call.token, permission); | ||
if (ctx.auth.remote && !permission.roles.Remote) | ||
throw new errors_1.Unauthorized(`Internal call allowed only for method [${permission.method}]`); | ||
return ctx; | ||
} | ||
async eventAuth(call, permission) { | ||
if (!permission.roles.Internal) | ||
throw new errors_1.Forbidden(`Internal events not allowed for method [${permission.method}]`); | ||
let ctx = { | ||
requestId: call.requestId, | ||
token: null, | ||
permission, | ||
auth: { | ||
tokenId: call.requestId, | ||
subject: "event", | ||
issuer: this.config.appId, | ||
audience: this.config.appId, | ||
remote: false, | ||
userId: null, | ||
role: "Internal", | ||
issued: new Date(), | ||
expires: new Date(Date.now() + 60000) | ||
} | ||
}; | ||
return ctx; | ||
} | ||
issueToken(req) { | ||
@@ -121,43 +107,41 @@ req.tokenId = req.tokenId || utils_1.Utils.uuid(); | ||
} | ||
verify(requestId, token, permission) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let decoded, secret; | ||
try { | ||
if (token && token.startsWith("Bearer")) | ||
token = token.substring(6).trim(); | ||
decoded = JWT.decode(token); | ||
secret = decoded && this.secret(decoded.sub, decoded.iss, decoded.aud) || "NULL"; | ||
decoded = JWT.verify(token, secret); | ||
async verify(requestId, token, permission) { | ||
let decoded, secret; | ||
try { | ||
if (token && token.startsWith("Bearer")) | ||
token = token.substring(6).trim(); | ||
decoded = JWT.decode(token); | ||
secret = decoded && this.secret(decoded.sub, decoded.iss, decoded.aud) || "NULL"; | ||
decoded = JWT.verify(token, secret); | ||
} | ||
catch (e) { | ||
this.log.error("Token [%s]: %j", secret, decoded); | ||
this.log.error(e); | ||
if (e.message === "jwt expired") | ||
throw new errors_1.Unauthorized(`Token: expired [${Date.now()}] > [${decoded.exp * 1000}]`); | ||
throw new errors_1.BadRequest("Token: " + e.message, e); | ||
} | ||
if (decoded.role !== "Application" && permission.roles[decoded.role] !== true) | ||
throw new errors_1.Unauthorized(`Role [${decoded.role}] not authorized to access method [${permission.method}]`); | ||
let ctx = { | ||
requestId, | ||
token, | ||
permission, | ||
auth: { | ||
tokenId: decoded.jti, | ||
subject: decoded.sub, | ||
issuer: decoded.iss, | ||
audience: decoded.aud, | ||
remote: decoded.iss !== decoded.aud, | ||
userId: decoded.oid, | ||
role: decoded.role, | ||
scope: decoded.scope, | ||
email: decoded.email, | ||
name: decoded.name, | ||
ipAddress: decoded.ipaddr, | ||
issued: new Date(decoded.iat * 1000), | ||
expires: new Date(decoded.exp * 1000) | ||
} | ||
catch (e) { | ||
this.log.error("Token [%s]: %j", secret, decoded); | ||
this.log.error(e); | ||
if (e.message === "jwt expired") | ||
throw new errors_1.Unauthorized(`Token: expired [${Date.now()}] > [${decoded.exp * 1000}]`); | ||
throw new errors_1.BadRequest("Token: " + e.message, e); | ||
} | ||
if (decoded.role !== "Application" && permission.roles[decoded.role] !== true) | ||
throw new errors_1.Unauthorized(`Role [${decoded.role}] not authorized to access method [${permission.method}]`); | ||
let ctx = { | ||
requestId, | ||
token, | ||
permission, | ||
auth: { | ||
tokenId: decoded.jti, | ||
subject: decoded.sub, | ||
issuer: decoded.iss, | ||
audience: decoded.aud, | ||
remote: decoded.iss !== decoded.aud, | ||
userId: decoded.oid, | ||
role: decoded.role, | ||
scope: decoded.scope, | ||
email: decoded.email, | ||
name: decoded.name, | ||
ipAddress: decoded.ipaddr, | ||
issued: new Date(decoded.iat * 1000), | ||
expires: new Date(decoded.exp * 1000) | ||
} | ||
}; | ||
return ctx; | ||
}); | ||
}; | ||
return ctx; | ||
} | ||
@@ -164,0 +148,0 @@ secret(subject, issuer, audience) { |
@@ -27,2 +27,4 @@ import "../env"; | ||
export interface Container { | ||
state: ContainerState; | ||
metadata: ContainerMetadata; | ||
register(resource: Object, name?: string): this; | ||
@@ -34,5 +36,3 @@ register(service: Service): this; | ||
publish(service: Service): this; | ||
state(): ContainerState; | ||
prepare(): Container; | ||
metadata(): ContainerMetadata; | ||
restCall(call: RestCall): Promise<RestResult>; | ||
@@ -39,0 +39,0 @@ remoteCall(call: RemoteCall): Promise<any>; |
import "../env"; | ||
import { Context, RestCall, RestResult, RemoteCall, EventCall, EventResult } from "../types"; | ||
import { ContainerMetadata } from "../metadata"; | ||
import { Service, Proxy } from "../decorators"; | ||
import { Configuration, Security } from "../base"; | ||
import { Logger } from "../logger"; | ||
import { Container, ContainerState, ObjectType } from "./common"; | ||
export declare class ContainerInstance implements Container { | ||
private _application; | ||
private _name; | ||
protected log: Logger; | ||
protected config: Configuration; | ||
protected security: Security; | ||
private _state; | ||
private _resources; | ||
private _services; | ||
private _proxies; | ||
private _metadata; | ||
private _remoteHandlers; | ||
private _restHandlers; | ||
private _eventHandlers; | ||
private application; | ||
private name; | ||
private log; | ||
private config; | ||
private security; | ||
private istate; | ||
private imetadata; | ||
private resources; | ||
private services; | ||
private proxies; | ||
private remoteHandlers; | ||
private restHandlers; | ||
private eventHandlers; | ||
constructor(application: string, name: string, index?: string); | ||
state(): ContainerState; | ||
metadata(): ContainerMetadata; | ||
readonly state: ContainerState; | ||
readonly metadata: any; | ||
get<T>(type: ObjectType<T> | string): T; | ||
@@ -26,0 +23,0 @@ register(resource: Object, name?: string): this; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -21,15 +13,15 @@ require("../env"); | ||
constructor(application, name, index) { | ||
this._application = application; | ||
this._name = name || ContainerInstance.name; | ||
this.application = application; | ||
this.name = name || ContainerInstance.name; | ||
if (index !== undefined) | ||
this._name += ":" + index; | ||
this.log = logger_1.Logger.get(this._application, this._name); | ||
this._state = common_1.ContainerState.Pending; | ||
this._resources = {}; | ||
this._services = {}; | ||
this._proxies = {}; | ||
this._remoteHandlers = {}; | ||
this._restHandlers = {}; | ||
this._eventHandlers = {}; | ||
this._metadata = { | ||
this.name += ":" + index; | ||
this.log = logger_1.Logger.get(this.application, this.name); | ||
this.istate = common_1.ContainerState.Pending; | ||
this.resources = {}; | ||
this.services = {}; | ||
this.proxies = {}; | ||
this.remoteHandlers = {}; | ||
this.restHandlers = {}; | ||
this.eventHandlers = {}; | ||
this.imetadata = { | ||
permissions: {}, | ||
@@ -41,7 +33,7 @@ restMetadata: {}, | ||
} | ||
state() { | ||
return this._state; | ||
get state() { | ||
return this.istate; | ||
} | ||
metadata() { | ||
return this._metadata; | ||
get metadata() { | ||
return this.metadata; | ||
} | ||
@@ -54,11 +46,11 @@ get(type) { | ||
if (typeof type === "string") | ||
return this._services[type] || this._proxies[type] || this._resources[type]; | ||
return this.services[type] || this.proxies[type] || this.resources[type]; | ||
if (metadata_1.ServiceMetadata.has(type)) | ||
return this._services[metadata_1.ServiceMetadata.service(type)]; | ||
return this.services[metadata_1.ServiceMetadata.service(type)]; | ||
if (metadata_1.ProxyMetadata.has(type)) | ||
return this._proxies[metadata_1.ProxyMetadata.service(type)]; | ||
return this.proxies[metadata_1.ProxyMetadata.service(type)]; | ||
return null; | ||
} | ||
register(target, ...args) { | ||
if (this._state !== common_1.ContainerState.Pending) | ||
if (this.istate !== common_1.ContainerState.Pending) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
@@ -84,3 +76,3 @@ let name = undefined; | ||
name = metadata_1.ProxyMetadata.service(target); | ||
id = metadata_1.ProxyMetadata.id(target, this._application); | ||
id = metadata_1.ProxyMetadata.id(target, this.application); | ||
} | ||
@@ -90,3 +82,3 @@ else { | ||
} | ||
if (this._services[id] || this._proxies[id] || this._resources[id]) | ||
if (this.services[id] || this.proxies[id] || this.resources[id]) | ||
throw new errors_1.InternalServerError(`Duplicate registration [${id}]`); | ||
@@ -98,3 +90,3 @@ if (name === base_1.Configuration) { | ||
if (target instanceof base_1.BaseConfiguration) { | ||
target.init(this._application); | ||
target.init(this.application); | ||
} | ||
@@ -108,11 +100,11 @@ } | ||
if (metadata_1.ServiceMetadata.has(target)) { | ||
this._services[id] = target; | ||
this.services[id] = target; | ||
this.log.info("Service: %s", id); | ||
} | ||
else if (metadata_1.ProxyMetadata.has(target)) { | ||
this._proxies[id] = target; | ||
this.proxies[id] = target; | ||
this.log.info("Proxy: %s", id); | ||
} | ||
else { | ||
this._resources[id] = target; | ||
this.resources[id] = target; | ||
this.log.info("Resource: %s", id); | ||
@@ -123,3 +115,3 @@ } | ||
publish(service, ...args) { | ||
if (this._state !== common_1.ContainerState.Pending) | ||
if (this.istate !== common_1.ContainerState.Pending) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
@@ -140,3 +132,3 @@ // Call constructor | ||
let key = meta.service + "." + method; | ||
this._metadata.permissions[key] = meta; | ||
this.imetadata.permissions[key] = meta; | ||
}); | ||
@@ -148,6 +140,6 @@ let remoteMetadata = metadata_1.ServiceMetadata.remoteMetadata(service); | ||
let key = meta.service + "." + name; | ||
if (this._metadata.remoteMetadata[key]) | ||
if (this.imetadata.remoteMetadata[key]) | ||
throw new errors_1.InternalServerError(`Duplicate service method [${key}]`); | ||
this._metadata.remoteMetadata[key] = meta; | ||
this._remoteHandlers[key] = this.remoteHandler(service, meta); | ||
this.imetadata.remoteMetadata[key] = meta; | ||
this.remoteHandlers[key] = this.remoteHandler(service, meta); | ||
}); | ||
@@ -159,7 +151,7 @@ let restMetadata = metadata_1.ServiceMetadata.restMetadata(service); | ||
let meta = restMetadata[route]; | ||
if (this._metadata.restMetadata[route]) | ||
if (this.imetadata.restMetadata[route]) | ||
throw new errors_1.InternalServerError(`Duplicate REST route [${route}]`); | ||
this._metadata.restMetadata[route] = meta; | ||
this.imetadata.restMetadata[route] = meta; | ||
let bindings = bindMetadata[meta.method]; | ||
this._restHandlers[route] = this.restHandler(service, meta, bindings); | ||
this.restHandlers[route] = this.restHandler(service, meta, bindings); | ||
}); | ||
@@ -170,7 +162,7 @@ let eventMetadata = metadata_1.ServiceMetadata.eventMetadata(service); | ||
let metas = eventMetadata[event]; | ||
this._metadata.eventMetadata[event] = this._metadata.eventMetadata[event] || []; | ||
this._metadata.eventMetadata[event] = this._metadata.eventMetadata[event].concat(metas); | ||
this.imetadata.eventMetadata[event] = this.imetadata.eventMetadata[event] || []; | ||
this.imetadata.eventMetadata[event] = this.imetadata.eventMetadata[event].concat(metas); | ||
let handlers = metas.map(m => this.eventHandler(service, m)); | ||
this._eventHandlers[event] = this._eventHandlers[event] || []; | ||
this._eventHandlers[event] = this._eventHandlers[event].concat(handlers); | ||
this.eventHandlers[event] = this.eventHandlers[event] || []; | ||
this.eventHandlers[event] = this.eventHandlers[event].concat(handlers); | ||
}); | ||
@@ -180,3 +172,3 @@ return this; | ||
remoteHandler(service, metadata) { | ||
let fun = (ctx, call) => __awaiter(this, void 0, void 0, function* () { | ||
let fun = async (ctx, call) => { | ||
let log = service.log || this.log; | ||
@@ -186,3 +178,3 @@ let startTime = log.time(); | ||
let method = service[metadata.method]; | ||
let result = yield method.apply(service, call.args); | ||
let result = await method.apply(service, call.args); | ||
return result; | ||
@@ -196,7 +188,7 @@ } | ||
} | ||
}); | ||
}; | ||
return fun; | ||
} | ||
restHandler(service, metadata, bindings) { | ||
let fun = (ctx, call) => __awaiter(this, void 0, void 0, function* () { | ||
let fun = async (ctx, call) => { | ||
let log = service.log || this.log; | ||
@@ -208,3 +200,3 @@ let startTime = log.time(); | ||
if (metadata.adapter) { | ||
result = yield metadata.adapter(method.bind(service), ctx, call, call.pathParameters || {}, call.queryStringParameters || {}); | ||
result = await metadata.adapter(method.bind(service), ctx, call, call.pathParameters || {}, call.queryStringParameters || {}); | ||
} | ||
@@ -216,6 +208,6 @@ else if (bindings && bindings.argBindings) { | ||
} | ||
result = yield method.apply(service, args); | ||
result = await method.apply(service, args); | ||
} | ||
else { | ||
result = yield method.apply(service); | ||
result = await method.apply(service); | ||
} | ||
@@ -231,7 +223,7 @@ let contentType = bindings && bindings.contentType || "application/json"; | ||
} | ||
}); | ||
}; | ||
return fun; | ||
} | ||
eventHandler(service, metadata) { | ||
let handler = (ctx, call) => __awaiter(this, void 0, void 0, function* () { | ||
let handler = async (ctx, call) => { | ||
let log = service.log || this.log; | ||
@@ -243,6 +235,6 @@ let startTime = log.time(); | ||
if (metadata.adapter) { | ||
result = yield metadata.adapter(method.bind(service), ctx, call); | ||
result = await metadata.adapter(method.bind(service), ctx, call); | ||
} | ||
else { | ||
result = yield method.call(service, ctx, call); | ||
result = await method.call(service, ctx, call); | ||
} | ||
@@ -257,7 +249,7 @@ return result; | ||
} | ||
}); | ||
}; | ||
return handler; | ||
} | ||
prepare() { | ||
if (this._state !== common_1.ContainerState.Pending) | ||
if (this.istate !== common_1.ContainerState.Pending) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
@@ -272,8 +264,8 @@ if (!this.config) { | ||
} | ||
for (let sid in this._services) { | ||
let service = this._services[sid]; | ||
for (let sid in this.services) { | ||
let service = this.services[sid]; | ||
this.inject(service); | ||
} | ||
for (let pid in this._proxies) { | ||
let proxy = this._proxies[pid]; | ||
for (let pid in this.proxies) { | ||
let proxy = this.proxies[pid]; | ||
if (proxy instanceof base_1.BaseProxy) { | ||
@@ -284,3 +276,3 @@ proxy.initialize(this.config, this.security); | ||
} | ||
this._state = common_1.ContainerState.Ready; | ||
this.istate = common_1.ContainerState.Ready; | ||
return this; | ||
@@ -293,4 +285,4 @@ } | ||
let localId = dep.resource; | ||
let proxyId = (dep.application || this._application) + ":" + localId; | ||
let resolved = this._proxies[proxyId] || this._services[localId] || this._resources[localId]; | ||
let proxyId = (dep.application || this.application) + ":" + localId; | ||
let resolved = this.proxies[proxyId] || this.services[localId] || this.resources[localId]; | ||
let depId = (dep.application ? dep.application + ":" : "") + localId; | ||
@@ -304,206 +296,196 @@ if (!resolved) | ||
// -------------------------------------------------- | ||
remoteCall(call) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
this._state = common_1.ContainerState.Reserved; | ||
try { | ||
this.log.debug("Remote Call: %j", call); | ||
if (call.application !== this._application) { | ||
throw this.log.error(new errors_1.NotFound(`Application not found [${call.application}]`)); | ||
} | ||
let service = this._services[call.service]; | ||
if (!service) | ||
throw this.log.error(new errors_1.NotFound(`Service not found [${call.service}]`)); | ||
let permissionId = call.service + "." + call.method; | ||
let permission = permissionId && this._metadata.permissions[permissionId]; | ||
if (permission == null) | ||
throw this.log.error(new errors_1.Forbidden(`Undefined permission for method [${permissionId}]`)); | ||
let caller = this._remoteHandlers[permissionId]; | ||
if (!caller) | ||
throw this.log.error(new errors_1.NotFound(`Method not found [${permissionId}]`)); | ||
this._state = common_1.ContainerState.Busy; | ||
let ctx = yield this.security.remoteAuth(call, permission); | ||
// let ctx = await this.security.localAuth(); | ||
try { | ||
yield this.activate(ctx); | ||
let result = yield caller(ctx, call); | ||
return result; | ||
} | ||
catch (e) { | ||
throw this.log.error(e); | ||
} | ||
finally { | ||
yield this.release(ctx); | ||
} | ||
async remoteCall(call) { | ||
if (this.istate !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
this.istate = common_1.ContainerState.Reserved; | ||
try { | ||
this.log.debug("Remote Call: %j", call); | ||
if (call.application !== this.application) { | ||
throw this.log.error(new errors_1.NotFound(`Application not found [${call.application}]`)); | ||
} | ||
finally { | ||
this._state = common_1.ContainerState.Ready; | ||
} | ||
}); | ||
} | ||
eventCall(call) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
this._state = common_1.ContainerState.Reserved; | ||
let service = this.services[call.service]; | ||
if (!service) | ||
throw this.log.error(new errors_1.NotFound(`Service not found [${call.service}]`)); | ||
let permissionId = call.service + "." + call.method; | ||
let permission = permissionId && this.imetadata.permissions[permissionId]; | ||
if (permission == null) | ||
throw this.log.error(new errors_1.Forbidden(`Undefined permission for method [${permissionId}]`)); | ||
let caller = this.remoteHandlers[permissionId]; | ||
if (!caller) | ||
throw this.log.error(new errors_1.NotFound(`Method not found [${permissionId}]`)); | ||
this.istate = common_1.ContainerState.Busy; | ||
let ctx = await this.security.remoteAuth(call, permission); | ||
// let ctx = await this.security.localAuth(); | ||
try { | ||
call.type = "event"; | ||
this.log.debug("Event Call: %j", call); | ||
let key = `${call.source} ${call.resource}`; | ||
let alias = this.config.resources && this.config.resources[call.resource]; | ||
let metas = this._metadata.eventMetadata[key]; | ||
let handlers = this._eventHandlers && this._eventHandlers[key]; | ||
if (!handlers && alias) { | ||
let key2 = `${call.source} ${alias}`; | ||
metas = this._metadata.eventMetadata[key2]; | ||
handlers = this._eventHandlers && this._eventHandlers[key2]; | ||
} | ||
if (!handlers) | ||
throw this.log.error(new errors_1.NotFound(`Event handler not found [${key}] [${call.object}]`)); | ||
let result = { | ||
status: null, | ||
source: call.source, | ||
action: call.action, | ||
resource: call.resource, | ||
object: call.object, | ||
returns: [] | ||
}; | ||
this._state = common_1.ContainerState.Busy; | ||
for (let i = 0; i < handlers.length; i++) { | ||
let handler = handlers[i]; | ||
let target = metas[i]; | ||
if (!utils_2.Utils.wildcardMatch(target.actionFilter, call.action) || !utils_2.Utils.wildcardMatch(target.objectFilter, call.object)) | ||
continue; | ||
call.application = this._application; | ||
call.service = target.service; | ||
call.method = target.method; | ||
let permissionId = call.service + "." + call.method; | ||
let permission = permissionId && this._metadata.permissions[permissionId]; | ||
if (permission == null) | ||
throw this.log.error(new errors_1.Forbidden(`Undefined permission for method [${permissionId}]`)); | ||
let ctx = yield this.security.eventAuth(call, permission); | ||
try { | ||
yield this.activate(ctx); | ||
for (let record of call.records) { | ||
call.record = record; | ||
let data = yield handler(ctx, call); | ||
result.status = result.status || "OK"; | ||
result.returns.push({ | ||
service: target.service, | ||
method: target.method, | ||
error: null, | ||
data | ||
}); | ||
} | ||
} | ||
catch (e) { | ||
this.log.error(e); | ||
result.status = "FAILED"; | ||
result.returns.push({ | ||
service: target.service, | ||
method: target.method, | ||
error: errors_1.InternalServerError.wrap(e), | ||
data: null | ||
}); | ||
} | ||
finally { | ||
yield this.release(ctx); | ||
} | ||
} | ||
result.status = result.status || "NOP"; | ||
await this.activate(ctx); | ||
let result = await caller(ctx, call); | ||
return result; | ||
} | ||
catch (e) { | ||
throw this.log.error(e); | ||
} | ||
finally { | ||
this._state = common_1.ContainerState.Ready; | ||
await this.release(ctx); | ||
} | ||
}); | ||
} | ||
finally { | ||
this.istate = common_1.ContainerState.Ready; | ||
} | ||
} | ||
restCall(call) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
this._state = common_1.ContainerState.Reserved; | ||
try { | ||
call.type = "rest"; | ||
this.log.debug("REST Event: %j", call); | ||
call.contentType = utils_1.RestUtils.contentType(call.headers, call.body); | ||
let key = `${call.httpMethod} ${call.resource}`; | ||
if (call.contentType.domainModel) | ||
key += `:${call.contentType.domainModel}`; | ||
let rester = this._restHandlers && this._restHandlers[key]; | ||
if (!rester) | ||
throw this.log.error(new errors_1.NotFound(`Route not found [${key}]`)); | ||
let target = this._metadata.restMetadata[key]; | ||
call.application = this._application; | ||
async eventCall(call) { | ||
if (this.istate !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
this.istate = common_1.ContainerState.Reserved; | ||
try { | ||
call.type = "event"; | ||
this.log.debug("Event Call: %j", call); | ||
let key = `${call.source} ${call.resource}`; | ||
let alias = this.config.resources && this.config.resources[call.resource]; | ||
let metas = this.imetadata.eventMetadata[key]; | ||
let handlers = this.eventHandlers && this.eventHandlers[key]; | ||
if (!handlers && alias) { | ||
let key2 = `${call.source} ${alias}`; | ||
metas = this.imetadata.eventMetadata[key2]; | ||
handlers = this.eventHandlers && this.eventHandlers[key2]; | ||
} | ||
if (!handlers) | ||
throw this.log.error(new errors_1.NotFound(`Event handler not found [${key}] [${call.object}]`)); | ||
let result = { | ||
status: null, | ||
source: call.source, | ||
action: call.action, | ||
resource: call.resource, | ||
object: call.object, | ||
returns: [] | ||
}; | ||
this.istate = common_1.ContainerState.Busy; | ||
for (let i = 0; i < handlers.length; i++) { | ||
let handler = handlers[i]; | ||
let target = metas[i]; | ||
if (!utils_2.Utils.wildcardMatch(target.actionFilter, call.action) || !utils_2.Utils.wildcardMatch(target.objectFilter, call.object)) | ||
continue; | ||
call.application = this.application; | ||
call.service = target.service; | ||
call.method = target.method; | ||
let permissionId = call.service + "." + call.method; | ||
let permission = permissionId && this._metadata.permissions[permissionId]; | ||
let permission = permissionId && this.imetadata.permissions[permissionId]; | ||
if (permission == null) | ||
throw this.log.error(new errors_1.Forbidden(`Undefined permission for method [${permissionId}]`)); | ||
this._state = common_1.ContainerState.Busy; | ||
let ctx = yield this.security.restAuth(call, permission); | ||
let ctx = await this.security.eventAuth(call, permission); | ||
try { | ||
yield this.activate(ctx); | ||
utils_1.RestUtils.body(call); | ||
this.log.debug("REST Context: %j", ctx); | ||
this.log.debug("REST Call: %j", call); | ||
let result = yield rester(ctx, call); | ||
if (result[2] === "RAW") { | ||
return result[1]; | ||
await this.activate(ctx); | ||
for (let record of call.records) { | ||
call.record = record; | ||
let data = await handler(ctx, call); | ||
result.status = result.status || "OK"; | ||
result.returns.push({ | ||
service: target.service, | ||
method: target.method, | ||
error: null, | ||
data | ||
}); | ||
} | ||
else { | ||
let resp = { statusCode: result[0], body: result[1], contentType: result[2] }; | ||
this.log.debug("Response: %j", resp); | ||
return resp; | ||
} | ||
} | ||
catch (e) { | ||
this.log.error(e); | ||
throw errors_1.InternalServerError.wrap(e); | ||
result.status = "FAILED"; | ||
result.returns.push({ | ||
service: target.service, | ||
method: target.method, | ||
error: errors_1.InternalServerError.wrap(e), | ||
data: null | ||
}); | ||
} | ||
finally { | ||
yield this.release(ctx); | ||
await this.release(ctx); | ||
} | ||
} | ||
finally { | ||
this._state = common_1.ContainerState.Ready; | ||
} | ||
}); | ||
result.status = result.status || "NOP"; | ||
return result; | ||
} | ||
finally { | ||
this.istate = common_1.ContainerState.Ready; | ||
} | ||
} | ||
activate(ctx) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
for (let sid in this._services) { | ||
let service = this._services[sid]; | ||
try { | ||
if (service.activate) | ||
yield service.activate(ctx); | ||
async restCall(call) { | ||
if (this.istate !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
this.istate = common_1.ContainerState.Reserved; | ||
try { | ||
call.type = "rest"; | ||
this.log.debug("REST Event: %j", call); | ||
call.contentType = utils_1.RestUtils.contentType(call.headers, call.body); | ||
let key = `${call.httpMethod} ${call.resource}`; | ||
if (call.contentType.domainModel) | ||
key += `:${call.contentType.domainModel}`; | ||
let rester = this.restHandlers && this.restHandlers[key]; | ||
if (!rester) | ||
throw this.log.error(new errors_1.NotFound(`Route not found [${key}]`)); | ||
let target = this.imetadata.restMetadata[key]; | ||
call.application = this.application; | ||
call.service = target.service; | ||
call.method = target.method; | ||
let permissionId = call.service + "." + call.method; | ||
let permission = permissionId && this.imetadata.permissions[permissionId]; | ||
if (permission == null) | ||
throw this.log.error(new errors_1.Forbidden(`Undefined permission for method [${permissionId}]`)); | ||
this.istate = common_1.ContainerState.Busy; | ||
let ctx = await this.security.restAuth(call, permission); | ||
try { | ||
await this.activate(ctx); | ||
utils_1.RestUtils.body(call); | ||
this.log.debug("REST Context: %j", ctx); | ||
this.log.debug("REST Call: %j", call); | ||
let result = await rester(ctx, call); | ||
if (result[2] === "RAW") { // TODO: Verbatim response ... | ||
return result[1]; | ||
} | ||
catch (e) { | ||
this.log.error("Failed to activate service: [%s]", sid); | ||
this.log.error(e); | ||
throw e; | ||
// TODO: Error state for container | ||
else { | ||
let resp = { statusCode: result[0], body: result[1], contentType: result[2] }; | ||
this.log.debug("Response: %j", resp); | ||
return resp; | ||
} | ||
} | ||
return ctx; | ||
}); | ||
catch (e) { | ||
this.log.error(e); | ||
throw errors_1.InternalServerError.wrap(e); | ||
} | ||
finally { | ||
await this.release(ctx); | ||
} | ||
} | ||
finally { | ||
this.istate = common_1.ContainerState.Ready; | ||
} | ||
} | ||
release(ctx) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
for (let sid in this._services) { | ||
let service = this._services[sid]; | ||
try { | ||
if (service.release) | ||
yield service.release(ctx); | ||
} | ||
catch (e) { | ||
this.log.error("Failed to release service: [%s]", sid); | ||
this.log.error(e); | ||
// TODO: Error state for container | ||
} | ||
async activate(ctx) { | ||
for (let sid in this.services) { | ||
let service = this.services[sid]; | ||
try { | ||
if (service.activate) | ||
await service.activate(ctx); | ||
} | ||
}); | ||
catch (e) { | ||
this.log.error("Failed to activate service: [%s]", sid); | ||
this.log.error(e); | ||
throw e; | ||
// TODO: Error state for container | ||
} | ||
} | ||
return ctx; | ||
} | ||
async release(ctx) { | ||
for (let sid in this.services) { | ||
let service = this.services[sid]; | ||
try { | ||
if (service.release) | ||
await service.release(ctx); | ||
} | ||
catch (e) { | ||
this.log.error("Failed to release service: [%s]", sid); | ||
this.log.error(e); | ||
// TODO: Error state for container | ||
} | ||
} | ||
} | ||
} | ||
@@ -510,0 +492,0 @@ exports.ContainerInstance = ContainerInstance; |
@@ -11,10 +11,14 @@ import "../env"; | ||
protected log: Logger; | ||
private _application; | ||
private _name; | ||
private _state; | ||
private _registers; | ||
private _publishes; | ||
private _head; | ||
private _pool; | ||
private application; | ||
private name; | ||
private cstate; | ||
private registers; | ||
private publishes; | ||
private head; | ||
private pool; | ||
constructor(application: string, name?: string); | ||
readonly state: ContainerState; | ||
readonly metadata: ContainerMetadata; | ||
readonly config: Configuration; | ||
readonly security: Security; | ||
register(resource: Object, name?: string): this; | ||
@@ -26,6 +30,2 @@ register(service: Service): this; | ||
publish(service: Service): this; | ||
state(): ContainerState; | ||
metadata(): ContainerMetadata; | ||
config(): Configuration; | ||
security(): Security; | ||
prepare(): ContainerInstance; | ||
@@ -32,0 +32,0 @@ dispose(): void; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -19,83 +11,77 @@ require("../env"); | ||
constructor(application, name) { | ||
this._application = application; | ||
this._name = name || ContainerPool.name; | ||
this.log = logger_1.Logger.get(application, this._name); | ||
this._state = common_1.ContainerState.Pending; | ||
this._registers = []; | ||
this._publishes = []; | ||
this._pool = []; | ||
this.application = application; | ||
this.name = name || ContainerPool.name; | ||
this.log = logger_1.Logger.get(application, this.name); | ||
this.cstate = common_1.ContainerState.Pending; | ||
this.registers = []; | ||
this.publishes = []; | ||
this.pool = []; | ||
} | ||
get state() { | ||
return this.cstate; | ||
} | ||
get metadata() { | ||
if (this.cstate !== common_1.ContainerState.Ready) | ||
return undefined; | ||
return this.head.metadata; | ||
} | ||
get config() { | ||
if (this.cstate !== common_1.ContainerState.Ready) | ||
return undefined; | ||
return this.head.get(base_1.Configuration); | ||
} | ||
get security() { | ||
if (this.cstate !== common_1.ContainerState.Ready) | ||
return undefined; | ||
return this.head.get(base_1.Security); | ||
} | ||
register(target, ...args) { | ||
if (this._state !== common_1.ContainerState.Pending) | ||
if (this.cstate !== common_1.ContainerState.Pending) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
this._registers.push({ target, args }); | ||
this.registers.push({ target, args }); | ||
return this; | ||
} | ||
publish(service, ...args) { | ||
if (this._state !== common_1.ContainerState.Pending) | ||
if (this.cstate !== common_1.ContainerState.Pending) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
this._publishes.push({ service, args }); | ||
this.publishes.push({ service, args }); | ||
return this; | ||
} | ||
state() { | ||
return this._state; | ||
} | ||
metadata() { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
return undefined; | ||
return this._head.metadata(); | ||
} | ||
config() { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
return undefined; | ||
return this._head.get(base_1.Configuration); | ||
} | ||
security() { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
return undefined; | ||
return this._head.get(base_1.Security); | ||
} | ||
prepare() { | ||
let instance = this._pool.find(x => x.state() === common_1.ContainerState.Ready); | ||
let instance = this.pool.find(x => x.state === common_1.ContainerState.Ready); | ||
if (!instance) { | ||
instance = new instance_1.ContainerInstance(this._application, this._pool.length.toString()); | ||
instance = new instance_1.ContainerInstance(this.application, this.pool.length.toString()); | ||
// TODO: Identity | ||
this._registers.forEach(u => instance.register(u.target, ...u.args)); | ||
this._publishes.forEach(p => instance.publish(p.service, ...p.args)); | ||
this.registers.forEach(u => instance.register(u.target, ...u.args)); | ||
this.publishes.forEach(p => instance.publish(p.service, ...p.args)); | ||
instance.prepare(); | ||
this._pool.push(instance); | ||
this._head = this._head || instance; | ||
this.pool.push(instance); | ||
this.head = this.head || instance; | ||
} | ||
if (this._state === common_1.ContainerState.Pending) | ||
this._state = common_1.ContainerState.Ready; | ||
if (this.cstate === common_1.ContainerState.Pending) | ||
this.cstate = common_1.ContainerState.Ready; | ||
return instance; | ||
} | ||
dispose() { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
if (this.cstate !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
this._pool = [this._head]; | ||
this.pool = [this.head]; | ||
} | ||
remoteCall(call) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
let instance = this.prepare(); | ||
return instance.remoteCall(call); | ||
}); | ||
async remoteCall(call) { | ||
if (this.cstate !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
let instance = this.prepare(); | ||
return instance.remoteCall(call); | ||
} | ||
eventCall(call) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
let instance = this.prepare(); | ||
return instance.eventCall(call); | ||
}); | ||
async eventCall(call) { | ||
if (this.cstate !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
let instance = this.prepare(); | ||
return instance.eventCall(call); | ||
} | ||
restCall(call) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this._state !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
let instance = this.prepare(); | ||
return instance.restCall(call); | ||
}); | ||
async restCall(call) { | ||
if (this.cstate !== common_1.ContainerState.Ready) | ||
throw new errors_1.InternalServerError("Invalid container state"); | ||
let instance = this.prepare(); | ||
return instance.restCall(call); | ||
} | ||
@@ -102,0 +88,0 @@ } |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
require("reflect-metadata"); | ||
if (Symbol["asyncIterator"] === undefined) | ||
(Symbol["asyncIterator"]) = Symbol.for("asyncIterator"); | ||
process.on("unhandledRejection", (e) => { | ||
@@ -5,0 +7,0 @@ console.log(e); |
@@ -13,5 +13,6 @@ import "../env"; | ||
export interface EventRecord { | ||
eventSource: string; | ||
eventVersion: string; | ||
eventName: string; | ||
eventSource?: string; | ||
eventVersion?: string; | ||
eventName?: string; | ||
[prop: string]: any; | ||
} | ||
@@ -18,0 +19,0 @@ export interface EventResult { |
import "../env"; | ||
export declare function getArgs(func: Function): string[]; | ||
export declare function getArgs(func: (...args: any[]) => any): string[]; | ||
export declare function uuid(): string; | ||
@@ -4,0 +4,0 @@ export declare function password(): string; |
@@ -54,10 +54,10 @@ "use strict"; | ||
exports.isBase64 = isBase64; | ||
const prefix = Buffer.from("1F8B", "hex"); | ||
const gzipPrefix = Buffer.from("1F8B", "hex"); | ||
function isGzip(buf) { | ||
// 1f 8b; | ||
if (typeof buf === "string") { | ||
return buf.startsWith(prefix.toString()); | ||
return buf.startsWith(gzipPrefix.toString()); | ||
} | ||
if (typeof buf === "object" && buf instanceof Buffer) { | ||
return (buf[0] === prefix[0] && buf[1] === prefix[1]); | ||
return (buf[0] === gzipPrefix[0] && buf[1] === gzipPrefix[1]); | ||
} | ||
@@ -75,4 +75,5 @@ return false; | ||
let parts = map.split(";").map(x => x.trim()).filter(x => x); | ||
for (let part of parts) { | ||
let key, value; | ||
for (const part of parts) { | ||
let key; | ||
let value; | ||
[key, value] = part.split("=").map(x => x.trim()).filter(x => x); | ||
@@ -79,0 +80,0 @@ res[prefix + key] = value; |
@@ -8,3 +8,3 @@ | ||
private server; | ||
private application; | ||
private app; | ||
private basePath; | ||
@@ -11,0 +11,0 @@ constructor(application: string, basePath?: string); |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -26,5 +18,5 @@ const container_1 = require("../core/container"); | ||
this.prepare(); | ||
this.application = express(); | ||
this.application.use(BodyParser.text({ type: ["*/json", "text/*"], defaultCharset: "utf-8" })); | ||
this.application.use((req, res, next) => { | ||
this.app = express(); | ||
this.app.use(BodyParser.text({ type: ["*/json", "text/*"], defaultCharset: "utf-8" })); | ||
this.app.use((req, res, next) => { | ||
res.header("access-control-allow-origin", "*"); | ||
@@ -37,3 +29,3 @@ res.header("access-control-allow-methods", "GET,PUT,POST,DELETE,PATCH"); | ||
let paths = []; | ||
let restMetadata = this.metadata().restMetadata; | ||
let restMetadata = this.metadata.restMetadata; | ||
for (let hd in restMetadata) { | ||
@@ -60,15 +52,15 @@ let target = restMetadata[hd]; | ||
case "GET": | ||
this.application.get(path, adapter); | ||
this.app.get(path, adapter); | ||
break; | ||
case "POST": | ||
this.application.post(path, adapter); | ||
this.app.post(path, adapter); | ||
break; | ||
case "PUT": | ||
this.application.put(path, adapter); | ||
this.app.put(path, adapter); | ||
break; | ||
case "PATCH": | ||
this.application.patch(path, adapter); | ||
this.app.patch(path, adapter); | ||
break; | ||
case "DELETE": | ||
this.application.delete(path, adapter); | ||
this.app.delete(path, adapter); | ||
break; | ||
@@ -78,3 +70,3 @@ default: throw new errors_1.InternalServerError(`Unsupported http method: ${httpMethod}`); | ||
} | ||
this.server = http_1.createServer(this.application); | ||
this.server = http_1.createServer(this.app); | ||
this.server.listen(port); | ||
@@ -86,48 +78,45 @@ this.log.info("Server initialized."); | ||
} | ||
handle(resource, req, res) { | ||
const _super = name => super[name]; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
logger_1.LogLevel.set(this.config().logLevel); | ||
this.log.info("%s: %s", req.method, req.url); | ||
if (Buffer.isBuffer(req.body)) | ||
req.body = req.body.toString("utf-8"); | ||
if (req.body instanceof Object) { | ||
if (Object.getOwnPropertyNames(req.body).length) | ||
req.body = JSON.stringify(req.body); | ||
else | ||
req.body = undefined; | ||
async handle(resource, req, res) { | ||
logger_1.LogLevel.set(this.config.logLevel); | ||
this.log.info("%s: %s", req.method, req.url); | ||
if (Buffer.isBuffer(req.body)) | ||
req.body = req.body.toString("utf-8"); | ||
if (req.body instanceof Object) { | ||
if (Object.getOwnPropertyNames(req.body).length) | ||
req.body = JSON.stringify(req.body); | ||
else | ||
req.body = undefined; | ||
} | ||
let call = { | ||
type: "rest", | ||
requestId: utils_1.Utils.uuid(), | ||
sourceIp: req.ip || "255.255.255.255", | ||
application: undefined, | ||
service: undefined, | ||
method: undefined, | ||
httpMethod: req.method, | ||
resource, | ||
path: req.path, | ||
pathParameters: req.params || {}, | ||
queryStringParameters: req.query || {}, | ||
headers: req.headers || {}, | ||
body: req.body, | ||
isBase64Encoded: false // TODO | ||
}; | ||
try { | ||
let result = await super.restCall(call); | ||
for (let header in result.headers) { | ||
res.setHeader(header, result.headers[header]); | ||
} | ||
let call = { | ||
type: "rest", | ||
requestId: utils_1.Utils.uuid(), | ||
sourceIp: req.ip || "255.255.255.255", | ||
application: undefined, | ||
service: undefined, | ||
method: undefined, | ||
httpMethod: req.method, | ||
resource, | ||
path: req.path, | ||
pathParameters: req.params || {}, | ||
queryStringParameters: req.query || {}, | ||
headers: req.headers || {}, | ||
body: req.body, | ||
isBase64Encoded: false // TODO | ||
}; | ||
try { | ||
let result = yield _super("restCall").call(this, call); | ||
for (let header in result.headers) { | ||
res.setHeader(header, result.headers[header]); | ||
} | ||
if (result.contentType) | ||
res.setHeader("content-type", result.contentType); | ||
res.status(result.statusCode).send(result.body); | ||
if (result.contentType) | ||
res.setHeader("content-type", result.contentType); | ||
res.status(result.statusCode).send(result.body); | ||
} | ||
catch (err) { | ||
let result = container_1.HttpResponse.error(err); | ||
for (let header in result.headers) { | ||
res.setHeader(header, result.headers[header]); | ||
} | ||
catch (err) { | ||
let result = container_1.HttpResponse.error(err); | ||
for (let header in result.headers) { | ||
res.setHeader(header, result.headers[header]); | ||
} | ||
res.status(result.statusCode).send(result.body); | ||
} | ||
}); | ||
res.status(result.statusCode).send(result.body); | ||
} | ||
} | ||
@@ -134,0 +123,0 @@ stop() { |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -15,35 +7,31 @@ const base_1 = require("../core/base"); | ||
class ExpressService extends base_1.BaseService { | ||
process(ctx, call) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let rsrc = call.resource; | ||
if (rsrc.indexOf("{") > 0) | ||
rsrc = rsrc.substring(0, rsrc.indexOf("{") - 1); | ||
call.path = call.path.substring(call.path.indexOf(rsrc)); | ||
for (let p in call.queryStringParameters) { | ||
call.queryStringParameters[p] = encodeURIComponent(call.queryStringParameters[p]); | ||
} | ||
let app = express(); | ||
// app.use(bodyParser.json()); | ||
// app.use(awsServerlessExpressMiddleware.eventContext()); | ||
this.setup(app, ctx, call); | ||
// TODO: Complete response | ||
return new Promise((resolve, reject) => { | ||
this.server = awsServerlessExpress.createServer(app); | ||
awsServerlessExpress.proxy(this.server, call, { | ||
succeed: (input) => resolve({ | ||
statusCode: input.statusCode, | ||
headers: input.headers, | ||
body: input.body | ||
}), | ||
fail: (err) => reject(err) | ||
}); | ||
async process(ctx, call) { | ||
let rsrc = call.resource; | ||
if (rsrc.indexOf("{") > 0) | ||
rsrc = rsrc.substring(0, rsrc.indexOf("{") - 1); | ||
call.path = call.path.substring(call.path.indexOf(rsrc)); | ||
for (let p in call.queryStringParameters) { | ||
call.queryStringParameters[p] = encodeURIComponent(call.queryStringParameters[p]); | ||
} | ||
let app = express(); | ||
// app.use(bodyParser.json()); | ||
// app.use(awsServerlessExpressMiddleware.eventContext()); | ||
this.setup(app, ctx, call); | ||
// TODO: Complete response | ||
return new Promise((resolve, reject) => { | ||
this.server = awsServerlessExpress.createServer(app); | ||
awsServerlessExpress.proxy(this.server, call, { | ||
succeed: (input) => resolve({ | ||
statusCode: input.statusCode, | ||
headers: input.headers, | ||
body: input.body | ||
}), | ||
fail: (err) => reject(err) | ||
}); | ||
}); | ||
} | ||
release() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this.server) | ||
this.server.close(); | ||
this.server = undefined; | ||
}); | ||
async release() { | ||
if (this.server) | ||
this.server.close(); | ||
this.server = undefined; | ||
} | ||
@@ -50,0 +38,0 @@ } |
{ | ||
"name": "tyx", | ||
"description": "TyX Core Framework, Serverless back-end in TypeScript for AWS Lambda", | ||
"version": "0.1.4", | ||
"version": "0.1.5", | ||
"private": false, | ||
@@ -25,18 +25,21 @@ "license": "MIT", | ||
], | ||
"scripts": { | ||
"package": "./node_modules/.bin/gulp package" | ||
}, | ||
"dependencies": { | ||
"aws-serverless-express": "^3.0.2", | ||
"aws-serverless-express": "^3.2.0", | ||
"body-parser": "^1.17.2", | ||
"express": "^4.15.3", | ||
"express": "^4.16.3", | ||
"jsonwebtoken": "^7.4.3", | ||
"reflect-metadata": "^0.1.10", | ||
"uuid": "^3.0.1" | ||
"reflect-metadata": "^0.1.12", | ||
"uuid": "^3.2.1" | ||
}, | ||
"devDependencies": { | ||
"@types/aws-serverless-express": "^2.1.0", | ||
"@types/body-parser": "^1.16.3", | ||
"@types/express": "^4.0.35", | ||
"@types/jsonwebtoken": "^7.2.3", | ||
"@types/node": "^7.0.33", | ||
"@types/body-parser": "^1.16.8", | ||
"@types/express": "^4.11.1", | ||
"@types/jsonwebtoken": "^7.2.6", | ||
"@types/node": "^7.0.61", | ||
"@types/uuid": "^2.0.30", | ||
"aws-sdk": "^2.67.0", | ||
"aws-sdk": "^2.224.1", | ||
"del": "^3.0.0", | ||
@@ -46,5 +49,5 @@ "gulp": "^3.9.1", | ||
"gulp-replace": "^0.6.1", | ||
"gulp-shell": "^0.6.3", | ||
"gulp-sourcemaps": "^2.6.1", | ||
"gulp-typescript": "^3.2.2", | ||
"gulp-shell": "^0.6.5", | ||
"gulp-sourcemaps": "^2.6.4", | ||
"gulp-typescript": "^3.2.4", | ||
"gulpclass": "^0.1.2", | ||
@@ -54,4 +57,4 @@ "serverless-s3-deploy": "^0.5.0", | ||
"ts-node": "^3.3.0", | ||
"typescript": "^2.5.2" | ||
"typescript": "^2.8.1" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
421449
3535
Updatedexpress@^4.16.3
Updatedreflect-metadata@^0.1.12
Updateduuid@^3.2.1