1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | exports.EnvVarSync = exports.APIFileService = exports.APIKVService = exports.APIUtils = exports.APIResponse = exports.APIError = exports.APIAuthUtils = exports.APIConfig = exports.APIEndpoint = exports.APIParameter = exports.APILove = void 0;
|
7 | const express_1 = __importDefault(require("express"));
|
8 | const body_parser_1 = __importDefault(require("body-parser"));
|
9 | const cookie_parser_1 = __importDefault(require("cookie-parser"));
|
10 | const lodash_1 = require("lodash");
|
11 | const APIConfig_1 = require("./lib/APIConfig");
|
12 | Object.defineProperty(exports, "APIConfig", { enumerable: true, get: function () { return APIConfig_1.APIConfig; } });
|
13 | const path_1 = __importDefault(require("path"));
|
14 | const APIUtils_1 = require("./lib/APIUtils");
|
15 | Object.defineProperty(exports, "APIUtils", { enumerable: true, get: function () { return APIUtils_1.APIUtils; } });
|
16 | require("reflect-metadata");
|
17 | const APIResponse_1 = require("./lib/APIResponse");
|
18 | Object.defineProperty(exports, "APIResponse", { enumerable: true, get: function () { return APIResponse_1.APIResponse; } });
|
19 | const APIError_1 = require("./lib/APIError");
|
20 | Object.defineProperty(exports, "APIError", { enumerable: true, get: function () { return APIError_1.APIError; } });
|
21 | const KVService_1 = require("./lib/Services/KeyValue/KVService");
|
22 | Object.defineProperty(exports, "APIKVService", { enumerable: true, get: function () { return KVService_1.KVService; } });
|
23 | const FileService_1 = require("./lib/Services/File/FileService");
|
24 | Object.defineProperty(exports, "APIFileService", { enumerable: true, get: function () { return FileService_1.FileService; } });
|
25 | const Config_1 = require("./lib/Services/Config");
|
26 | Object.defineProperty(exports, "EnvVarSync", { enumerable: true, get: function () { return Config_1.EnvVarSync; } });
|
27 | const APIAuthUtils_1 = require("./lib/APIAuthUtils");
|
28 | Object.defineProperty(exports, "APIAuthUtils", { enumerable: true, get: function () { return APIAuthUtils_1.APIAuthUtils; } });
|
29 | function _createHandlerWrapperFunction(handlerData, thisObject) {
|
30 | return (req, res, next) => {
|
31 | let apiResponse = new APIResponse_1.APIResponse(req, res, next);
|
32 |
|
33 | if (handlerData.options.requireAuthentication) {
|
34 | if (!req.auth || !req.auth.isAuthenticated || req.auth.isExpired) {
|
35 | apiResponse.withError(APIError_1.APIError.create401UnauthorizedError());
|
36 | return;
|
37 | }
|
38 | }
|
39 | let handlerArgs = [];
|
40 | let validationErrors = [];
|
41 |
|
42 | for (let index = 0; index < handlerData.handlerParameterNames.length; index++) {
|
43 | let paramData = handlerData.handlerParameterData[index];
|
44 | let paramOptions = lodash_1.get(paramData, "paramOptions", {});
|
45 | let paramName = APIUtils_1.APIUtils.coalesce(paramOptions.rawName, handlerData.handlerParameterNames[index]);
|
46 |
|
47 | if ((index === handlerData.handlerParameterNames.length - 1 || index === handlerData.handlerParameterNames.length - 2) && ["req", "request", "res", "response"].indexOf(paramName.toLowerCase()) >= 0) {
|
48 | continue;
|
49 | }
|
50 | let paramSources = lodash_1.castArray(lodash_1.get(paramOptions, "sources", ["params", "query", "body", "cookie", "headers"]));
|
51 | let paramValue;
|
52 | if (req.auth && paramData.paramType === "APIAuthUser") {
|
53 | paramValue = APIAuthUtils_1.APIAuthUtils.getAPIAuthUserFromAuthCredentials(req.auth);
|
54 | }
|
55 | else {
|
56 | for (let paramSource of paramSources) {
|
57 | let paramValues = lodash_1.get(req, paramSource);
|
58 | if (lodash_1.isNil(paramValues)) {
|
59 | continue;
|
60 | }
|
61 | if (paramOptions.includeFullSource ||
|
62 | (/[\.\[\]]/g).test(paramSource)
|
63 | ) {
|
64 | paramValue = paramValues;
|
65 | break;
|
66 | }
|
67 | else {
|
68 | if (lodash_1.has(paramValues, paramName)) {
|
69 | paramValue = paramValues[paramName];
|
70 | break;
|
71 | }
|
72 | }
|
73 | }
|
74 | }
|
75 | let argValue = APIUtils_1.APIUtils.coalesce(paramValue, paramOptions.defaultValue);
|
76 | if (paramOptions.processor) {
|
77 | try {
|
78 | argValue = paramOptions.processor(argValue, req);
|
79 | }
|
80 | catch (error) {
|
81 | validationErrors.push({
|
82 | parameter: paramName,
|
83 | message: error.message || error.toString()
|
84 | });
|
85 | continue;
|
86 | }
|
87 | }
|
88 | if (lodash_1.isNil(argValue)) {
|
89 |
|
90 | if (!lodash_1.get(paramOptions, "optional", false)) {
|
91 | validationErrors.push({
|
92 | parameter: paramName,
|
93 | message: "missing"
|
94 | });
|
95 | }
|
96 | handlerArgs.push(undefined);
|
97 | continue;
|
98 | }
|
99 | argValue = APIUtils_1.APIUtils.convertToType(argValue, paramData.paramRawType);
|
100 | if (lodash_1.isNil(argValue) || lodash_1.isNaN(argValue)) {
|
101 | validationErrors.push({
|
102 | parameter: paramName,
|
103 | message: "invalid"
|
104 | });
|
105 | continue;
|
106 | }
|
107 | handlerArgs.push(argValue);
|
108 | }
|
109 | if (validationErrors.length > 0) {
|
110 | apiResponse.withError(APIError_1.APIError.createValidationError(validationErrors));
|
111 | return;
|
112 | }
|
113 | apiResponse.processHandlerFunction(thisObject, handlerData.handlerFunction, handlerArgs, handlerData.options.disableFriendlyResponse, handlerData.options.successResponse);
|
114 | };
|
115 | }
|
116 | function _loadAPI(apiRouter, apiDefinition) {
|
117 | let apiModule;
|
118 | try {
|
119 | apiModule = require(path_1.default.resolve(process.cwd(), apiDefinition.require));
|
120 | }
|
121 | catch (e) {
|
122 | console.error(e);
|
123 | return null;
|
124 | }
|
125 | if (lodash_1.isNil(apiModule)) {
|
126 | return null;
|
127 | }
|
128 | let moduleName = APIUtils_1.APIUtils.coalesce(apiDefinition.moduleName, path_1.default.basename(apiDefinition.require));
|
129 | let apiClass = APIUtils_1.APIUtils.coalesce(apiModule[moduleName], apiModule.default, apiModule);
|
130 | let apiInstance;
|
131 | lodash_1.each(lodash_1.get(apiClass, "__handlerData", {}), (handlerData, name) => {
|
132 |
|
133 | if (handlerData.isInstance && lodash_1.isNil(apiInstance)) {
|
134 | apiInstance = new apiClass();
|
135 | }
|
136 | let options = handlerData.options;
|
137 | let argsArray = [options.path];
|
138 | if (options.middleware) {
|
139 | argsArray = argsArray.concat(lodash_1.castArray(options.middleware));
|
140 | }
|
141 | let handlerWrapper = _createHandlerWrapperFunction(handlerData, handlerData.isInstance ? apiInstance : apiClass);
|
142 | argsArray.push(handlerWrapper);
|
143 | apiRouter[options.method.toLowerCase()].apply(apiRouter, argsArray);
|
144 | });
|
145 | }
|
146 | class APILove {
|
147 | static start(options) {
|
148 | if (options.loadStandardMiddleware !== false) {
|
149 | this.app.use(cookie_parser_1.default());
|
150 | this.app.use(body_parser_1.default.json({ limit: "50mb" }));
|
151 | this.app.use(body_parser_1.default.urlencoded({ limit: "50mb", extended: false, parameterLimit: 50000 }));
|
152 | this.app.use(body_parser_1.default.text({ limit: "50mb" }));
|
153 | this.app.use((req, res, next) => {
|
154 | req.auth = APIAuthUtils_1.APIAuthUtils.getAuthCredentialsFromRequest(req, true);
|
155 | next();
|
156 | });
|
157 | }
|
158 | for (let mw of lodash_1.get(options, "middleware", [])) {
|
159 | this.app.use(mw);
|
160 | }
|
161 |
|
162 | for (let api of lodash_1.get(options, "apis", [])) {
|
163 | if (lodash_1.isNil(api.apiPath)) {
|
164 | api.apiPath = "";
|
165 | }
|
166 | if (APIConfig_1.APIConfig.LAZY_LOAD_APIS) {
|
167 | let apiRouter;
|
168 | this.app.use(api.apiPath, (req, res, next) => {
|
169 |
|
170 | if (!apiRouter) {
|
171 | apiRouter = express_1.default.Router();
|
172 | _loadAPI(apiRouter, api);
|
173 | }
|
174 | apiRouter(req, res, next);
|
175 | });
|
176 | }
|
177 | else {
|
178 | let apiRouter = express_1.default.Router();
|
179 | _loadAPI(apiRouter, api);
|
180 | this.app.use(api.apiPath, apiRouter);
|
181 | }
|
182 | }
|
183 | if (!lodash_1.isNil(options.defaultRouteHandler)) {
|
184 | this.app.use(options.defaultRouteHandler);
|
185 | }
|
186 |
|
187 | if (!lodash_1.isNil(options.defaultErrorHandler)) {
|
188 | this.app.use(options.defaultErrorHandler);
|
189 | }
|
190 | else {
|
191 | this.app.use((error, req, res, next) => {
|
192 | if (error instanceof APIError_1.APIError) {
|
193 | let apiError = error;
|
194 | res.status(apiError.statusCode).send(APIConfig_1.APIConfig.OUTPUT_HAPI_RESULTS ? apiError.hapiOut() : apiError.out());
|
195 | }
|
196 | else {
|
197 | let apiResponse = new APIResponse_1.APIResponse(res, res);
|
198 | apiResponse.withError(error);
|
199 | }
|
200 | });
|
201 | }
|
202 | if (APIConfig_1.APIConfig.RUN_AS_SERVER) {
|
203 | this.app.listen(APIConfig_1.APIConfig.WEB_PORT, () => console.log(`API listening on port ${APIConfig_1.APIConfig.WEB_PORT}`));
|
204 | return this.app;
|
205 | }
|
206 | else {
|
207 | let serverless = require("serverless-http");
|
208 | return serverless(this.app, { callbackWaitsForEmptyEventLoop: !!options.callbackWaitsForEmptyEventLoop });
|
209 | }
|
210 | }
|
211 | }
|
212 | exports.APILove = APILove;
|
213 | APILove.app = express_1.default();
|
214 | function APIParameter(options) {
|
215 | return function (target, key, parameterIndex) {
|
216 | let isInstance = lodash_1.isNil(target.prototype);
|
217 | let theClass = isInstance ? target.constructor : target.prototype.constructor;
|
218 | let handlerData = lodash_1.get(theClass, `__handlerData.${key}`, {});
|
219 | lodash_1.set(handlerData, `handlerParameterData.${parameterIndex}.paramOptions`, options);
|
220 | lodash_1.set(theClass, `__handlerData.${key}`, handlerData);
|
221 | };
|
222 | }
|
223 | exports.APIParameter = APIParameter;
|
224 | function APIEndpoint(options) {
|
225 | return function (target, key, descriptor) {
|
226 | let isInstance = lodash_1.isNil(target.prototype);
|
227 | let theClass = isInstance ? target.constructor : target.prototype.constructor;
|
228 | let handlerData = lodash_1.get(theClass, `__handlerData.${key}`, {});
|
229 | options = lodash_1.defaultsDeep({}, options, {
|
230 | method: "get",
|
231 | path: "/"
|
232 | });
|
233 | let parameterMetadata = Reflect.getMetadata("design:paramtypes", target, key);
|
234 | let parameterNames = APIUtils_1.APIUtils.getFunctionParamNames(descriptor.value);
|
235 | handlerData.isInstance = isInstance;
|
236 | handlerData.handlerFunction = descriptor.value;
|
237 | handlerData.options = options;
|
238 | handlerData.handlerParameterNames = parameterNames;
|
239 | for (let parameterIndex = 0; parameterIndex < parameterNames.length; parameterIndex++) {
|
240 | lodash_1.set(handlerData, `handlerParameterData.${parameterIndex}.paramRawType`, APIUtils_1.APIUtils.getRawTypeName(parameterMetadata[parameterIndex].prototype));
|
241 | lodash_1.set(handlerData, `handlerParameterData.${parameterIndex}.paramType`, parameterMetadata[parameterIndex].name);
|
242 | lodash_1.set(handlerData, `handlerParameterData.${parameterIndex}.paramName`, parameterNames[parameterIndex]);
|
243 | }
|
244 | lodash_1.set(theClass, `__handlerData.${key}`, handlerData);
|
245 | };
|
246 | }
|
247 | exports.APIEndpoint = APIEndpoint;
|
248 |
|
\ | No newline at end of file |