UNPKG

@lucidcms/core

Version:

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

1,841 lines (1,795 loc) 453 kB
import { build_response_default, route_default } from "./chunk-SX4AK7IW.js"; import { ClientIntegrationsFormatter, CollectionDocumentVersions, CollectionDocumentsFormatter, CollectionsFormatter, EmailsFormatter, LocalesFormatter, MediaFormatter, PermissionsFormatter, RolesFormatter, SettingsFormatter, UsersFormatter, choose_accept_header_format_default, formatters_default, generate_process_key_default, get_unique_locale_codes_default, merge_translation_groups_default, should_update_translations_default } from "./chunk-URI3PAN7.js"; import { permissions_default, service_wrapper_default } from "./chunk-CGRLN764.js"; import { constants_default, decode_error_default, logging_default, lucid_api_error_default, lucid_error_default, permission_groups_default, translations_default } from "./chunk-ZMWDUGJW.js"; // src/libs/fastify/server.ts import Fastify from "fastify"; // src/libs/fastify/plugins/lucid.ts import fs10 from "node:fs"; import path5 from "node:path"; import fastifyCookie from "@fastify/cookie"; import cors from "@fastify/cors"; import fastifyHelmet from "@fastify/helmet"; import fastifyRateLimit from "@fastify/rate-limit"; import fastifyStatic2 from "@fastify/static"; import fastifySwagger from "@fastify/swagger"; import fastifySwaggerUi from "@fastify/swagger-ui"; import fp2 from "fastify-plugin"; // package.json var package_default = { name: "@lucidcms/core", version: "0.10.2-alpha.0", description: "The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.", type: "module", types: "./dist/index.d.ts", module: "dist/index.js", exports: { ".": { import: "./dist/index.js", types: "./dist/index.d.ts" }, "./adapters": { types: "./dist/adapters.d.ts", default: "./dist/adapters.js" }, "./api": { types: "./dist/api.d.ts", default: "./dist/api.js" }, "./builders": { types: "./dist/builders.d.ts", default: "./dist/builders.js" }, "./middleware": { types: "./dist/middleware.d.ts", default: "./dist/middleware.js" }, "./types": { types: "./dist/types.d.ts", default: "./dist/types.js" }, "./package.json": "./package.json" }, scripts: { build: "tsc && tsup", dev: "tsup --watch", format: "biome format ./src", "format:fix": "biome format --write ./src", lint: "biome lint ./src", "lint:fix": "biome lint --apply ./src", "clear-db:postgres": "node ./scripts/clear-db-pg.js" }, files: ["dist", "cms", "templates", "assets"], author: "Proto Digital", repository: { type: "git", url: "git+https://github.com/ProtoDigitalUK/lucid_cms.git", directory: "packages/core" }, keywords: [ "CMS", "Headless", "Node.js", "Typescript", "ESM", "Fastify", "Postgres", "SQLite", "LibSQL", "Kysely" ], devDependencies: { "@biomejs/biome": "^1.8.3", "@lucidcms/admin": "*", "@lucidcms/config": "*", "@types/fs-extra": "^11.0.4", "@types/jsonwebtoken": "^9.0.6", "@types/lodash.merge": "^4.6.9", "@types/mime-types": "^2.1.4", "@types/mjml": "^4.7.4", "@types/node": "^20.14.10", "@types/node-cron": "^3.0.11", "@types/pg": "^8.11.6", "@types/sanitize-html": "^2.11.0", "@types/semver": "^7.5.8", "@types/slug": "^5.0.9", "@types/uuid": "^10.0.0", tsup: "^8.2.4", typescript: "^5.5.4" }, dependencies: { "@fastify/cookie": "^9.3.1", "@fastify/cors": "^9.0.1", "@fastify/helmet": "^11.1.1", "@fastify/rate-limit": "^9.1.0", "@fastify/static": "^7.0.4", "@fastify/swagger": "^8.15.0", "@fastify/swagger-ui": "^4.1.0", "@libsql/kysely-libsql": "^0.4.1", "@tailwindcss/vite": "^4.0.0-beta.4", argon2: "^0.41.1", "better-sqlite3": "^11.5.0", blurhash: "^2.0.5", "date-fns": "^4.1.0", "fast-average-color-node": "^3.1.0", fastify: "^4.28.1", "fastify-plugin": "^4.5.1", "fs-extra": "^11.2.0", handlebars: "^4.7.8", jsonwebtoken: "^9.0.2", kysely: "^0.27.4", "lodash.merge": "^4.6.2", "mime-types": "^2.1.35", mjml: "^5.0.0-alpha.4", "node-cron": "^3.0.3", pg: "^8.13.1", "sanitize-html": "^2.13.1", semver: "^7.6.3", sharp: "^0.33.5", slug: "^10.0.0", "solid-js": "^1.9.3", tailwindcss: "^4.0.0-beta.4", uuid: "^11.0.3", vite: "^5.3.3", "vite-plugin-solid": "^2.11.0", winston: "^3.17.0", zod: "^3.23.8", "zod-validation-error": "^3.4.0", "@lucidcms/admin": "0.10.2-alpha.0" }, volta: { node: "20.18.1" }, license: "MIT" }; // src/actions/register-cron-jobs.ts import cron from "node-cron"; var registerCronJobs = async (service) => { try { cron.schedule(constants_default.cronSchedule, async () => { logging_default("info", { message: translations_default("running_cron_jobs") }); await Promise.allSettled([ service_wrapper_default(service.services.crons.clearExpiredLocales, { transaction: true, logError: true, defaultError: { type: "cron", name: translations_default("cron_job_error_name"), message: translations_default("an_error_occurred_clearing_expired_locales") } })(service), service_wrapper_default(service.services.crons.clearExpiredTokens, { transaction: true, logError: true, defaultError: { type: "cron", name: translations_default("cron_job_error_name"), message: translations_default("an_error_occurred_clearing_expired_tokens") } })(service), service_wrapper_default(service.services.crons.updateMediaStorage, { transaction: true, logError: true, defaultError: { type: "cron", name: translations_default("cron_job_error_name"), message: translations_default("an_error_occurred_updating_media_storage") } })(service), service_wrapper_default(service.services.crons.deleteExpiredMedia, { transaction: true, logError: true, defaultError: { type: "cron", name: translations_default("cron_job_error_name"), message: translations_default("an_error_occurred_deleting_expired_media") } })(service) ]); }); } catch (error) { logging_default("error", { message: translations_default("cron_job_error_message") }); } }; var register_cron_jobs_default = registerCronJobs; // src/actions/execute-start-tasks.ts var executeStartTasks = async (service) => { await service.config.db.migrateToLatest(); await Promise.all([ service_wrapper_default(service.services.start.executeSeeds, { transaction: true, logError: true, defaultError: { name: translations_default("seed_error_name") } })(service), service_wrapper_default(service.services.start.syncLocales, { transaction: true, logError: true, defaultError: { name: translations_default("start_error_name"), message: translations_default("locale_error_occured_saving_default") } })(service) ]); register_cron_jobs_default(service); }; var execute_start_tasks_default = executeStartTasks; // src/libs/config/get-config-path.ts import path from "node:path"; import fs from "fs-extra"; var getConfigPath = (cwd, filename) => { let configPath = void 0; const root = path.parse(cwd).root; const configFileName = filename ?? "lucid.config"; const configExtensions = [".ts", ".js", ".mjs", ".mts"]; const search = (cwd2) => { const files = fs.readdirSync(cwd2); const configFiles = files.filter((file) => { const { name, ext } = path.parse(file); return name === configFileName && configExtensions.includes(ext); }); if (configFiles.length > 0 && configFiles[0]) { configPath = path.resolve(cwd2, configFiles[0]); return; } const parent = path.resolve(cwd2, ".."); if (parent === cwd2 || parent === root) { return; } search(parent); }; search(cwd); if (!configPath) { throw new Error(translations_default("cannot_find_config_path")); } return configPath; }; var get_config_path_default = getConfigPath; // src/libs/config/get-config.ts import path2 from "node:path"; import { pathToFileURL } from "node:url"; var config = void 0; var getConfig = async (props) => { if (props?.config) { config = props.config; return config; } if (config) { return config; } const configPath = props?.givenPath ? props.givenPath : get_config_path_default(process.cwd()); const importPath = pathToFileURL(path2.resolve(configPath)).href; const configModule = await import( /* @vite-ignore */ importPath ); config = configModule.default; return config; }; var get_config_default = getConfig; // src/schemas/auth.ts import z from "zod"; var auth_default = { getCSRF: { body: void 0, query: void 0, params: void 0 }, login: { body: z.object({ usernameOrEmail: z.string(), password: z.string() }), query: void 0, params: void 0 }, token: { body: void 0, query: void 0, params: void 0 }, logout: { body: void 0, query: void 0, params: void 0 } }; // src/utils/swagger/swagger-response.ts var metaObject = { type: "object", properties: { path: { type: "string" }, links: { type: "array" }, currentPage: { type: "number", nullable: true, example: null }, lastPage: { type: "number", nullable: true, example: null }, perPage: { type: "number", nullable: true, example: null }, total: { type: "number", nullable: true, example: null } } }; var paginatedMetaObject = { type: "object", properties: { path: { type: "string" }, links: { type: "array", items: { type: "object", properties: { active: { type: "boolean" }, label: { type: "string" }, url: { type: "string", nullable: true }, page: { type: "number" } } } }, currentPage: { type: "number", nullable: true, example: constants_default.query.page }, lastPage: { type: "number", nullable: true, example: 200 / constants_default.query.perPage }, perPage: { type: "number", nullable: true, example: constants_default.query.perPage }, total: { type: "number", nullable: true, example: 200 } } }; var linksObject = { type: "object", properties: { first: { type: "string", nullable: true }, last: { type: "string", nullable: true }, next: { type: "string", nullable: true }, prev: { type: "string", nullable: true } } }; var swaggerResponse = (params) => { let description = translations_default("swagger_response_200"); const headers = {}; switch (params.type) { case 200: description = translations_default("swagger_response_200"); break; case 201: description = translations_default("swagger_response_201"); break; case 204: description = translations_default("swagger_response_204"); break; case 400: description = translations_default("swagger_response_400"); break; case 401: description = translations_default("swagger_response_401"); break; case 403: description = translations_default("swagger_response_403"); break; case 404: description = translations_default("swagger_response_404"); break; case 500: description = translations_default("swagger_response_500"); break; } const propertise = { data: params.data, meta: params.paginated ? paginatedMetaObject : metaObject }; if (params.paginated) { propertise.links = linksObject; } return { description, type: params.noPropertise === true ? "null" : "object", properties: params.noPropertise === true ? void 0 : propertise, headers }; }; var swagger_response_default = swaggerResponse; // src/utils/swagger/swagger-headers.ts var swaggerHeaders = (headers) => { const propertise = {}; const required = []; if (headers.csrf !== void 0) { propertise._csrf = { type: "string", description: translations_default("swagger_csrf_header_description") }; if (headers.csrf) { required.push("_csrf"); } } if (headers.contentLocale !== void 0) { propertise["lucid-content-locale"] = { type: "string", description: translations_default("swagger_content_locale_header_description") }; } if (headers.clientKey !== void 0) { propertise["lucid-client-key"] = { type: "string", description: translations_default("swagger_client_key_header_description") }; } if (headers.authorization !== void 0) { propertise.Authorization = { type: "string", description: translations_default("swagger_authorization_header_description") }; } return { type: "object", properties: propertise, required }; }; var swagger_headers_default = swaggerHeaders; // src/utils/swagger/swagger-query-string.ts var swaggerQueryString = (config2) => { const queryString = { type: "object", properties: {} }; if (config2.include && config2.include.length > 0) { queryString.properties.include = { type: "string", enum: config2.include, description: translations_default("swagger_query_string_include_description") }; } if (config2.filters && config2.filters.length > 0) { for (const filter of config2.filters) { queryString.properties[`filter[${filter.key}]`] = { type: "string", enum: filter.enum, description: translations_default("swagger_query_string_filter_description") }; } } if (config2.sorts && config2.sorts.length > 0) { queryString.properties.sort = { type: "string", enum: config2.sorts, description: translations_default("swagger_query_string_sort_description") }; } if (config2.page) { queryString.properties.page = { type: "number", description: translations_default("swagger_query_string_page_description") }; } if (config2.perPage) { queryString.properties.perPage = { type: "number", description: translations_default("swagger_query_string_per_page_description") }; } return queryString; }; var swagger_query_string_default = swaggerQueryString; // src/controllers/auth/get-csrf.ts var getCSRFController = async (request, reply) => { const tokenRes = await request.server.services.auth.csrf.generateToken( request, reply ); if (tokenRes.error) throw new lucid_api_error_default(tokenRes.error); reply.status(200).send( build_response_default(request, { data: { _csrf: tokenRes.data } }) ); }; var get_csrf_default = { controller: getCSRFController, zodSchema: auth_default.getCSRF, swaggerSchema: { description: "This route returns a CSRF token in the response body and also sets a _csrf httpOnly cookie. The client can use this token on required routes by setting a _csrf header. On required routes this header will be checked against the _csrf cookie.", tags: ["auth"], summary: "Returns a CSRF token", response: { 200: swagger_response_default({ type: 200, data: { type: "object", properties: { _csrf: { type: "string" } } } }) } } }; // src/controllers/auth/login.ts var loginController = async (request, reply) => { const userRes = await service_wrapper_default(request.server.services.auth.login, { transaction: false, defaultError: { type: "basic", code: "login", name: translations_default("route_login_error_name"), message: translations_default("route_login_error_message") } })( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { usernameOrEmail: request.body.usernameOrEmail, password: request.body.password } ); if (userRes.error) throw new lucid_api_error_default(userRes.error); const [refreshRes, accessRes] = await Promise.all([ request.server.services.auth.refreshToken.generateToken( reply, request, userRes.data.id ), request.server.services.auth.accessToken.generateToken( reply, request, userRes.data.id ) ]); if (refreshRes.error) throw new lucid_api_error_default(refreshRes.error); if (accessRes.error) throw new lucid_api_error_default(accessRes.error); reply.status(204).send(); }; var login_default = { controller: loginController, zodSchema: auth_default.login, swaggerSchema: { description: "Authenticates a user and sets a refresh and access token as httpOnly cookies.", tags: ["auth"], summary: "Authenticates a user and sets httpOnly cookies", body: { type: "object", properties: { usernameOrEmail: { type: "string" }, password: { type: "string" } }, required: ["usernameOrEmail", "password"] }, response: { 204: swagger_response_default({ type: 204, noPropertise: true }) }, headers: swagger_headers_default({ csrf: true }) } }; // src/controllers/auth/token.ts var tokenController = async (request, reply) => { const payloadRes = await request.server.services.auth.refreshToken.verifyToken(request, reply); if (payloadRes.error) throw new lucid_api_error_default(payloadRes.error); const [refreshRes, accessRes] = await Promise.all([ request.server.services.auth.refreshToken.generateToken( reply, request, payloadRes.data.user_id ), request.server.services.auth.accessToken.generateToken( reply, request, payloadRes.data.user_id ) ]); if (refreshRes.error) throw new lucid_api_error_default(refreshRes.error); if (accessRes.error) throw new lucid_api_error_default(accessRes.error); reply.status(204).send(); }; var token_default = { controller: tokenController, zodSchema: auth_default.token, swaggerSchema: { description: "Verifies the refresh token and issues a new access and refresh token.", tags: ["auth"], summary: "Issues a new access and refresh token.", response: { 204: swagger_response_default({ type: 204, noPropertise: true }) }, headers: swagger_headers_default({ csrf: true }) } }; // src/controllers/auth/logout.ts var logoutController = async (request, reply) => { const [clearRefreshRes, clearAccessRes, clearCSRFRes] = await Promise.all([ request.server.services.auth.refreshToken.clearToken(request, reply), request.server.services.auth.accessToken.clearToken(reply), request.server.services.auth.csrf.clearToken(reply) ]); if (clearRefreshRes.error) throw new lucid_api_error_default(clearRefreshRes.error); if (clearAccessRes.error) throw new lucid_api_error_default(clearAccessRes.error); if (clearCSRFRes.error) throw new lucid_api_error_default(clearCSRFRes.error); reply.status(204).send(); }; var logout_default = { controller: logoutController, zodSchema: auth_default.logout, swaggerSchema: { description: "Logs out a user by clearing the refresh token and access token, it also clears the CSRF token", tags: ["auth"], summary: "Logs out a user", response: { 204: swagger_response_default({ type: 204, noPropertise: true }) }, headers: swagger_headers_default({ csrf: true }) } }; // src/controllers/auth/index.ts var auth_default2 = { getCSRF: get_csrf_default, login: login_default, token: token_default, logout: logout_default }; // src/routes/v1/api/auth.routes.ts var authRoutes = async (fastify2) => { route_default(fastify2, { method: "get", url: "/csrf", zodSchema: auth_default2.getCSRF.zodSchema, swaggerSchema: auth_default2.getCSRF.swaggerSchema, controller: auth_default2.getCSRF.controller }); route_default(fastify2, { method: "post", url: "/token", middleware: { validateCSRF: true // Does have the authenticate middleware because all it does it checks if the access token is valid // and if it is it will return the user data, this handles authorisatio itsself via the refresh token. }, zodSchema: auth_default2.token.zodSchema, swaggerSchema: auth_default2.token.swaggerSchema, controller: auth_default2.token.controller }); route_default(fastify2, { method: "post", url: "/login", middleware: { validateCSRF: true }, zodSchema: auth_default2.login.zodSchema, swaggerSchema: auth_default2.login.swaggerSchema, controller: auth_default2.login.controller }); route_default(fastify2, { method: "post", url: "/logout", middleware: { authenticate: true, validateCSRF: true }, zodSchema: auth_default2.logout.zodSchema, swaggerSchema: auth_default2.logout.swaggerSchema, controller: auth_default2.logout.controller }); }; var auth_routes_default = authRoutes; // src/schemas/permissions.ts var permissions_default2 = { getAll: { body: void 0, query: void 0, params: void 0 } }; // src/controllers/permissions/get-all.ts var getAllController = async (request, reply) => { const PermissionsFormatter2 = formatters_default.get("permissions"); reply.status(200).send( build_response_default(request, { data: PermissionsFormatter2.formatMultiple({ permissions: permission_groups_default }) }) ); }; var get_all_default = { controller: getAllController, zodSchema: permissions_default2.getAll, swaggerSchema: { description: "Returns a list of all permissions available for users.", tags: ["permissions"], summary: "Get all permissions", response: { 200: swagger_response_default({ type: 200, data: { type: "array", items: PermissionsFormatter.swagger } }) } } }; // src/controllers/permissions/index.ts var permissions_default3 = { getAll: get_all_default }; // src/routes/v1/api/permissions.routes.ts var permissionRoutes = async (fastify2) => { route_default(fastify2, { method: "get", url: "", middleware: { authenticate: true }, swaggerSchema: permissions_default3.getAll.swaggerSchema, zodSchema: permissions_default3.getAll.zodSchema, controller: permissions_default3.getAll.controller }); }; var permissions_routes_default = permissionRoutes; // src/schemas/roles.ts import z3 from "zod"; // src/schemas/default-query.ts import z2 from "zod"; var filterOperators = z2.enum(["=", "%", "like", "ilike", "in", "not in", "<>", "is not", "is", "!="]).optional(); var filterSchemas = { single: z2.object({ value: z2.union([z2.string(), z2.number()]), operator: filterOperators }), union: z2.object({ value: z2.union([ z2.string(), z2.array(z2.string()), z2.number(), z2.array(z2.number()) ]), operator: filterOperators }) }; var default_query_default = { filter: z2.object({}).optional(), sort: z2.array( z2.object({ key: z2.string(), value: z2.enum(["asc", "desc"]) }) ).optional(), include: z2.array(z2.string()).optional(), exclude: z2.array(z2.string()).optional(), page: z2.number(), perPage: z2.number() }; // src/schemas/roles.ts var roles_default = { createSingle: { body: z3.object({ name: z3.string().min(2), description: z3.string().optional(), permissions: z3.array(z3.string()) }), query: void 0, params: void 0 }, updateSingle: { body: z3.object({ name: z3.string().min(2).optional(), description: z3.string().optional(), permissions: z3.array(z3.string()).optional() }), query: void 0, params: z3.object({ id: z3.string() }) }, deleteSingle: { body: void 0, query: void 0, params: z3.object({ id: z3.string() }) }, getMultiple: { body: void 0, query: z3.object({ filter: z3.object({ name: filterSchemas.single.optional(), roleIds: filterSchemas.union.optional() }).optional(), sort: z3.array( z3.object({ key: z3.enum(["createdAt", "name"]), value: z3.enum(["asc", "desc"]) }) ).optional(), include: z3.array(z3.enum(["permissions"])).optional(), exclude: default_query_default.exclude, page: default_query_default.page, perPage: default_query_default.perPage }), params: void 0 }, getSingle: { body: void 0, query: void 0, params: z3.object({ id: z3.string() }) } }; // src/controllers/roles/create-single.ts var createSingleController = async (request, reply) => { const roleId = await service_wrapper_default( request.server.services.role.createSingle, { transaction: true, defaultError: { type: "basic", name: translations_default("route_roles_create_error_name"), message: translations_default("route_roles_create_error_message") } } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { name: request.body.name, description: request.body.description, permissions: request.body.permissions } ); if (roleId.error) throw new lucid_api_error_default(roleId.error); const role = await service_wrapper_default(request.server.services.role.getSingle, { transaction: false, defaultError: { type: "basic", name: translations_default("route_roles_fetch_error_name"), message: translations_default("route_roles_fetch_error_message") } })( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { id: roleId.data } ); if (role.error) throw new lucid_api_error_default(role.error); reply.status(200).send( build_response_default(request, { data: role.data }) ); }; var create_single_default = { controller: createSingleController, zodSchema: roles_default.createSingle, swaggerSchema: { description: "Create a single role with the given name and permission groups.", tags: ["roles"], summary: "Create a single role", response: { 200: swagger_response_default({ type: 200, data: RolesFormatter.swagger }) }, body: { type: "object", properties: { name: { type: "string" }, description: { type: "string" }, permissions: { type: "array", items: { type: "string" } } }, required: ["name", "permissions"] }, headers: swagger_headers_default({ csrf: true }) } }; // src/controllers/roles/get-single.ts var getSingleController = async (request, reply) => { const role = await service_wrapper_default(request.server.services.role.getSingle, { transaction: false, defaultError: { type: "basic", name: translations_default("route_roles_fetch_error_name"), message: translations_default("route_roles_fetch_error_message") } })( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { id: Number.parseInt(request.params.id, 10) } ); if (role.error) throw new lucid_api_error_default(role.error); reply.status(200).send( build_response_default(request, { data: role.data }) ); }; var get_single_default = { controller: getSingleController, zodSchema: roles_default.getSingle, swaggerSchema: { description: "Returns a single role based on the id URL paramater.", tags: ["roles"], summary: "Get a single role", response: { 200: swagger_response_default({ type: 200, data: RolesFormatter.swagger }) } } }; // src/controllers/roles/get-multiple.ts var getMultipleController = async (request, reply) => { const role = await service_wrapper_default(request.server.services.role.getMultiple, { transaction: false, defaultError: { type: "basic", name: translations_default("route_roles_fetch_error_name"), message: translations_default("route_roles_fetch_error_message") } })( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { query: request.query } ); if (role.error) throw new lucid_api_error_default(role.error); reply.status(200).send( build_response_default(request, { data: role.data.data, pagination: { count: role.data.count, page: request.query.page, perPage: request.query.perPage } }) ); }; var get_multiple_default = { controller: getMultipleController, zodSchema: roles_default.getMultiple, swaggerSchema: { description: "Returns multiple roles based on the query parameters.", tags: ["roles"], summary: "Get multiple roles", response: { 200: swagger_response_default({ type: 200, data: { type: "array", items: RolesFormatter.swagger }, paginated: true }) }, querystring: swagger_query_string_default({ include: ["permissions"], filters: [ { key: "name" }, { key: "roleIds" } ], sorts: ["name", "createdAt"], page: true, perPage: true }) } }; // src/controllers/roles/delete-single.ts var deleteSingleController = async (request, reply) => { const deleteSingle7 = await service_wrapper_default( request.server.services.role.deleteSingle, { transaction: true, defaultError: { type: "basic", name: translations_default("route_roles_delete_error_name"), message: translations_default("route_roles_delete_error_message") } } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { id: Number.parseInt(request.params.id) } ); if (deleteSingle7.error) throw new lucid_api_error_default(deleteSingle7.error); reply.status(204).send(); }; var delete_single_default = { controller: deleteSingleController, zodSchema: roles_default.deleteSingle, swaggerSchema: { description: "Delete a single role based on the given role id.", tags: ["roles"], summary: "Delete a single role", response: { 204: swagger_response_default({ type: 204, noPropertise: true }) }, headers: swagger_headers_default({ csrf: true }) } }; // src/controllers/roles/update-single.ts var updateSingleController = async (request, reply) => { const updateSingel = await service_wrapper_default( request.server.services.role.updateSingle, { transaction: true, defaultError: { type: "basic", name: translations_default("route_roles_update_error_name"), message: translations_default("route_roles_update_error_message") } } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { id: Number.parseInt(request.params.id), name: request.body.name, description: request.body.description, permissions: request.body.permissions } ); if (updateSingel.error) throw new lucid_api_error_default(updateSingel.error); reply.status(204).send(); }; var update_single_default = { controller: updateSingleController, zodSchema: roles_default.updateSingle, swaggerSchema: { description: "Update a single role with the given name and permission groups.", tags: ["roles"], summary: "Update a single role", response: { 204: swagger_response_default({ type: 204, noPropertise: true }) }, body: { type: "object", properties: { name: { type: "string" }, description: { type: "string" }, permissions: { type: "array", items: { type: "string" } } } }, headers: swagger_headers_default({ csrf: true }) } }; // src/controllers/roles/index.ts var roles_default2 = { createSingle: create_single_default, getSingle: get_single_default, getMultiple: get_multiple_default, deleteSingle: delete_single_default, updateSingle: update_single_default }; // src/routes/v1/api/roles.routes.ts var roleRoutes = async (fastify2) => { route_default(fastify2, { method: "post", url: "", middleware: { authenticate: true, validateCSRF: true }, permissions: ["create_role"], swaggerSchema: roles_default2.createSingle.swaggerSchema, zodSchema: roles_default2.createSingle.zodSchema, controller: roles_default2.createSingle.controller }); route_default(fastify2, { method: "get", url: "/:id", middleware: { authenticate: true }, swaggerSchema: roles_default2.getSingle.swaggerSchema, zodSchema: roles_default2.getSingle.zodSchema, controller: roles_default2.getSingle.controller }); route_default(fastify2, { method: "get", url: "", middleware: { authenticate: true }, swaggerSchema: roles_default2.getMultiple.swaggerSchema, zodSchema: roles_default2.getMultiple.zodSchema, controller: roles_default2.getMultiple.controller }); route_default(fastify2, { method: "delete", url: "/:id", middleware: { authenticate: true, validateCSRF: true }, permissions: ["delete_role"], swaggerSchema: roles_default2.deleteSingle.swaggerSchema, zodSchema: roles_default2.deleteSingle.zodSchema, controller: roles_default2.deleteSingle.controller }); route_default(fastify2, { method: "patch", url: "/:id", permissions: ["update_role"], middleware: { authenticate: true, validateCSRF: true }, swaggerSchema: roles_default2.updateSingle.swaggerSchema, zodSchema: roles_default2.updateSingle.zodSchema, controller: roles_default2.updateSingle.controller }); }; var roles_routes_default = roleRoutes; // src/schemas/account.ts import z4 from "zod"; var account_default = { getMe: { body: void 0, query: void 0, params: void 0 }, updateMe: { body: z4.object({ firstName: z4.string().optional(), lastName: z4.string().optional(), username: z4.string().min(3).optional(), email: z4.string().email().optional(), currentPassword: z4.string().optional(), newPassword: z4.string().min(8).max(128).optional(), passwordConfirmation: z4.string().min(8).max(128).optional() }), query: void 0, params: void 0 }, sendResetPassword: { body: z4.object({ email: z4.string().email() }), query: void 0, params: void 0 }, verifyResetPassword: { body: void 0, query: void 0, params: z4.object({ token: z4.string() }) }, resetPassword: { body: z4.object({ password: z4.string().min(8).max(128), passwordConfirmation: z4.string().min(8).max(128) }).refine((data) => data.password === data.passwordConfirmation, { message: translations_default("please_ensure_passwords_match"), path: ["passwordConfirmation"] }), query: void 0, params: z4.object({ token: z4.string() }) } }; // src/controllers/account/update-me.ts var updateMeController = async (request, reply) => { const updateMe2 = await service_wrapper_default( request.server.services.account.updateMe, { transaction: true, defaultError: { type: "basic", name: translations_default("route_user_me_update_error_name"), message: translations_default("route_user_me_update_error_message") } } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { auth: request.auth, firstName: request.body.firstName, lastName: request.body.lastName, username: request.body.username, email: request.body.email, currentPassword: request.body.currentPassword, newPassword: request.body.newPassword, passwordConfirmation: request.body.passwordConfirmation } ); if (updateMe2.error) throw new lucid_api_error_default(updateMe2.error); reply.status(204).send(); }; var update_me_default = { controller: updateMeController, zodSchema: account_default.updateMe, swaggerSchema: { description: "Used to update the current authenticated users information", tags: ["account"], summary: "Update the authenticated user", response: { 204: swagger_response_default({ type: 204, noPropertise: true }) }, body: { type: "object", properties: { firstName: { type: "string" }, lastName: { type: "string" }, username: { type: "string" }, email: { type: "string" }, roleIds: { type: "array", items: { type: "number" } } } }, headers: swagger_headers_default({ csrf: true }) } }; // src/controllers/account/get-me.ts var getMeController = async (request, reply) => { const user = await service_wrapper_default(request.server.services.user.getSingle, { transaction: false, defaultError: { type: "basic", name: translations_default("route_user_fetch_error_name"), message: translations_default("route_user_fetch_error_message") } })( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { userId: request.auth.id } ); if (user.error) throw new lucid_api_error_default(user.error); reply.status(200).send( build_response_default(request, { data: user.data }) ); }; var get_me_default = { controller: getMeController, zodSchema: account_default.getMe, swaggerSchema: { description: "Returns user data based on the authenticated user", tags: ["account"], summary: "Returns user data based on the authenticated user", response: { 200: swagger_response_default({ type: 200, data: UsersFormatter.swagger }) } } }; // src/controllers/account/send-reset-password.ts var sendResetPasswordController = async (request, reply) => { const resetPassword2 = await service_wrapper_default( request.server.services.account.sendResetPassword, { transaction: true, defaultError: { type: "basic", name: translations_default("route_send_password_reset_error_name"), message: translations_default("route_send_password_reset_error_message") } } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { email: request.body.email } ); if (resetPassword2.error) throw new lucid_api_error_default(resetPassword2.error); reply.status(200).send( build_response_default(request, { data: resetPassword2.data }) ); }; var send_reset_password_default = { controller: sendResetPasswordController, zodSchema: account_default.sendResetPassword, swaggerSchema: { description: "Sends a reset password email to the given users email", tags: ["account"], summary: "Send reset password email", response: { 200: swagger_response_default({ type: 200, data: { type: "object", properties: { message: { type: "string" } } } }) }, headers: swagger_headers_default({ csrf: true }) } }; // src/controllers/account/verify-reset-password.ts var verifyResetPasswordController = async (request, reply) => { const token = await service_wrapper_default( request.server.services.user.token.getSingle, { transaction: false, defaultError: { type: "basic", name: translations_default("route_verify_password_reset_error_name"), message: translations_default("route_verify_password_reset_error_message") } } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { tokenType: "password_reset", token: request.params.token } ); if (token.error) throw new lucid_api_error_default(token.error); reply.status(204).send(); }; var verify_reset_password_default = { controller: verifyResetPasswordController, zodSchema: account_default.verifyResetPassword, swaggerSchema: { description: "Verifies the password reset token is valid", tags: ["account"], summary: "Verify reset token", response: { 204: swagger_response_default({ type: 204, noPropertise: true }) } } }; // src/controllers/account/reset-password.ts var resetPasswordController = async (request, reply) => { const resetPassword2 = await service_wrapper_default( request.server.services.account.resetPassword, { transaction: true, defaultError: { type: "basic", name: translations_default("route_reset_password_error_name"), message: translations_default("route_reset_password_error_message") } } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { token: request.params.token, password: request.body.password } ); if (resetPassword2.error) throw new lucid_api_error_default(resetPassword2.error); reply.status(204).send(); }; var reset_password_default = { controller: resetPasswordController, zodSchema: account_default.resetPassword, swaggerSchema: { description: "Resets the password for the user if the token is valid", tags: ["account"], summary: "Resets users password", response: { 204: swagger_response_default({ type: 204, noPropertise: true }) }, headers: swagger_headers_default({ csrf: true }) } }; // src/controllers/account/index.ts var account_default2 = { updateMe: update_me_default, getMe: get_me_default, sendResetPassword: send_reset_password_default, verifyResetPassword: verify_reset_password_default, resetPassword: reset_password_default }; // src/routes/v1/api/account.routes.ts var accountRoutes = async (fastify2) => { route_default(fastify2, { method: "get", url: "", middleware: { authenticate: true }, zodSchema: account_default2.getMe.zodSchema, swaggerSchema: account_default2.getMe.swaggerSchema, controller: account_default2.getMe.controller }); route_default(fastify2, { method: "patch", url: "", middleware: { authenticate: true, validateCSRF: true }, swaggerSchema: account_default2.updateMe.swaggerSchema, zodSchema: account_default2.updateMe.zodSchema, controller: account_default2.updateMe.controller }); route_default(fastify2, { method: "post", url: "/reset-password", middleware: { validateCSRF: true }, swaggerSchema: account_default2.sendResetPassword.swaggerSchema, zodSchema: account_default2.sendResetPassword.zodSchema, controller: account_default2.sendResetPassword.controller }); route_default(fastify2, { method: "get", url: "/reset-password/:token", swaggerSchema: account_default2.verifyResetPassword.swaggerSchema, zodSchema: account_default2.verifyResetPassword.zodSchema, controller: account_default2.verifyResetPassword.controller }); route_default(fastify2, { method: "patch", url: "/reset-password/:token", middleware: { validateCSRF: true }, swaggerSchema: account_default2.resetPassword.swaggerSchema, zodSchema: account_default2.resetPassword.zodSchema, controller: account_default2.resetPassword.controller }); }; var account_routes_default = accountRoutes; // src/schemas/locales.ts import z5 from "zod"; var stringTranslations = z5.union([ z5.string(), z5.record(z5.enum(constants_default.locales), z5.string()) ]); var locales_default = { getSingle: { query: void 0, params: z5.object({ code: z5.string().min(2) }), body: void 0 }, getAll: { query: void 0, params: void 0, body: void 0 }, client: { getAll: { query: void 0, params: void 0, body: void 0 } } }; // src/controllers/locales/client/get-all.ts var getAllController2 = async (request, reply) => { const locales = await service_wrapper_default(request.server.services.locale.getAll, { transaction: false, defaultError: { type: "basic", name: translations_default("route_locale_fetch_error_name"), message: translations_default("route_locale_fetch_error_message") } })({ db: request.server.config.db.client, config: request.server.config, services: request.server.services }); if (locales.error) throw new lucid_api_error_default(locales.error); reply.status(200).send( build_response_default(request, { data: locales.data }) ); }; var get_all_default2 = { controller: getAllController2, zodSchema: locales_default.client.getAll, swaggerSchema: { description: "Returns all enabled locales via the client integration.", tags: ["client-integrations", "locales"], summary: "Get all locales", response: { 200: swagger_response_default({ type: 200, data: { type: "array", items: LocalesFormatter.swagger }, paginated: true }) }, querystring: swagger_query_string_default({ sorts: ["code", "createdAt", "updatedAt"], page: true, perPage: true }) } }; // src/controllers/locales/client/index.ts var client_default = { getAll: get_all_default2 }; // src/controllers/locales/get-single.ts var getSingleController2 = async (request, reply) => { const localeRes = await service_wrapper_default( request.server.services.locale.getSingle, { transaction: false, defaultError: { type: "basic", name: translations_default("route_locale_fetch_error_name"), message: translations_default("route_locale_fetch_error_message") } } )( { db: request.server.config.db.client, config: request.server.config, services: request.server.services }, { code: request.params.code } ); if (localeRes.error) throw new lucid_api_error_default(localeRes.error); reply.status(200).send( build_response_default(request, { data: localeRes.data }) ); }; var get_single_default2 = { controller: getSingleController2, zodSchema: locales_default.getSingle, swaggerSchema: { description: "Returns a single locale based on the code URL parameter.", tags: ["locales"], summary: "Get a single locale", response: { 200: swagger_response_default({ type: 200, data: LocalesFormatter.swagger }) } } }; // src/controllers/locales/get-all.ts var getAllController3 = async (request, reply) => { const locales = await service_wrapper_default(request.server.services.locale.getAll, { transaction: false, defaultError: { type: "basic", name: translations_default("route_locale_fetch_error_name"), message: translations_default("route_locale_fetch_error_message") } })({ db: request.server.config.db.client, config: request.server.config, services: request.server.services }); if (locales.error) throw new lucid_api_error_default(locales.error); reply.status(200).send( build_response_default(request, { data: locales.data }) ); }; var get_all_default3 = { controller: getAllController3, zodSchema: locales_default.getAll, swaggerSchema: { description: "Returns all locale.", tags: ["locales"], summary: "Get all locales", response: { 200: swagger_response_default({ type: 200, data: { type: "array", items: LocalesFormatter.swagger }, paginated: true }) }, querystring: swagger_query_string_default({ sorts: ["code", "createdAt", "updatedAt"], page: true, perPage: true }) } }; // src/controllers/locales/index.ts var locales_default2 = { client: client_default, getSingle: get_single_default2, getAll: get_all_default3 }; // src/routes/v1/api/locales.routes.ts var localeRoutes = async (fastify2) => { route_default(fastify2, { method: "get", url: "/:code", middleware: { authenticate: true }, swaggerSchema: locales_default2.getSingle.swaggerSchema, zodSchema: locales_default2.getSingle.zodSchema, controller: locales_default2.getSingle.controller }); route_default(fastify2, { method: "get", url: "", middleware: { authenticate: true }, swaggerSchema: locales_default2.getAll.swaggerSchema, zodSchema: locales_default2.getAll.zodSchema, controller: locales_default2.g