@lucidcms/core
Version:
The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.
1,713 lines (1,673 loc) • 607 kB
JavaScript
import {
build_response_default,
route_default,
swaggerRegisterRefs,
swagger_headers_default,
swagger_refs_default,
swagger_response_default
} from "./chunk-JNP7DCNX.js";
import {
build_table_name_default,
choose_accept_header_format_default,
collectionTableParts,
formatters_default,
generate_process_key_default,
get_unique_locale_codes_default,
merge_translation_groups_default,
should_update_translations_default
} from "./chunk-5BJFGYMM.js";
import "./chunk-K5KJEV2Z.js";
import {
prefix_generated_column_name_default
} from "./chunk-FRZBD5RL.js";
import {
permissions_default,
service_wrapper_default
} from "./chunk-HLKZRFCZ.js";
import {
decode_error_default,
logger_default,
logging_default,
lucid_api_error_default,
lucid_error_default,
tidy_zod_errors_default
} from "./chunk-7SRFYA4B.js";
import {
constants_default,
permission_groups_default,
translations_default
} from "./chunk-7XW7FQ7W.js";
// src/libs/fastify/server.ts
import Fastify from "fastify";
// src/libs/fastify/plugins/lucid.ts
import fs8 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 fp2 from "fastify-plugin";
// package.json
var package_default = {
name: "@lucidcms/core",
version: "0.11.0-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"
},
"./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"
},
"./helpers": {
types: "./dist/helpers.d.ts",
default: "./dist/helpers.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"
},
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",
"Kysely"
],
devDependencies: {
"@biomejs/biome": "^1.9.4",
"@lucidcms/admin": "*",
"@lucidcms/config": "*",
"@types/jsonwebtoken": "^9.0.9",
"@types/lodash.merge": "^4.6.9",
"@types/mime-types": "^2.1.4",
"@types/mjml": "^4.7.4",
"@types/node": "^22.15.2",
"@types/node-cron": "^3.0.11",
"@types/sanitize-html": "^2.15.0",
"@types/semver": "^7.7.0",
"@types/slug": "^5.0.9",
tsup: "^8.4.0",
typescript: "^5.8.3"
},
dependencies: {
"@fastify/cookie": "^11.0.2",
"@fastify/cors": "^11.0.1",
"@fastify/helmet": "^13.0.1",
"@fastify/rate-limit": "^10.2.2",
"@fastify/static": "^8.1.1",
"@fastify/swagger": "^9.5.0",
"@lucidcms/admin": "0.11.0-alpha.0",
"@scalar/fastify-api-reference": "^1.28.26",
"@tailwindcss/vite": "^4.1.4",
argon2: "^0.43.0",
blurhash: "^2.0.5",
"date-fns": "^4.1.0",
"fast-average-color-node": "^3.1.0",
fastify: "^5.3.2",
"fastify-plugin": "^5.0.1",
handlebars: "^4.7.8",
jiti: "^2.4.2",
jsonwebtoken: "^9.0.2",
kysely: "0.27.4",
"lodash.merge": "^4.6.2",
"mime-types": "^3.0.1",
mjml: "^5.0.0-alpha.6",
"node-cron": "^3.0.3",
"sanitize-html": "^2.16.0",
semver: "^7.7.1",
sharp: "^0.33.5",
slug: "^10.0.0",
"solid-js": "^1.9.5",
tailwindcss: "^4.1.4",
vite: "^6.3.5",
"vite-plugin-solid": "^2.11.6",
winston: "^3.17.0",
zod: "^4.0.0-beta"
},
volta: {
node: "22.15.0"
},
engines: {
node: ">=22.0.0 <23.0.0"
},
license: "BSL-1.0"
};
// 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"),
scope: constants_default.logScopes.cron
});
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.clearExpiredCollections, {
transaction: true,
logError: true,
defaultError: {
type: "cron",
name: translations_default("cron_job_error_name"),
message: translations_default("an_error_occurred_clearing_expired_collections")
}
})(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"),
scope: constants_default.logScopes.cron
});
}
};
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),
service_wrapper_default(service.services.start.syncCollections, {
transaction: true,
logError: true,
defaultError: {
name: translations_default("start_error_name"),
message: translations_default("collection_error_occured_saving_default")
}
})(service)
]);
await service_wrapper_default(
service.services.collection.migrator.migrateCollections,
{
transaction: true,
logError: true,
defaultError: {
name: translations_default("collection_migrator_error_name")
}
}
)(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 "node:fs";
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";
import { createJiti } from "jiti";
var jiti = createJiti(import.meta.url);
var config = void 0;
var getConfig = async (props) => {
if (props?.config) {
config = props.config;
return config;
}
if (config) {
return config;
}
const configPath = props?.path ? props.path : get_config_path_default(process.cwd());
const importPath = pathToFileURL(path2.resolve(configPath)).href;
if (props?.dynamicImport) {
const configModule = await import(importPath);
config = configModule.default;
} else {
const configModule = await jiti.import(importPath, { default: true });
config = configModule;
}
return config;
};
var get_config_default = getConfig;
// src/libs/fastify/controllers/auth/get-csrf.ts
import z2 from "zod";
// src/schemas/auth.ts
import z from "zod";
var controllerSchemas = {
getCSRF: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: z.object({
_csrf: z.string().meta({
description: "Store this value and use it for the _csrf header on required endpoints.",
example: "55b26b90b9715d0e9cc425e8f1ba565cad5157e3d56ae8380d8c832a5fb3fcb7"
})
})
},
login: {
body: z.object({
usernameOrEmail: z.string().meta({
description: "Username or email address",
example: "admin"
}),
password: z.string().meta({
description: "User password",
example: "password"
})
}).meta({ description: "User credentials for login" }),
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: void 0
},
token: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: void 0
},
logout: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: void 0
}
};
// src/libs/fastify/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: controllerSchemas.getCSRF,
swaggerSchema: {
description: "This endpoint returns a CSRF token in the response body as well as setting a _csrf httpOnly cookie. Some endpoints require this value to be passed via a _csrf header.",
tags: ["auth"],
summary: "CSRF Token",
response: swagger_response_default({
schema: z2.toJSONSchema(controllerSchemas.getCSRF.response)
})
}
};
// src/libs/fastify/controllers/auth/login.ts
import z3 from "zod";
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: controllerSchemas.login,
swaggerSchema: {
description: "Authenticates a user and sets a refresh and access token as httpOnly cookies.",
tags: ["auth"],
summary: "Login",
headers: swagger_headers_default({
csrf: true
}),
body: z3.toJSONSchema(controllerSchemas.login.body),
response: swagger_response_default({
noProperties: true
})
}
};
// src/libs/fastify/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: controllerSchemas.token,
swaggerSchema: {
description: "Verifies the refresh token and issues a new access and refresh token.",
tags: ["auth"],
summary: "Refresh Token",
headers: swagger_headers_default({
csrf: true
}),
response: swagger_response_default({
noProperties: true
})
}
};
// src/libs/fastify/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: controllerSchemas.logout,
swaggerSchema: {
description: "Logs out a user by clearing the refresh token and access token, it also clears the CSRF token.",
tags: ["auth"],
summary: "Logout",
headers: swagger_headers_default({
csrf: true
}),
response: swagger_response_default({
noProperties: true
})
}
};
// src/libs/fastify/controllers/auth/index.ts
var controllers = {
getCSRF: get_csrf_default,
login: login_default,
token: token_default,
logout: logout_default
};
var auth_default = controllers;
// src/libs/fastify/routes/v1/api/auth.routes.ts
var authRoutes = async (fastify2) => {
route_default(fastify2, {
method: "get",
url: "/csrf",
zodSchema: auth_default.getCSRF.zodSchema,
swaggerSchema: auth_default.getCSRF.swaggerSchema,
controller: auth_default.getCSRF.controller
});
route_default(fastify2, {
method: "post",
url: "/login",
middleware: {
validateCSRF: true
},
zodSchema: auth_default.login.zodSchema,
swaggerSchema: auth_default.login.swaggerSchema,
controller: auth_default.login.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_default.token.zodSchema,
swaggerSchema: auth_default.token.swaggerSchema,
controller: auth_default.token.controller
});
route_default(fastify2, {
method: "post",
url: "/logout",
middleware: {
authenticate: true,
validateCSRF: true
},
zodSchema: auth_default.logout.zodSchema,
swaggerSchema: auth_default.logout.swaggerSchema,
controller: auth_default.logout.controller
});
};
var auth_routes_default = authRoutes;
// src/libs/fastify/controllers/permissions/get-all.ts
import z5 from "zod";
// src/schemas/permissions.ts
import z4 from "zod";
var permissionResponseSchema = z4.object({
key: z4.string().meta({
description: "The permission's group key",
example: "users_permissions"
}),
permissions: z4.array(z4.string()).meta({
description: "The permissions for this permission group",
example: ["create_user", "update_user", "delete_user"]
})
});
var controllerSchemas2 = {
getAll: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: z4.array(permissionResponseSchema)
}
};
// src/libs/fastify/controllers/permissions/get-all.ts
var getAllController = async (request, reply) => {
const PermissionsFormatter = formatters_default.get("permissions");
reply.status(200).send(
build_response_default(request, {
data: PermissionsFormatter.formatMultiple({
permissions: permission_groups_default
})
})
);
};
var get_all_default = {
controller: getAllController,
zodSchema: controllerSchemas2.getAll,
swaggerSchema: {
description: "Returns a list of all permissions available for users.",
tags: ["permissions"],
summary: "Get All Permissions",
response: swagger_response_default({
schema: z5.toJSONSchema(controllerSchemas2.getAll.response)
})
}
};
// src/libs/fastify/controllers/permissions/index.ts
var controllers2 = {
getAll: get_all_default
};
var permissions_default2 = controllers2;
// src/libs/fastify/routes/v1/api/permissions.routes.ts
var permissionRoutes = async (fastify2) => {
route_default(fastify2, {
method: "get",
url: "",
middleware: {
authenticate: true
},
swaggerSchema: permissions_default2.getAll.swaggerSchema,
zodSchema: permissions_default2.getAll.zodSchema,
controller: permissions_default2.getAll.controller
});
};
var permissions_routes_default = permissionRoutes;
// src/libs/fastify/controllers/roles/create-single.ts
import z8 from "zod";
// src/schemas/roles.ts
import z7 from "zod";
// src/schemas/helpers/querystring.ts
import z6 from "zod";
var filterOperators = z6.enum(["=", "%", "like", "ilike", "in", "not in", "<>", "is not", "is", "!="]).optional();
var queryString = {
schema: {
filter: (multiple = false, example, description) => z6.string().meta({
description: multiple ? description || "Accepts multiple values separated by commas." : description || "Accepts a single value only.",
example
}).optional(),
sort: (example) => z6.string().meta({
description: "Orders results using comma-separated field names. Prefix with - for descending order.",
example
}).optional(),
include: (example) => z6.string().meta({
description: "Specifies related resources to include in response as comma-separated values",
example
}).optional(),
exclude: (example) => z6.string().meta({
description: "Defines fields to exclude from response as comma-separated values",
example
}).optional(),
page: z6.string().regex(/^[1-9][0-9]*$/).describe(
"Specifies the page number for pagination (must be a positive integer)"
).optional(),
perPage: z6.string().regex(/^([1-9][0-9]*|-1)$/).describe(
"Sets the number of items per page (use positive integer or -1 for all items)"
).optional()
},
meta: {
patternProperties: {
"^filter\\[([^\\]:]+):?([^\\]]*)\\]$": {
type: ["string", "null"],
description: "Dynamic filter parameter in format filter[fieldName:operator]. Supported operators include: '=', '%', 'like', 'ilike', 'in', 'not in', '<>', 'is not', 'is' and '!='."
}
},
additionalProperties: false
}
};
var queryFormatted = {
schema: {
filters: {
single: z6.object({
value: z6.union([z6.string(), z6.number()]),
operator: filterOperators
}),
union: z6.object({
value: z6.union([
z6.string(),
z6.array(z6.string()),
z6.number(),
z6.array(z6.number())
]),
operator: filterOperators
})
},
page: z6.number(),
perPage: z6.number()
}
};
// src/schemas/roles.ts
var roleResponseSchema = z7.interface({
id: z7.number().meta({
description: "The role ID",
example: 1
}),
name: z7.string().meta({
description: "The role's name",
example: "Editors"
}),
description: z7.string().nullable().meta({
description: "The role's description",
example: "Editor's can edit documents from any collection"
}),
"permissions?": z7.array(
z7.object({
id: z7.number().meta({
description: "The permission ID",
example: 1
}),
permission: z7.string().meta({
description: "The permission key",
example: "create_user"
})
})
).meta({
description: "A list of all of the roles permissions"
}),
createdAt: z7.string().meta({
description: "Creation timestamp",
example: "2022-01-01T00:00:00Z"
}),
updatedAt: z7.string().meta({
description: "Last update timestamp",
example: "2022-01-01T00:00:00Z"
})
});
var controllerSchemas3 = {
createSingle: {
body: z7.object({
name: z7.string().min(2).meta({
description: "The role's name",
example: "Editor"
}),
description: z7.string().meta({
description: "A description for the role",
example: "Editor's can edit documents from any collection"
}).optional(),
permissions: z7.array(z7.string()).meta({
description: "A lit of permissions",
example: ["create_user", "update_user"]
})
}),
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: roleResponseSchema
},
updateSingle: {
body: z7.object({
name: z7.string().min(2).meta({
description: "The role's name",
example: "Editor"
}).optional(),
description: z7.string().meta({
description: "A description for the role",
example: "Editor's can edit documents from any collection"
}).optional(),
permissions: z7.array(z7.string()).meta({
description: "A lit of permissions",
example: ["create_user", "update_user"]
}).optional()
}),
query: {
string: void 0,
formatted: void 0
},
params: z7.object({
id: z7.string().meta({
description: "The role's ID",
example: 1
})
}),
response: void 0
},
deleteSingle: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: z7.object({
id: z7.string().meta({
description: "The role's ID",
example: 1
})
}),
response: void 0
},
getMultiple: {
body: void 0,
query: {
string: z7.object({
"filter[name]": queryString.schema.filter(false, "Editor"),
"filter[roleIds]": queryString.schema.filter(true, "1,2"),
sort: queryString.schema.sort("createdAt,name"),
include: queryString.schema.include("permissions"),
page: queryString.schema.page,
perPage: queryString.schema.perPage
}).meta(queryString.meta),
formatted: z7.object({
filter: z7.object({
name: queryFormatted.schema.filters.single.optional(),
roleIds: queryFormatted.schema.filters.union.optional()
}).optional(),
sort: z7.array(
z7.object({
key: z7.enum(["createdAt", "name"]),
value: z7.enum(["asc", "desc"])
})
).optional(),
include: z7.array(z7.enum(["permissions"])).optional(),
page: queryFormatted.schema.page,
perPage: queryFormatted.schema.perPage
})
},
params: void 0,
response: z7.array(roleResponseSchema)
},
getSingle: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: z7.object({
id: z7.string().meta({
description: "The role's ID",
example: 1
})
}),
response: roleResponseSchema
}
};
// src/libs/fastify/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: controllerSchemas3.createSingle,
swaggerSchema: {
description: "Create a single role with the given name and permission groups.",
tags: ["roles"],
summary: "Create Role",
headers: swagger_headers_default({
csrf: true
}),
body: z8.toJSONSchema(controllerSchemas3.createSingle.body),
response: swagger_response_default({
schema: z8.toJSONSchema(controllerSchemas3.createSingle.response)
})
}
};
// src/libs/fastify/controllers/roles/get-single.ts
import z9 from "zod";
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: controllerSchemas3.getSingle,
swaggerSchema: {
description: "Returns a single role based on the given ID.",
tags: ["roles"],
summary: "Get Role",
params: z9.toJSONSchema(controllerSchemas3.getSingle.params),
response: swagger_response_default({
schema: z9.toJSONSchema(controllerSchemas3.getSingle.response)
})
}
};
// src/libs/fastify/controllers/roles/get-multiple.ts
import z10 from "zod";
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.formattedQuery
}
);
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.formattedQuery.page,
perPage: request.formattedQuery.perPage
}
})
);
};
var get_multiple_default = {
controller: getMultipleController,
zodSchema: controllerSchemas3.getMultiple,
swaggerSchema: {
description: "Returns multiple roles based on the query parameters.",
tags: ["roles"],
summary: "Get Multiple Roles",
querystring: z10.toJSONSchema(controllerSchemas3.getMultiple.query.string),
response: swagger_response_default({
schema: z10.toJSONSchema(controllerSchemas3.getMultiple.response),
paginated: true
})
}
};
// src/libs/fastify/controllers/roles/delete-single.ts
import z11 from "zod";
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: controllerSchemas3.deleteSingle,
swaggerSchema: {
description: "Delete a single role based on the given role ID.",
tags: ["roles"],
summary: "Delete Role",
headers: swagger_headers_default({
csrf: true
}),
params: z11.toJSONSchema(controllerSchemas3.deleteSingle.params),
response: swagger_response_default({
noProperties: true
})
}
};
// src/libs/fastify/controllers/roles/update-single.ts
import z12 from "zod";
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: controllerSchemas3.updateSingle,
swaggerSchema: {
description: "Update a single role with the given name and permission groups by ID.",
tags: ["roles"],
summary: "Update Role",
headers: swagger_headers_default({
csrf: true
}),
body: z12.toJSONSchema(controllerSchemas3.updateSingle.body),
params: z12.toJSONSchema(controllerSchemas3.updateSingle.params),
response: swagger_response_default({
noProperties: true
})
}
};
// src/libs/fastify/controllers/roles/index.ts
var controllers3 = {
createSingle: create_single_default,
getSingle: get_single_default,
getMultiple: get_multiple_default,
deleteSingle: delete_single_default,
updateSingle: update_single_default
};
var roles_default = controllers3;
// src/libs/fastify/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_default.createSingle.swaggerSchema,
zodSchema: roles_default.createSingle.zodSchema,
controller: roles_default.createSingle.controller
});
route_default(fastify2, {
method: "get",
url: "/:id",
middleware: {
authenticate: true
},
swaggerSchema: roles_default.getSingle.swaggerSchema,
zodSchema: roles_default.getSingle.zodSchema,
controller: roles_default.getSingle.controller
});
route_default(fastify2, {
method: "get",
url: "",
middleware: {
authenticate: true
},
swaggerSchema: roles_default.getMultiple.swaggerSchema,
zodSchema: roles_default.getMultiple.zodSchema,
controller: roles_default.getMultiple.controller
});
route_default(fastify2, {
method: "delete",
url: "/:id",
middleware: {
authenticate: true,
validateCSRF: true
},
permissions: ["delete_role"],
swaggerSchema: roles_default.deleteSingle.swaggerSchema,
zodSchema: roles_default.deleteSingle.zodSchema,
controller: roles_default.deleteSingle.controller
});
route_default(fastify2, {
method: "patch",
url: "/:id",
permissions: ["update_role"],
middleware: {
authenticate: true,
validateCSRF: true
},
swaggerSchema: roles_default.updateSingle.swaggerSchema,
zodSchema: roles_default.updateSingle.zodSchema,
controller: roles_default.updateSingle.controller
});
};
var roles_routes_default = roleRoutes;
// src/libs/fastify/controllers/account/update-me.ts
import z15 from "zod";
// src/schemas/account.ts
import z14 from "zod";
// src/schemas/users.ts
import z13 from "zod";
var userResponsePermissionSchema = z13.string().meta({
description: "A permission identifier",
example: "create_user"
});
var userResponseRoleSchema = z13.object({
id: z13.number().meta({
description: "The role ID",
example: 1
}),
name: z13.string().meta({
description: "The role name",
example: "Admin"
})
});
var userResponseSchema = z13.object({
id: z13.number().meta({
description: "The user's ID",
example: 1
}),
superAdmin: z13.boolean().meta({
description: "Whether the user is a superadmin.",
example: true
}),
email: z13.email().meta({
description: "The user's email address",
example: "admin@lucidcms.io"
}),
username: z13.string().meta({
description: "The user's username",
example: "admin"
}),
firstName: z13.string().nullable().meta({
description: "The user's first name",
example: "John"
}),
lastName: z13.string().nullable().meta({
description: "The user's last name",
example: "Smith"
}),
triggerPasswordReset: z13.boolean().nullable().meta({
description: "Should the UI force a password reset?",
example: false
}),
roles: z13.array(userResponseRoleSchema).meta({
description: "The user's roles"
}),
permissions: z13.array(userResponsePermissionSchema),
createdAt: z13.string().nullable().meta({
description: "The date the user was added",
example: "2021-06-10T20:00:00.000Z"
}),
updatedAt: z13.string().nullable().meta({
description: "The date the user row was last updated",
example: "2021-06-10T20:00:00.000Z"
})
});
var controllerSchemas4 = {
createSingle: {
body: z13.object({
email: z13.email().meta({
description: "The user's email address",
example: "admin@lucidcms.io"
}),
username: z13.string().meta({
description: "The user's username",
example: "Admin"
}),
roleIds: z13.array(z13.number()).meta({
description: "A list of role IDs to attach to the user",
example: [1, 2]
}),
firstName: z13.string().meta({
description: "The user's first name",
example: "John"
}).optional(),
lastName: z13.string().meta({
description: "The user's last name",
example: "Smith"
}).optional(),
superAdmin: z13.boolean().meta({
description: "Whether the user is a super admin or not",
example: true
}).optional()
}),
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: userResponseSchema
},
updateSingle: {
body: z13.object({
roleIds: z13.array(z13.number()).meta({
description: "A list of role IDs to attach to the user",
example: [1, 2]
}).optional(),
superAdmin: z13.boolean().meta({
description: "Whether the user is a super admin or not",
example: true
}).optional(),
triggerPasswordReset: z13.boolean().meta({
description: "Whether the user should be forced to update their password in the UI",
example: true
}).optional(),
isDeleted: z13.literal(false).meta({
description: "Restore a deleted user",
example: false
}).optional()
}),
query: {
string: void 0,
formatted: void 0
},
params: z13.object({
id: z13.string().meta({
description: "The user's ID",
example: 1
})
}),
response: void 0
},
getSingle: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: z13.object({
id: z13.string().meta({
description: "The user's ID",
example: 1
})
}),
response: userResponseSchema
},
getMultiple: {
query: {
string: z13.object({
"filter[firstName]": queryString.schema.filter(false, "John"),
"filter[lastName]": queryString.schema.filter(false, "Smith"),
"filter[email]": queryString.schema.filter(
false,
"admin@lucidcms.io"
),
"filter[username]": queryString.schema.filter(false, "admin"),
"filter[roleIds]": queryString.schema.filter(true, "1,2,3"),
"filter[id]": queryString.schema.filter(true, "1,2"),
sort: queryString.schema.sort(
"createdAt,updatedAt,firstName,lastName,email,username"
),
include: queryString.schema.include("permissions"),
page: queryString.schema.page,
perPage: queryString.schema.perPage
}).meta(queryString.meta),
formatted: z13.object({
filter: z13.object({
firstName: queryFormatted.schema.filters.single.optional(),
lastName: queryFormatted.schema.filters.single.optional(),
email: queryFormatted.schema.filters.single.optional(),
username: queryFormatted.schema.filters.single.optional(),
roleIds: queryFormatted.schema.filters.union.optional(),
id: queryFormatted.schema.filters.union.optional()
}).optional(),
sort: z13.array(
z13.object({
key: z13.enum([
"createdAt",
"updatedAt",
"firstName",
"lastName",
"email",
"username"
]),
value: z13.enum(["asc", "desc"])
})
).optional(),
include: z13.array(z13.enum(["permissions"])).optional(),
page: queryFormatted.schema.page,
perPage: queryFormatted.schema.perPage
})
},
params: void 0,
body: void 0,
response: z13.array(userResponseSchema)
},
deleteSingle: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: z13.object({
id: z13.string().meta({
description: "The user's ID",
example: 1
})
}),
response: void 0
}
};
// src/schemas/account.ts
var controllerSchemas5 = {
getMe: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: userResponseSchema
},
resetPassword: {
body: z14.object({
password: z14.string().min(8).max(128).meta({
description: "Your new password",
example: "password123"
}),
passwordConfirmation: z14.string().min(8).max(128).meta({
description: "A repeat of your new password",
example: "password123"
})
}).refine((data) => data.password === data.passwordConfirmation, {
message: translations_default("please_ensure_passwords_match"),
path: ["passwordConfirmation"]
}),
query: {
string: void 0,
formatted: void 0
},
params: z14.object({
token: z14.string().meta({
description: "A unique token granted to you when you request a password reset",
example: "838ece1033bf7c7468e873e79ba2a3ec"
})
}),
response: void 0
},
sendResetPassword: {
body: z14.object({
email: z14.email().meta({
description: "Your email address",
example: "admin@lucidcms.io"
})
}),
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: z14.object({
message: z14.string().meta({
description: "A status message",
example: translations_default("if_account_exists_with_email_not_found")
})
})
},
verifyResetPassword: {
body: void 0,
query: {
string: void 0,
formatted: void 0
},
params: z14.object({
token: z14.string().meta({
description: "A unique token granted to you when you request a password reset",
example: "838ece1033bf7c7468e873e79ba2a3ec"
})
}),
response: void 0
},
updateMe: {
body: z14.object({
firstName: z14.string().meta({
description: "Your new first name",
example: "John"
}).optional(),
lastName: z14.string().meta({
description: "Your new last name",
example: "Smith"
}).optional(),
username: z14.string().min(3).meta({
description: "Your new username",
example: "admin"
}).optional(),
email: z14.email().meta({
description: "your new email address",
example: "admin@lucidcms.io"
}).optional(),
currentPassword: z14.string().meta({
description: "Your current password",
example: "password"
}).optional(),
newPassword: z14.string().min(8).max(128).meta({
description: "Your new password",
example: "password123"
}).optional(),
passwordConfirmation: z14.string().min(8).max(128).meta({
description: "A repeat of your new password",
example: "password123"
}).optional()
}),
query: {
string: void 0,
formatted: void 0
},
params: void 0,
response: void 0
}
};
// src/libs/fastify/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: controllerSchemas5.updateMe,
swaggerSchema: {
description: "Update the authenticated user's information.",
tags: ["account"],
summary: "Update Authenticated User",
headers: swagger_headers_default({
csrf: true
}),
body: z15.toJSONSchema(controllerSchemas5.updateMe.body),
response: swagger_response_default({
noProperties: true
})
}
};
// src/libs/fastify/controllers/account/get-me.ts
import z16 from "zod";
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: controllerSchemas5.getMe,
swaggerSchema: {
description: "Returns the authenticated user based on the access token.",
tags: ["account"],
summary: "Get Authenticated User",
response: swagger_response_default({
schema: z16.toJSONSchema(controllerSchemas5.getMe.response)
})
}
};
// src/libs/fastify/controllers/account/send-reset-password.ts
import z17 from "zod";
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: controllerSchemas5.sendResetPassword,
swaggerSchema: {
description: "Sends an email to the given email address informing them to reset their password.",
tags: ["account"],
summary: "Send Password Reset",
headers: swagger_headers_default({
csrf: true
}),
body: z17.toJSONSchema(controllerSchemas5.sendResetPassword.body),
response: swagger_response_default({
schema: z17.toJSONSchema(controllerSchemas5.sendResetPassword.response)
})
}
};
// src/libs/fastify/controllers/account/verify-reset-password.ts
import z18 from "zod";
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: controllerSchemas5.verifyResetPassword,
swaggerSchema: {
description: "Verifies the password reset token is valid.",
tags: ["account"],
summary: "Verify Reset Token",
params: z18.toJSONSchema(controllerSchemas5.verifyResetPassword.params),
response: swagger_response_default({
noProperties: true
})
}
};
// src/libs/fastify/controllers/account/reset-password.ts
import z19 from "zod";
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: reques