@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
JavaScript
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