UNPKG

@lucidcms/core

Version:

The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.

401 lines (388 loc) 11.5 kB
import { constants_default, error_type_defaults_default, logging_default, lucid_api_error_default, translations_default } from "./chunk-ZMWDUGJW.js"; // src/middleware/log-route.ts var logRoute = (hook) => async (request, reply) => { if (hook === "prehandler") { logging_default("info", { message: `Request - ${request.url}`, scope: request.method, data: { userAgent: request.headers["user-agent"], timeStamp: Date.now() } }); return; } logging_default("info", { message: `Response - ${request.url}`, scope: request.method, data: { userAgent: request.headers["user-agent"], timeStamp: Date.now(), elapsedTime: reply.elapsedTime, status: reply.statusCode } }); }; var log_route_default = logRoute; // src/middleware/validate-body.ts import z from "zod"; var validateBody = (schema) => async (request) => { const bodySchema = z.object({ body: schema ?? z.object({}) }); const validateResult = await bodySchema.safeParseAsync({ body: request.body || {} }); if (!validateResult.success) { throw new lucid_api_error_default({ type: "validation", message: translations_default("validation_body_error_message"), zod: validateResult.error }); } request.body = validateResult.data.body; }; var validate_body_default = validateBody; // src/middleware/validate-params.ts import z2 from "zod"; var validateParams = (schema) => async (request) => { const bodySchema = z2.object({ params: schema ?? z2.object({}) }); const validateResult = await bodySchema.safeParseAsync({ params: request.params }); if (!validateResult.success) { throw new lucid_api_error_default({ type: "validation", message: translations_default("validation_params_error_message"), zod: validateResult.error }); } request.params = validateResult.data.params; }; var validate_params_default = validateParams; // src/middleware/validate-query.ts import z3 from "zod"; var buildSort = (query) => { const queryObject = query; const sort = queryObject.sort; if (!sort) return void 0; return sort.split(",").map((sort2) => { if (sort2.startsWith("-")) { return { key: sort2.slice(1), value: "desc" }; } return { key: sort2, value: "asc" }; }); }; var buildFilter = (query) => { return Object.entries( query ).reduce((acc, [key, value]) => { if (key.includes("filter[")) { const match = key.match(/filter\[([^\]:]+):?([^\]]*)\]/); if (!match) return acc; const [, name, operator] = match; if (!name) return acc; acc[name] = { value: value.includes(",") ? value.split(",") : value, operator: operator === "" || operator === void 0 ? void 0 : operator }; } return acc; }, {}); }; var buildPage = (query) => { const queryObject = query; const page = queryObject.page; if (!page) return constants_default.query.page; return Number.parseInt(page); }; var buildPerPage = (query) => { const queryObject = query; const perPage = queryObject.perPage; if (!perPage) return constants_default.query.perPage; return Number.parseInt(perPage); }; var buildInclude = (query) => { const queryObject = query; const include = queryObject.include; if (!include) return void 0; return include.split(","); }; var buildExclude = (query) => { const queryObject = query; const exclude = queryObject.exclude; if (!exclude) return void 0; return exclude.split(","); }; var addRemainingQuery = (query) => { const queryObject = query; const remainingQuery = Object.fromEntries( Object.entries(queryObject).filter( ([key]) => !["include", "exclude", "filter", "sort", "page", "perPage"].includes( key ) ) ); return remainingQuery; }; var validateQuery = (schema) => async (request) => { const querySchema = z3.object({ query: schema ?? z3.object({}) }); const validateResult = await querySchema.safeParseAsync({ query: { sort: buildSort(request.query), filter: buildFilter(request.query), include: buildInclude(request.query), exclude: buildExclude(request.query), page: buildPage(request.query), perPage: buildPerPage(request.query), ...addRemainingQuery(request.query) } }); if (!validateResult.success) { throw new lucid_api_error_default({ type: "validation", message: translations_default("validation_query_error_message"), zod: validateResult.error }); } request.query = validateResult.data.query; }; var validate_query_default = validateQuery; // src/middleware/authenticate.ts var authenticate = async (request) => { const accessTokenRes = request.server.services.auth.accessToken.verifyToken(request); if (accessTokenRes.error) throw new lucid_api_error_default(accessTokenRes.error); request.auth = accessTokenRes.data; }; var authenticate_default = authenticate; // src/middleware/validate-csrf.ts var validateCSRF = async (request) => { const verifyCSRFRes = request.server.services.auth.csrf.verifyToken(request); if (verifyCSRFRes.error) throw new lucid_api_error_default(verifyCSRFRes.error); }; var validate_csrf_default = validateCSRF; // src/middleware/permissions.ts var throwPermissionError = () => { throw new lucid_api_error_default({ type: "basic", name: translations_default("permission_error_name"), message: translations_default("you_do_not_have_permission_to_perform_this_action"), status: 403 }); }; var permissions = (permissions2) => async (request) => { const payloadPermissions = request.auth.permissions; if (request.auth.superAdmin) return; if (payloadPermissions === void 0) return throwPermissionError(); if (permissions2) { for (const permission of permissions2) { if (!payloadPermissions.includes(permission)) { throwPermissionError(); break; } } } }; var permissions_default = permissions; // src/utils/services/utils/transaction-error.ts var TransactionError = class extends Error { error; constructor(error) { super(error.message); this.error = error; } }; var transaction_error_default = TransactionError; // src/utils/services/utils/merge-errors.ts var mergeServiceError = (error, defaultError) => { const errorTypeRes = error_type_defaults_default(error); error.status = errorTypeRes.status; error.name = errorTypeRes.name; error.message = errorTypeRes.message; return { type: error.type ?? defaultError?.type ?? "basic", name: error.name ?? defaultError?.name ?? translations_default("unknown_service_error"), message: error.message ?? defaultError?.message ?? translations_default("unknown_service_error_message"), status: error.status ?? defaultError?.status ?? 500, code: error.code ?? defaultError?.code ?? void 0, zod: error.zod ?? void 0, errorResponse: error.errorResponse ?? void 0 }; }; var merge_errors_default = mergeServiceError; // src/utils/services/service-wrapper.ts var serviceWrapper = (fn, wrapperConfig) => async (service, ...args) => { try { if (wrapperConfig.schema) { const result = await wrapperConfig.schema.safeParseAsync( args[wrapperConfig.schemaArgIndex ?? 0] ); if (result.success === false) { return { error: merge_errors_default( { type: "validation", // message: result.error.message, zod: result.error }, wrapperConfig.defaultError ), data: void 0 }; } } if (!wrapperConfig.transaction || service.db.isTransaction) { const result = await fn(service, ...args); if (result.error) return { error: merge_errors_default(result.error, wrapperConfig.defaultError), data: void 0 }; return result; } return await service.db.transaction().execute(async (tx) => { const result = await fn( { ...service, db: tx }, ...args ); if (result.error) { throw new transaction_error_default(result.error); } return result; }); } catch (error) { if (wrapperConfig.logError) { logging_default("error", { // @ts-expect-error message: error?.message ?? translations_default("an_unknown_error_occurred") }); } if (error instanceof transaction_error_default) { return { error: merge_errors_default(error.error, wrapperConfig.defaultError), data: void 0 }; } if (error instanceof Error) { return { error: merge_errors_default( { message: error.message }, wrapperConfig.defaultError ), data: void 0 }; } return { error: merge_errors_default( { // @ts-expect-error message: error?.message ?? void 0 }, wrapperConfig.defaultError ), data: void 0 }; } }; var service_wrapper_default = serviceWrapper; // src/middleware/content-locale.ts var contentLocale = async (request) => { const contentLocale2 = request.headers[constants_default.headers.contentLocale]; const localeRes = await service_wrapper_default( request.server.services.locale.getSingleFallback, { transaction: false } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { code: Array.isArray(contentLocale2) ? contentLocale2[0] : contentLocale2 } ); if (localeRes.error) throw new lucid_api_error_default(localeRes.error); request.locale = localeRes.data; return; }; var content_locale_default = contentLocale; // src/middleware/client-authenticate.ts var clientAuthentication = async (request) => { const clientKey = request.headers[constants_default.headers.clientIntegrationKey]; const apiKey = request.headers.authorization; if (!clientKey) { throw new lucid_api_error_default({ type: "authorisation", message: translations_default("client_integration_key_missing"), status: 401 }); } if (!apiKey) { throw new lucid_api_error_default({ type: "authorisation", message: translations_default("client_integration_api_key_missing"), status: 401 }); } const verifyApiKey = await service_wrapper_default( request.server.services.clientIntegrations.verifyApiKey, { transaction: false, defaultError: { type: "authorisation", message: translations_default("client_integration_error"), status: 401 } } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { key: String(clientKey), apiKey } ); if (verifyApiKey.error) throw new lucid_api_error_default(verifyApiKey.error); request.clientIntegrationAuth = verifyApiKey.data; }; var client_authenticate_default = clientAuthentication; export { log_route_default, validate_body_default, validate_params_default, validate_query_default, authenticate_default, validate_csrf_default, permissions_default, service_wrapper_default, content_locale_default, client_authenticate_default }; //! Kysely needs function to throw for transaction to rollback !\\ //# sourceMappingURL=chunk-CGRLN764.js.map