@medusajs/framework
Version:
252 lines • 14.5 kB
JavaScript
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _ApiLoader_instances, _a, _ApiLoader_app, _ApiLoader_sourceDirs, _ApiLoader_loadHttpResources, _ApiLoader_registerExpressHandler, _ApiLoader_assignRestrictedFields, _ApiLoader_createCorsOptions, _ApiLoader_applyCorsMiddleware, _ApiLoader_applyAuthMiddleware, _ApiLoader_applyBodyParserMiddleware, _ApiLoader_assignAdditionalDataValidator, _ApiLoader_applyStorePublishableKeyMiddleware;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApiLoader = void 0;
const reporter_1 = __importDefault(require("@medusajs/cli/dist/reporter"));
const cors_1 = __importDefault(require("cors"));
const utils_1 = require("@medusajs/utils");
const routes_loader_1 = require("./routes-loader");
const routes_finder_1 = require("./routes-finder");
const routes_sorter_1 = require("./routes-sorter");
const wrap_handler_1 = require("./utils/wrap-handler");
const middlewares_1 = require("./middlewares");
const error_handler_1 = require("./middlewares/error-handler");
const restricted_fields_1 = require("./utils/restricted-fields");
const middleware_file_loader_1 = require("./middleware-file-loader");
const bodyparser_1 = require("./middlewares/bodyparser");
const ensure_publishable_api_key_1 = require("./middlewares/ensure-publishable-api-key");
const config_1 = require("../config");
class ApiLoader {
constructor({ app, sourceDir, baseRestrictedFields = [], }) {
_ApiLoader_instances.add(this);
/**
* An express instance
* @private
*/
_ApiLoader_app.set(this, void 0);
/**
* Path from where to load the routes from
* @private
*/
_ApiLoader_sourceDirs.set(this, void 0);
__classPrivateFieldSet(this, _ApiLoader_app, app, "f");
__classPrivateFieldSet(this, _ApiLoader_sourceDirs, Array.isArray(sourceDir) ? sourceDir : [sourceDir], "f");
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_assignRestrictedFields).call(this, baseRestrictedFields ?? []);
}
async load() {
const { errorHandler: sourceErrorHandler, middlewares, routes, routesFinder, bodyParserConfigRoutes, additionalDataValidatorRoutes, } = await __classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_loadHttpResources).call(this);
/**
* Parse request body on all the requests and use the routes finder
* to pick the best matching config for the given route.
*/
const bodyParserRoutesFinder = new routes_finder_1.RoutesFinder(new routes_sorter_1.RoutesSorter(bodyParserConfigRoutes).sort([
"static",
"params",
"regex",
"wildcard",
"global",
]));
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_applyBodyParserMiddleware).call(this, "/", bodyParserRoutesFinder);
/**
* Use the routes finder to pick the additional data validator
* to be applied on the current request
*/
if (additionalDataValidatorRoutes.length) {
const additionalDataValidatorRoutesFinder = new routes_finder_1.RoutesFinder(new routes_sorter_1.RoutesSorter(additionalDataValidatorRoutes).sort([
"static",
"params",
"regex",
"wildcard",
"global",
]));
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_assignAdditionalDataValidator).call(this, "/", additionalDataValidatorRoutesFinder);
}
/**
* CORS and Auth setup for admin routes
*/
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_applyCorsMiddleware).call(this, routesFinder, "/admin", "shouldAppendAdminCors", __classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_createCorsOptions).call(this, config_1.configManager.config.projectConfig.http.adminCors));
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_applyAuthMiddleware).call(this, routesFinder, "/admin", "user", [
"bearer",
"session",
"api-key",
]);
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_applyCorsMiddleware).call(this, routesFinder, "/store", "shouldAppendStoreCors", __classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_createCorsOptions).call(this, config_1.configManager.config.projectConfig.http.storeCors));
/**
* Publishable key check, CORS and auth setup for store routes.
*/
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_applyStorePublishableKeyMiddleware).call(this, "/store");
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_applyAuthMiddleware).call(this, routesFinder, "/store", "customer", ["bearer", "session"], {
allowUnauthenticated: true,
});
/**
* Apply CORS middleware for "/auth" routes
*/
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_applyCorsMiddleware).call(this, routesFinder, "/auth", "shouldAppendAuthCors", __classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_createCorsOptions).call(this, config_1.configManager.config.projectConfig.http.authCors));
const collectionToSort = []
.concat(middlewares)
.concat(routes);
const sortedRoutes = new routes_sorter_1.RoutesSorter(collectionToSort).sort();
sortedRoutes.forEach((route) => {
if ("isRoute" in route) {
routesFinder.add(route);
}
__classPrivateFieldGet(this, _ApiLoader_instances, "m", _ApiLoader_registerExpressHandler).call(this, route);
});
/**
* Registering error handler as the final handler
*/
__classPrivateFieldGet(this, _ApiLoader_app, "f").use(sourceErrorHandler ?? (0, error_handler_1.errorHandler)());
}
}
exports.ApiLoader = ApiLoader;
_a = ApiLoader, _ApiLoader_app = new WeakMap(), _ApiLoader_sourceDirs = new WeakMap(), _ApiLoader_instances = new WeakSet(), _ApiLoader_loadHttpResources =
/**
* Loads routes, middleware, bodyParserConfig routes, routes that have
* opted out for Auth and CORS and the error handler.
*/
async function _ApiLoader_loadHttpResources() {
const routesLoader = new routes_loader_1.RoutesLoader();
const middlewareLoader = new middleware_file_loader_1.MiddlewareFileLoader();
for (let dir of __classPrivateFieldGet(this, _ApiLoader_sourceDirs, "f")) {
await routesLoader.scanDir(dir);
await middlewareLoader.scanDir(dir);
}
return {
routes: routesLoader.getRoutes(),
routesFinder: new routes_finder_1.RoutesFinder(),
middlewares: middlewareLoader.getMiddlewares(),
errorHandler: middlewareLoader.getErrorHandler(),
bodyParserConfigRoutes: middlewareLoader.getBodyParserConfigRoutes(),
additionalDataValidatorRoutes: middlewareLoader.getAdditionalDataValidatorRoutes(),
};
}, _ApiLoader_registerExpressHandler = function _ApiLoader_registerExpressHandler(route) {
if ("isRoute" in route) {
reporter_1.default.debug(`registering route ${route.method} ${route.matcher}`);
const handler = _a.traceRoute
? _a.traceRoute(route.handler, {
route: route.matcher,
method: route.method,
})
: route.handler;
__classPrivateFieldGet(this, _ApiLoader_app, "f")[route.method.toLowerCase()](route.matcher, (0, wrap_handler_1.wrapHandler)(handler));
return;
}
if (!route.methods) {
reporter_1.default.debug(`registering global middleware for ${route.matcher}`);
const handler = _a.traceMiddleware
? _a.traceMiddleware(route.handler, {
route: route.matcher,
})
: route.handler;
__classPrivateFieldGet(this, _ApiLoader_app, "f").use(route.matcher, (0, wrap_handler_1.wrapHandler)(handler));
return;
}
const methods = Array.isArray(route.methods)
? route.methods
: [route.methods];
methods.forEach((method) => {
reporter_1.default.debug(`registering route middleware ${method} ${route.matcher}`);
const handler = _a.traceMiddleware
? _a.traceMiddleware((0, wrap_handler_1.wrapHandler)(route.handler), {
route: route.matcher,
method: method,
})
: (0, wrap_handler_1.wrapHandler)(route.handler);
__classPrivateFieldGet(this, _ApiLoader_app, "f")[method.toLowerCase()](route.matcher, handler);
});
}, _ApiLoader_assignRestrictedFields = function _ApiLoader_assignRestrictedFields(baseRestrictedFields) {
__classPrivateFieldGet(this, _ApiLoader_app, "f").use("/store", ((req, _, next) => {
req.restrictedFields = new restricted_fields_1.RestrictedFields();
req.restrictedFields.add(baseRestrictedFields);
next();
}));
__classPrivateFieldGet(this, _ApiLoader_app, "f").use("/admin", ((req, _, next) => {
req.restrictedFields = new restricted_fields_1.RestrictedFields();
next();
}));
}, _ApiLoader_createCorsOptions = function _ApiLoader_createCorsOptions(origin) {
return {
origin: (0, utils_1.parseCorsOrigins)(origin),
credentials: true,
preflightContinue: false,
};
}, _ApiLoader_applyCorsMiddleware = function _ApiLoader_applyCorsMiddleware(routesFinder, namespace, toggleKey, corsOptions) {
const corsFn = (0, cors_1.default)(corsOptions);
const corsMiddleware = function corsMiddleware(req, res, next) {
let method = req.method;
if (req.method === "OPTIONS") {
method = req.headers["access-control-request-method"] ?? req.method;
}
const path = `${namespace}${req.path}`;
const matchingRoute = routesFinder.find(path, method);
if (matchingRoute && matchingRoute[toggleKey] === true) {
return corsFn(req, res, next);
}
reporter_1.default.debug(`Skipping CORS middleware ${req.method} ${path}`);
return next();
};
__classPrivateFieldGet(this, _ApiLoader_app, "f").use(namespace, _a.traceMiddleware
? _a.traceMiddleware(corsMiddleware, {
route: namespace,
})
: corsMiddleware);
}, _ApiLoader_applyAuthMiddleware = function _ApiLoader_applyAuthMiddleware(routesFinder, namespace, actorType, authType, options) {
reporter_1.default.debug(`Registering auth middleware for prefix ${namespace}`);
const originalFn = (0, middlewares_1.authenticate)(actorType, authType, options);
const authMiddleware = function authMiddleware(req, res, next) {
const path = `${namespace}${req.path}`;
const matchingRoute = routesFinder.find(path, req.method);
if (matchingRoute && matchingRoute.optedOutOfAuth) {
reporter_1.default.debug(`Skipping auth ${req.method} ${path}`);
return next();
}
reporter_1.default.debug(`Authenticating route ${req.method} ${path}`);
return originalFn(req, res, next);
};
__classPrivateFieldGet(this, _ApiLoader_app, "f").use(namespace, _a.traceMiddleware
? _a.traceMiddleware(authMiddleware, {
route: namespace,
})
: authMiddleware);
}, _ApiLoader_applyBodyParserMiddleware = function _ApiLoader_applyBodyParserMiddleware(namespace, routesFinder) {
reporter_1.default.debug(`Registering bodyparser middleware for prefix ${namespace}`);
__classPrivateFieldGet(this, _ApiLoader_app, "f").use(namespace, (0, bodyparser_1.createBodyParserMiddlewaresStack)(namespace, routesFinder, _a.traceMiddleware));
}, _ApiLoader_assignAdditionalDataValidator = function _ApiLoader_assignAdditionalDataValidator(namespace, routesFinder) {
reporter_1.default.debug(`Registering assignAdditionalDataValidator middleware for prefix ${namespace}`);
const additionalDataValidator = function additionalDataValidator(req, _, next) {
const matchingRoute = routesFinder.find(req.path, req.method);
if (matchingRoute && matchingRoute.validator) {
reporter_1.default.debug(`Using validator to validate additional data on ${req.method} ${req.path}`);
req.additionalDataValidator = matchingRoute.validator;
}
return next();
};
__classPrivateFieldGet(this, _ApiLoader_app, "f").use(namespace, _a.traceMiddleware
? _a.traceMiddleware(additionalDataValidator, {
route: namespace,
})
: additionalDataValidator);
}, _ApiLoader_applyStorePublishableKeyMiddleware = function _ApiLoader_applyStorePublishableKeyMiddleware(namespace) {
reporter_1.default.debug(`Registering publishable key middleware for namespace ${namespace}`);
let middleware = _a.traceMiddleware
? _a.traceMiddleware(ensure_publishable_api_key_1.ensurePublishableApiKeyMiddleware, {
route: namespace,
})
: ensure_publishable_api_key_1.ensurePublishableApiKeyMiddleware;
__classPrivateFieldGet(this, _ApiLoader_app, "f").use(namespace, middleware);
};
//# sourceMappingURL=router.js.map
;