@lucidcms/core
Version:
The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.
1,857 lines (1,832 loc) • 49.8 kB
JavaScript
import {
constants_default,
lucid_error_default,
translations_default
} from "./chunk-ZMWDUGJW.js";
// src/utils/media/create-cdn-url.ts
var createCdnUrl = (host, key) => `${host}/cdn/v1/${key}`;
var create_cdn_url_default = createCdnUrl;
// src/utils/media/choose-accept-header-format.ts
var chooseAcceptHeaderFormat = (accept, queryFormat) => {
if (queryFormat) return queryFormat;
if (accept) {
if (accept.includes("image/webp")) return "webp";
if (accept.includes("image/avif")) return "avif";
}
return void 0;
};
var choose_accept_header_format_default = chooseAcceptHeaderFormat;
// src/utils/media/generate-process-key.ts
var generateProcessKey = (data) => {
const [targetK, ext] = data.key.split(".");
let key = `processed/${targetK}`;
if (data.options.quality) key = key.concat(`-${data.options.quality}`);
if (data.options.width) key = key.concat(`-${data.options.width}`);
if (data.options.height) key = key.concat(`-${data.options.height}`);
if (data.options.format) key = key.concat(`.${data.options.format}`);
else key = key.concat(`.${ext}`);
return key;
};
var generate_process_key_default = generateProcessKey;
// src/libs/formatters/user-permissions.ts
var UserPermissionsFormatter = class {
formatMultiple = (props) => {
if (!props.roles) {
return {
roles: [],
permissions: []
};
}
const permissionsSet = /* @__PURE__ */ new Set();
for (const role of props.roles) {
if (!role.permissions) continue;
for (const permission of role.permissions) {
permissionsSet.add(permission.permission);
}
}
return {
roles: props.roles.map(({ id, name }) => ({ id, name })),
permissions: Array.from(permissionsSet)
};
};
static swaggerPermissions = {
type: "array",
items: {
type: "string",
example: "create_user"
}
};
static swaggerRoles = {
type: "array",
items: {
type: "object",
properties: {
id: { type: "number", example: 1 },
name: { type: "string", example: "Admin" }
}
}
};
};
// src/libs/formatters/users.ts
var UsersFormatter = class {
formatMultiple = (props) => {
return props.users.map(
(u) => this.formatSingle({
user: u
})
);
};
formatSingle = (props) => {
const { roles, permissions } = new UserPermissionsFormatter().formatMultiple({
roles: props.user.roles || []
});
return {
id: props.user.id,
superAdmin: props.user.super_admin ?? 0,
email: props.user.email,
username: props.user.username,
firstName: props.user.first_name,
lastName: props.user.last_name,
roles,
permissions,
triggerPasswordReset: props.user.triggered_password_reset,
createdAt: formatters_default.formatDate(props.user.created_at),
updatedAt: formatters_default.formatDate(props.user.updated_at)
};
};
static swagger = {
type: "object",
properties: {
id: { type: "number", example: 1 },
superAdmin: { type: "number", example: 1 },
email: { type: "string", example: "admin@lucidcms.io" },
username: { type: "string", example: "admin" },
firstName: { type: "string", example: "Admin" },
lastName: { type: "string", example: "User" },
triggerPasswordReset: { type: "number", example: 0 },
roles: UserPermissionsFormatter.swaggerRoles,
permissions: UserPermissionsFormatter.swaggerPermissions,
createdAt: { type: "string", example: "2021-06-10T20:00:00.000Z" },
updatedAt: { type: "string", example: "2021-06-10T20:00:00.000Z" }
}
};
};
// src/libs/formatters/roles.ts
var RolesFormatter = class {
formatMultiple = (props) => {
return props.roles.map(
(r) => this.formatSingle({
role: r
})
);
};
formatSingle = (props) => {
return {
id: props.role.id,
name: props.role.name,
description: props.role.description,
permissions: props.role.permissions?.map((p) => {
return {
id: p.id,
permission: p.permission
};
}),
createdAt: formatters_default.formatDate(props.role.created_at),
updatedAt: formatters_default.formatDate(props.role.updated_at)
};
};
static swagger = {
type: "object",
properties: {
id: { type: "number" },
name: {
type: "string",
example: "Admin"
},
description: {
type: "string",
example: "Admin role description"
},
permissions: {
type: "array",
example: [
{
id: 1,
permission: "create_role"
},
{
id: 2,
permission: "update_role"
}
],
items: {
type: "object",
properties: {
id: {
type: "number"
},
permission: {
type: "string"
}
}
}
},
createdAt: {
type: "string",
example: "2021-06-10T20:00:00.000Z"
},
updatedAt: {
type: "string",
example: "2021-06-10T20:00:00.000Z"
}
}
};
};
// src/libs/formatters/settings.ts
var SettingsFormatter = class {
formatSingle = (props) => {
return {
email: {
enabled: props.config.email !== void 0,
from: props.config.email?.from ?? null
},
media: {
enabled: props.config.media?.strategy !== void 0,
storage: {
total: props.config.media.storage,
remaining: props.config.media.storage - props.settings.mediaStorageUsed,
used: props.settings.mediaStorageUsed,
limit: props.config.media.storage
},
processed: {
stored: props.config.media.processed.store,
imageLimit: props.config.media.processed.limit,
total: props.settings.processedImageCount
}
}
};
};
static swagger = {
type: "object",
properties: {
email: {
type: "object",
properties: {
enabled: { type: "boolean" },
from: {
type: "object",
nullable: true,
properties: {
email: { type: "string" },
name: { type: "string" }
}
}
}
},
media: {
type: "object",
properties: {
enabled: { type: "boolean" },
storage: {
type: "object",
properties: {
total: { type: "number" },
remaining: { type: "number", nullable: true },
used: { type: "number", nullable: true },
limit: { type: "number", nullable: true }
}
},
processed: {
type: "object",
properties: {
stored: { type: "boolean" },
imageLimit: { type: "number" },
total: { type: "number", nullable: true }
}
}
}
}
}
};
};
// src/libs/formatters/permissions.ts
var PermissionsFormatter = class {
formatMultiple = (props) => {
return Object.values(props.permissions);
};
static swagger = {
type: "object",
properties: {
key: {
type: "string",
example: "users_permissions"
},
permissions: {
type: "array",
example: ["create_user", "update_user", "delete_user"]
}
}
};
};
// src/libs/formatters/options.ts
var OptionsFormatter = class {
formatSingle = (props) => {
return {
name: props.option.name,
valueText: props.option.value_text,
valueInt: props.option.value_int,
valueBool: props.option.value_bool
};
};
};
// src/libs/formatters/media.ts
var MediaFormatter = class {
formatMultiple = (props) => {
return props.media.map(
(m) => this.formatSingle({
media: m,
host: props.host
})
);
};
formatSingle = (props) => {
return {
id: props.media.id,
key: props.media.key,
url: create_cdn_url_default(props.host, props.media.key),
title: props.media.title_translations?.map((t) => ({
value: t.value,
localeCode: t.locale_code
})) ?? [],
alt: props.media.alt_translations?.map((t) => ({
value: t.value,
localeCode: t.locale_code
})) ?? [],
type: props.media.type,
meta: {
mimeType: props.media.mime_type,
extension: props.media.file_extension,
fileSize: props.media.file_size,
width: props.media.width,
height: props.media.height,
blurHash: props.media.blur_hash,
averageColour: props.media.average_colour,
isDark: props.media.is_dark,
isLight: props.media.is_light
},
createdAt: formatters_default.formatDate(props.media.created_at),
updatedAt: formatters_default.formatDate(props.media.updated_at)
};
};
static swagger = {
type: "object",
properties: {
id: { type: "number", example: 1 },
key: { type: "string", example: "placeholder-1708786317482" },
url: { type: "string", example: "https://example.com/cdn/v1/key" },
title: {
type: "array",
items: {
type: "object",
properties: {
localeCode: { type: "string", example: "en" },
value: { type: "string" }
}
}
},
alt: {
type: "array",
items: {
type: "object",
properties: {
localeCode: { type: "string", example: "en" },
value: {
type: "string"
}
}
}
},
type: { type: "string", example: "image" },
meta: {
type: "object",
properties: {
mimeType: { type: "string", example: "image/jpeg" },
extension: { type: "string", example: "jpeg" },
fileSize: { type: "number", example: 100 },
width: { type: "number", example: 100, nullable: true },
height: { type: "number", example: 100, nullable: true },
blurHash: {
type: "string",
example: "AQABAAAABAAAAgAA...",
nullable: true
},
averageColour: {
type: "string",
example: "rgba(255, 255, 255, 1)",
nullable: true
},
isDark: {
type: "number",
example: 1,
nullable: true
},
isLight: {
type: "number",
example: 1,
nullable: true
}
}
},
createdAt: { type: "string", example: "2022-01-01T00:00:00Z" },
updatedAt: { type: "string", example: "2022-01-01T00:00:00Z" }
}
};
static presignedUrlSwagger = {
type: "object",
properties: {
url: {
type: "string",
example: "https://example.com/cdn/v1/key"
},
key: {
type: "string",
example: "2024/09/5ttogd-placeholder-image.png"
}
}
};
};
// src/libs/formatters/locales.ts
var LocalesFormatter = class {
formatMultiple = (props) => {
return props.locales.map((l) => {
const configLocale = props.localisation.locales.find(
(locale) => locale.code === l.code
);
if (!configLocale) {
return null;
}
return this.formatSingle({
locale: l,
configLocale,
defaultLocale: props.localisation.defaultLocale
});
}).filter((l) => l !== null);
};
formatSingle = (props) => {
return {
code: props.locale.code,
name: props.configLocale.label,
isDefault: props.locale.code === props.defaultLocale ? 1 : 0,
createdAt: formatters_default.formatDate(props.locale.created_at),
updatedAt: formatters_default.formatDate(props.locale.updated_at)
};
};
static swagger = {
type: "object",
properties: {
code: { type: "string", example: "en" },
name: { type: "string", example: "English" },
isDefault: { type: "number", example: 1 },
createdAt: { type: "string", example: "2021-10-05T14:48:00.000Z" },
updatedAt: { type: "string", example: "2021-10-05T14:48:00.000Z" }
}
};
};
// src/libs/formatters/emails.ts
var EmailsFormatter = class {
formatMultiple = (props) => {
return props.emails.map(
(e) => this.formatSingle({
email: e
})
);
};
formatSingle = (props) => {
return {
id: props.email.id,
emailHash: props.email.email_hash,
type: props.email.type,
deliveryStatus: props.email.delivery_status,
mailDetails: {
from: {
address: props.email.from_address,
name: props.email.from_name
},
to: props.email.to_address,
subject: props.email.subject,
cc: props.email.cc,
bcc: props.email.bcc,
template: props.email.template
},
data: props.email.data ?? null,
sentCount: props.email.sent_count || 0,
errorCount: props.email.error_count || 0,
errorMessage: props.email.last_error_message,
html: props.html ?? null,
lastSuccessAt: formatters_default.formatDate(props.email.last_success_at),
lastAttemptAt: formatters_default.formatDate(props.email.last_attempt_at),
createdAt: formatters_default.formatDate(props.email.created_at)
};
};
static swagger = {
type: "object",
properties: {
id: {
type: "number"
},
emailHash: {
type: "string"
},
type: {
type: "string",
enum: ["external", "internal"]
},
deliveryStatus: {
type: "string",
enum: ["sent", "failed", "pending"]
},
mailDetails: {
type: "object",
properties: {
from: {
type: "object",
properties: {
address: {
type: "string"
},
name: {
type: "string"
}
}
},
to: {
type: "string"
},
subject: {
type: "string"
},
cc: {
type: "string",
nullable: true
},
bcc: {
type: "string",
nullable: true
},
template: {
type: "string"
}
}
},
data: {
type: "object",
nullable: true,
additionalProperties: true
},
sentCount: {
type: "number"
},
errorCount: {
type: "number"
},
errorMessage: {
type: "string",
nullable: true
},
html: {
type: "string",
nullable: true
},
lastSuccessAt: {
type: "string",
nullable: true
},
lastAttemptAt: {
type: "string",
nullable: true
},
createdAt: {
type: "string",
nullable: true
}
}
};
};
// src/libs/formatters/collections.ts
import "zod";
var CollectionsFormatter = class {
formatMultiple = (props) => {
return props.collections.map(
(c) => this.formatSingle({
collection: c,
include: props.include,
documents: props.documents
})
);
};
formatSingle = (props) => {
const collectionData = props.collection.getData;
const key = props.collection.key;
return {
key,
mode: collectionData.mode,
documentId: props.include?.document_id ? this.getDocumentId(key, props.documents) : void 0,
details: {
name: collectionData.details.name,
singularName: collectionData.details.singularName,
summary: collectionData.details.summary
},
config: {
useTranslations: collectionData.config.useTranslations,
useDrafts: collectionData.config.useDrafts,
useRevisions: collectionData.config.useRevisions,
isLocked: collectionData.config.isLocked,
fieldIncludes: props.collection.includeFieldKeys,
fieldFilters: props.collection.filterableFieldKeys.map((f) => f.key)
},
fixedBricks: props.include?.bricks ? props.collection.fixedBricks ?? [] : [],
builderBricks: props.include?.bricks ? props.collection.builderBricks ?? [] : [],
fields: props.include?.fields ? props.collection.fieldTree ?? [] : []
};
};
getDocumentId = (collectionKey, documents) => {
const document = documents?.find(
(document2) => document2.collection_key === collectionKey
);
return document?.id ?? void 0;
};
static swaggerFieldsConfig = {
type: "object",
additionalProperties: true,
properties: {
type: {
type: "string"
},
key: {
type: "string"
},
collection: {
type: "string",
nullable: true
},
details: {
type: "object",
additionalProperties: true,
properties: {
label: {
type: ["object", "string"],
additionalProperties: true
},
summary: {
type: ["object", "string"],
additionalProperties: true
},
placeholder: {
type: ["object", "string"],
additionalProperties: true
},
true: {
type: ["object", "string"],
additionalProperties: true
},
false: {
type: ["object", "string"],
additionalProperties: true
}
}
},
config: {
type: "object",
additionalProperties: true,
properties: {
isHidden: {
type: "boolean",
nullable: true
},
isDisabled: {
type: "boolean",
nullable: true
},
useTranslations: {
type: "boolean",
nullable: true
}
}
},
fields: {
type: "array",
items: {
type: "object",
additionalProperties: true
}
}
}
};
static swaggerBricksConfig = {
type: "object",
additionalProperties: true,
properties: {
key: {
type: "string"
},
details: {
type: "object",
properties: {
name: {
type: ["object", "string"],
additionalProperties: true
},
summary: {
type: ["object", "string"],
additionalProperties: true,
nullable: true
}
}
},
preview: {
type: "object",
additionalProperties: true,
properties: {
image: {
type: "string"
}
}
},
fields: {
type: "array",
items: this.swaggerFieldsConfig
}
}
};
static swagger = {
type: "object",
properties: {
key: { type: "string", example: "pages" },
mode: { type: "string", example: "single" },
documentId: { type: "number", example: 1, nullable: true },
details: {
type: "object",
properties: {
name: {
type: ["object", "string"],
additionalProperties: true
},
singularName: {
type: ["object", "string"],
additionalProperties: true
},
summary: {
type: ["object", "string"],
additionalProperties: true,
nullable: true
}
}
},
config: {
type: "object",
properties: {
useTranslations: { type: "boolean", example: false },
useDrafts: {
type: "boolean",
nullable: true
},
useRevisions: {
type: "boolean",
nullable: true
},
isLocked: {
type: "boolean",
nullable: true
},
fieldIncludes: {
type: "array",
items: {
type: "string"
}
},
fieldFilters: {
type: "array",
items: {
type: "string"
}
}
}
},
fixedBricks: {
type: "array",
items: this.swaggerBricksConfig
},
builderBricks: {
type: "array",
items: this.swaggerBricksConfig
},
fields: {
type: "array",
items: this.swaggerFieldsConfig
}
}
};
};
// src/libs/formatters/collection-document-fields.ts
var CollectionDocumentFieldsFormatter = class {
formatMultiple = (data, meta) => {
const fieldConfigTree = meta.builder.fieldTreeNoTab;
const sortedGroups = data.groups.sort(
(a, b) => a.group_order - b.group_order
);
return this.buildFieldTree(
{
fields: data.fields,
groups: sortedGroups
},
{
builder: meta.builder,
fieldConfig: fieldConfigTree,
host: meta.host,
localisation: meta.localisation,
collectionTranslations: meta.collectionTranslations,
groupId: null,
parentGroupId: null,
collections: meta.collections
}
);
};
formatMultipleFlat = (data, meta) => {
if (data.fields.length === 0) return [];
const fieldsRes = [];
const flatFields = meta.builder.flatFields;
for (const fieldConfig of flatFields) {
const fieldData = data.fields.filter((f) => f.key === fieldConfig.key).filter((f) => {
if (f.type === "repeater") return false;
if (f.type === "tab") return false;
return true;
});
if (fieldData.length === 0) continue;
const field = this.buildField(
{
fields: fieldData
},
{
builder: meta.builder,
fieldConfig,
host: meta.host,
includeGroupId: true,
collectionTranslations: meta.collectionTranslations,
localisation: meta.localisation,
collections: meta.collections
}
);
if (field) fieldsRes.push(field);
}
return fieldsRes;
};
// Helpers
objectifyFields = (fields) => {
return fields.reduce(
(acc, field) => {
if (!field) return acc;
acc[field.key] = {
...field,
groups: field.groups?.map((g) => {
return {
...g,
fields: this.objectifyFields(g.fields || [])
};
})
};
return acc;
},
{}
);
};
// Private methods
buildFieldTree = (data, meta) => {
const fieldsRes = [];
for (const config of meta.fieldConfig) {
if (config.type === "repeater") {
fieldsRes.push({
key: config.key,
type: config.type,
groups: this.buildGroups(
{
fields: data.fields,
groups: data.groups
},
{
builder: meta.builder,
repeaterConfig: config,
host: meta.host,
parentGroupId: meta.groupId,
localisation: meta.localisation,
collectionTranslations: meta.collectionTranslations,
collections: meta.collections
}
)
});
continue;
}
const fields = data.fields.filter(
(f) => f.key === config.key && f.group_id === meta.groupId
);
if (!fields) continue;
if (fields.length === 0) continue;
const field = this.buildField(
{
fields
},
{
builder: meta.builder,
fieldConfig: config,
host: meta.host,
includeGroupId: true,
localisation: meta.localisation,
collectionTranslations: meta.collectionTranslations,
collections: meta.collections
}
);
if (field) fieldsRes.push(field);
}
return fieldsRes;
};
buildField = (data, meta) => {
if (meta.fieldConfig.type !== "repeater" && meta.fieldConfig.type !== "tab" && meta.fieldConfig.config.useTranslations === true && meta.collectionTranslations === true) {
return this.addEmptyLocales(
{ field: this.reduceFieldLocales(data, meta) },
{
fieldConfig: meta.fieldConfig,
host: meta.host,
localisation: meta.localisation
}
);
}
const defaultField = data.fields.find(
(f) => f.locale_code === meta.localisation.default
);
if (!defaultField) return null;
const cfInstance = meta.builder.fields.get(meta.fieldConfig.key);
if (!cfInstance) return null;
return {
key: meta.fieldConfig.key,
type: meta.fieldConfig.type,
groupId: meta.includeGroupId ? defaultField.group_id ?? void 0 : void 0,
...cfInstance.responseValueFormat({
data: defaultField,
formatMeta: meta
})
};
};
buildGroups = (data, meta) => {
const groups = [];
const repeaterFields = meta.repeaterConfig.fields;
if (!repeaterFields) return groups;
const repeaterGroups = data.groups.filter(
(g) => g.repeater_key === meta.repeaterConfig.key && g.parent_group_id === meta.parentGroupId
);
for (const group of repeaterGroups) {
groups.push({
id: group.group_id,
order: group.group_order,
open: group.group_open,
fields: this.buildFieldTree(
{
fields: data.fields,
groups: data.groups
},
{
builder: meta.builder,
fieldConfig: repeaterFields,
host: meta.host,
groupId: group.group_id,
parentGroupId: group.parent_group_id,
collectionTranslations: meta.collectionTranslations,
localisation: meta.localisation,
collections: meta.collections
}
)
});
}
return groups;
};
reduceFieldLocales = (data, meta) => {
return data.fields.reduce(
(acc, field) => {
const cfInstance = meta.builder.fields.get(meta.fieldConfig.key);
if (!cfInstance) return acc;
if (acc.translations === void 0) acc.translations = {};
if (acc.meta === void 0 || acc.meta === null) acc.meta = {};
if (meta.includeGroupId) acc.groupId = field.group_id ?? void 0;
const fieldRes = cfInstance.responseValueFormat({
data: field,
formatMeta: meta
});
acc.translations[field.locale_code] = fieldRes.value;
acc.meta[field.locale_code] = fieldRes.meta;
return acc;
},
{
key: meta.fieldConfig.key,
type: meta.fieldConfig.type
}
);
};
addEmptyLocales = (data, meta) => {
if (data.field.translations === void 0) data.field.translations = {};
if (data.field.meta === void 0) data.field.meta = {};
const emptyLocales = meta.localisation.locales.filter(
(l) => !data.field.translations[l]
);
for (const locale of emptyLocales) {
data.field.translations[locale] = meta.fieldConfig.config.default ?? null;
data.field.meta[locale] = null;
}
return data.field;
};
static swagger = {
type: "object",
additionalProperties: true,
properties: {
key: {
type: "string"
},
type: {
type: "string",
enum: [
"tab",
"text",
"wysiwyg",
"media",
"number",
"checkbox",
"select",
"textarea",
"json",
"colour",
"datetime",
"link",
"repeater",
"user"
]
},
groupId: {
type: "number",
nullable: true
},
collectionDocumentId: {
type: "number"
},
translations: {
type: "object",
additionalProperties: true
},
value: {},
meta: {
type: "object",
additionalProperties: true,
nullable: true,
properties: {
id: {
type: "number",
nullable: true
},
url: {
type: "string",
nullable: true
},
key: {
type: "string",
nullable: true
},
mimeType: {
type: "string",
nullable: true
},
extension: {
type: "string",
nullable: true
},
fileSize: {
type: "number",
nullable: true
},
width: {
type: "number",
nullable: true
},
height: {
type: "number",
nullable: true
},
blurHash: {
type: "string",
nullable: true
},
averageColour: {
type: "string",
nullable: true
},
isDark: {
type: "number",
nullable: true
},
isLight: {
type: "number",
nullable: true
},
title: {
type: "object",
additionalProperties: true
},
alt: {
type: "object",
additionalProperties: true
},
type: {
type: "string",
nullable: true,
enum: ["image", "video", "audio", "document"]
},
email: {
type: "string",
nullable: true
},
username: {
type: "string",
nullable: true
},
firstName: {
type: "string",
nullable: true
},
lastName: {
type: "string",
nullable: true
},
fields: {
type: "object",
additionalProperties: true,
nullable: true
}
}
},
groups: {
type: "array",
items: {
type: "object",
additionalProperties: true,
properties: {
id: {
type: "number"
},
order: {
type: "number"
},
open: {
type: "number",
nullable: true
},
fields: {
type: "array",
items: {
type: "object",
additionalProperties: true
}
}
}
}
}
}
};
};
// src/libs/formatters/collection-document-bricks.ts
var CollectionDocumentBricksFormatter = class {
formatMultiple = (props) => {
const CollectionDocumentFieldsFormatter2 = formatters_default.get(
"collection-document-fields"
);
return props.bricks.filter((brick) => {
if (brick.brick_type === constants_default.brickTypes.collectionFields)
return false;
const builder = props.collection.brickInstances.find((b) => {
return b.key === brick.brick_key;
});
if (!builder) return false;
return true;
}).map((brick) => {
const builder = props.collection.brickInstances.find((b) => {
return b.key === brick.brick_key;
});
return {
id: brick.id,
key: brick.brick_key,
order: brick.brick_order,
type: brick.brick_type,
open: brick.brick_open,
fields: CollectionDocumentFieldsFormatter2.formatMultiple(
{
fields: brick.fields,
groups: brick.groups
},
{
host: props.config.host,
builder,
localisation: {
locales: props.config.localisation.locales.map((l) => l.code),
default: props.config.localisation.defaultLocale
},
collectionTranslations: props.collection.getData.config.useTranslations,
collections: props.config.collections
}
)
};
});
};
formatCollectionPseudoBrick = (props) => {
const CollectionDocumentFieldsFormatter2 = formatters_default.get(
"collection-document-fields"
);
return props.bricks.filter((brick) => {
if (brick.brick_type !== constants_default.brickTypes.collectionFields)
return false;
return true;
}).flatMap(
(brick) => CollectionDocumentFieldsFormatter2.formatMultiple(
{
fields: brick.fields,
groups: brick.groups
},
{
host: props.config.host,
builder: props.collection,
collectionTranslations: props.collection.getData.config.useTranslations,
localisation: {
locales: props.config.localisation.locales.map((l) => l.code),
default: props.config.localisation.defaultLocale
},
collections: props.config.collections
}
)
);
};
static swagger = {
type: "object",
additionalProperties: true,
properties: {
id: {
type: "number"
},
key: {
type: "string"
},
order: {
type: "number"
},
open: {
type: "number",
nullable: true
},
type: {
type: "string",
enum: ["builder", "fixed"]
},
fields: {
type: "array",
items: CollectionDocumentFieldsFormatter.swagger
}
}
};
};
// src/libs/formatters/collection-documents.ts
var CollectionDocumentsFormatter = class _CollectionDocumentsFormatter {
formatMultiple = (props) => {
return props.documents.map(
(d) => this.formatSingle({
document: d,
collection: props.collection,
config: props.config
})
);
};
formatSingle = (props) => {
let fields = props.fields ?? null;
const FieldsFormatter = formatters_default.get("collection-document-fields");
if (fields === null && props.document.fields) {
if (props.document.groups) {
fields = FieldsFormatter.formatMultiple(
{
fields: props.document.fields,
groups: props.document.groups
},
{
host: props.config.host,
builder: props.collection,
collectionTranslations: props.collection.getData.config.useTranslations,
localisation: {
locales: props.config.localisation.locales.map((l) => l.code),
default: props.config.localisation.defaultLocale
},
collections: props.config.collections
}
);
} else {
fields = FieldsFormatter.formatMultipleFlat(
{
fields: props.document.fields
},
{
host: props.config.host,
builder: props.collection,
collectionTranslations: props.collection.getData.config.useTranslations,
localisation: {
locales: props.config.localisation.locales.map((l) => l.code),
default: props.config.localisation.defaultLocale
},
collections: props.config.collections
}
);
}
}
return {
id: props.document.id,
collectionKey: props.document.collection_key,
status: props.document.version_type ?? null,
versionId: props.document.version_id ?? null,
version: this.formatVersion({
document: props.document
}),
bricks: props.bricks ?? null,
fields,
createdBy: props.document.cb_user_id ? {
id: props.document.cb_user_id,
email: props.document.cb_user_email ?? null,
firstName: props.document.cb_user_first_name ?? null,
lastName: props.document.cb_user_last_name ?? null,
username: props.document.cb_user_username ?? null
} : null,
updatedBy: props.document.ub_user_id ? {
id: props.document.ub_user_id,
email: props.document.ub_user_email ?? null,
firstName: props.document.ub_user_first_name ?? null,
lastName: props.document.ub_user_last_name ?? null,
username: props.document.ub_user_username ?? null
} : null,
createdAt: formatters_default.formatDate(props.document.created_at),
updatedAt: formatters_default.formatDate(props.document.updated_at)
};
};
formatVersion = (props) => {
const draftVersion = props.document.versions?.find(
(v) => v.version_type === "draft"
);
const publishedVersion = props.document.versions?.find(
(v) => v.version_type === "published"
);
return {
draft: draftVersion?.id ? {
id: draftVersion.id,
promotedFrom: draftVersion.promoted_from,
createdAt: formatters_default.formatDate(draftVersion.created_at),
createdBy: draftVersion.created_by
} : null,
published: publishedVersion?.id ? {
id: publishedVersion.id,
promotedFrom: publishedVersion.promoted_from,
createdAt: formatters_default.formatDate(publishedVersion.created_at),
createdBy: publishedVersion.created_by
} : null
};
};
// Client
formatClientMultiple = (props) => {
return props.documents.map(
(d) => this.formatClientSingle({
document: d,
collection: props.collection,
config: props.config
})
);
};
formatClientSingle = (props) => {
const FieldsFormatter = formatters_default.get("collection-document-fields");
const res = this.formatSingle({
document: props.document,
collection: props.collection,
bricks: props.bricks,
fields: props.fields,
config: props.config
});
return {
...res,
bricks: res.bricks !== null ? res.bricks.map((b) => {
return {
...b,
fields: FieldsFormatter.objectifyFields(b.fields)
};
}) : null,
fields: res.fields !== null ? FieldsFormatter.objectifyFields(res.fields) : null
};
};
static swagger = {
type: "object",
properties: {
id: {
type: "number"
},
versionId: {
type: "number",
nullable: true
},
collectionKey: {
type: "string",
nullable: true
},
status: {
type: "string",
nullable: true,
enum: ["published", "draft", "revision"]
},
version: {
type: "object",
properties: {
draft: {
type: "object",
properties: {
id: {
type: "number",
nullable: true
},
promotedFrom: {
type: "number",
nullable: true
},
createdAt: {
type: "string",
nullable: true
},
createdBy: {
type: "number",
nullable: true
}
},
nullable: true
},
published: {
type: "object",
properties: {
id: {
type: "number",
nullable: true
},
promotedFrom: {
type: "number",
nullable: true
},
createdAt: {
type: "string",
nullable: true
},
createdBy: {
type: "number",
nullable: true
}
},
nullable: true
}
}
},
bricks: {
type: "array",
items: CollectionDocumentBricksFormatter.swagger,
nullable: true
},
fields: {
type: "array",
nullable: true,
items: CollectionDocumentFieldsFormatter.swagger
},
createdBy: {
type: "object",
nullable: true,
properties: {
id: {
type: "number"
},
email: {
type: "string",
nullable: true
},
firstName: {
type: "string",
nullable: true
},
lastName: {
type: "string",
nullable: true
},
username: {
type: "string",
nullable: true
}
}
},
createdAt: {
type: "string",
nullable: true
},
updatedAt: {
type: "string",
nullable: true
},
updatedBy: {
type: "object",
nullable: true,
properties: {
id: {
type: "number"
},
email: {
type: "string",
nullable: true
},
firstName: {
type: "string",
nullable: true
},
lastName: {
type: "string",
nullable: true
},
username: {
type: "string",
nullable: true
}
}
}
}
};
static swaggerClient = {
type: "object",
properties: {
..._CollectionDocumentsFormatter.swagger.properties,
bricks: {
type: "array",
nullable: true,
items: {
type: "object",
additionalProperties: true,
properties: {
...CollectionDocumentBricksFormatter.swagger.properties,
fields: {
type: "object",
additionalProperties: true
}
}
}
},
fields: {
type: "object",
nullable: true,
additionalProperties: true
}
}
};
};
// src/libs/formatters/collection-document-versions.ts
var CollectionDocumentVersions = class {
formatMultiple = (props) => {
return props.versions.map(
(v) => this.formatSingle({
version: v
})
);
};
formatSingle = (props) => {
return {
id: props.version.id,
versionType: props.version.version_type,
promotedFrom: props.version.promoted_from ?? null,
createdAt: formatters_default.formatDate(props.version.created_at),
createdBy: props.version.created_by ?? null,
document: {
id: props.version.document_id ?? null,
collectionKey: props.version.collection_key,
createdBy: props.version.document_created_by ?? null,
createdAt: formatters_default.formatDate(props.version.document_created_at),
updatedAt: formatters_default.formatDate(props.version.document_updated_at),
updatedBy: props.version.document_updated_by ?? null
},
bricks: props.version.bricks.reduce(
(acc, brick) => {
if (!acc[brick.brick_type]) {
acc[brick.brick_type] = [];
}
acc[brick.brick_type].push({
id: brick.id,
brickKey: brick.brick_key,
fields: typeof brick.field_count === "number" ? brick.field_count : 0
});
return acc;
},
{}
)
};
};
static swagger = {
type: "object",
properties: {
id: {
type: "number"
},
versionType: {
type: "string",
nullable: true,
enum: ["published", "draft", "revision"]
},
promotedFrom: {
type: "number",
nullable: true
},
createdAt: {
type: "string",
nullable: true
},
createdBy: {
type: "number",
nullable: true
},
bricks: {
type: "object",
nullable: true,
additionalProperties: {
type: "array",
items: {
type: "object",
properties: {
id: {
type: "number"
},
brickKey: {
type: "string",
nullable: true
},
fields: {
type: "number"
}
}
}
}
},
document: {
type: "object",
nullable: true,
properties: {
id: {
type: "number"
},
collectionKey: {
type: "string",
nullable: true
},
createdBy: {
type: "number",
nullable: true
},
createdAt: {
type: "string",
nullable: true
},
updatedAt: {
type: "string",
nullable: true
},
updatedBy: {
type: "number",
nullable: true
}
}
}
}
};
};
// src/libs/formatters/client-integrations.ts
var ClientIntegrationsFormatter = class {
formatMultiple = (props) => {
return props.integrations.map(
(i) => this.formatSingle({
integration: i
})
);
};
formatSingle = (props) => {
return {
id: props.integration.id,
key: props.integration.key,
name: props.integration.name,
description: props.integration.description,
enabled: props.integration.enabled,
createdAt: formatters_default.formatDate(props.integration.created_at),
updatedAt: formatters_default.formatDate(props.integration.updated_at)
};
};
static swagger = {
type: "object",
additionalProperties: true,
properties: {
id: {
type: "number"
},
key: {
type: "string"
},
name: {
type: "string"
},
description: {
type: "string"
},
enabled: {
type: "number"
},
createdAt: {
type: "string"
},
updatedAt: {
type: "string"
}
}
};
};
// src/libs/formatters/index.ts
var Formatter = class {
static get(format) {
switch (format) {
case "users":
return new UsersFormatter();
case "user-permissions":
return new UserPermissionsFormatter();
case "settings":
return new SettingsFormatter();
case "roles":
return new RolesFormatter();
case "permissions":
return new PermissionsFormatter();
case "options":
return new OptionsFormatter();
case "media":
return new MediaFormatter();
case "locales":
return new LocalesFormatter();
case "emails":
return new EmailsFormatter();
case "collections":
return new CollectionsFormatter();
case "collection-documents":
return new CollectionDocumentsFormatter();
case "collection-document-bricks":
return new CollectionDocumentBricksFormatter();
case "collection-document-fields":
return new CollectionDocumentFieldsFormatter();
case "collection-document-versions":
return new CollectionDocumentVersions();
case "client-integrations":
return new ClientIntegrationsFormatter();
default:
throw new lucid_error_default({
message: translations_default("cannot_find_formatter", {
name: format
})
});
}
}
// helpers
static formatDate = (date) => {
if (typeof date === "string") {
return date;
}
return date ? date.toISOString() : null;
};
static parseJSON = (json) => {
if (typeof json === "object") return json;
if (!json) return null;
try {
return JSON.parse(json);
} catch (error) {
return null;
}
};
static stringifyJSON = (json) => {
try {
if (!json) return null;
return JSON.stringify(json);
} catch (error) {
return null;
}
};
static parseCount = (count) => {
return Number.parseInt(count || "0") || 0;
};
};
var formatters_default = Formatter;
// src/utils/translations/objectify-translations.ts
var objectifyTranslations = (values, locales) => {
return locales.reduce((acc, locale) => {
const value = values.find((v) => v.locale_code === locale);
if (!value) {
acc[locale] = "";
} else {
acc[locale] = value.value ?? "";
}
return acc;
}, {});
};
var objectify_translations_default = objectifyTranslations;
// src/utils/translations/remove-duplicates.ts
var removeDuplicates = (translations) => translations.filter(
(translation, index, self) => index === self.findIndex((t) => t.localeCode === translation.localeCode)
);
var remove_duplicates_default = removeDuplicates;
// src/utils/translations/merge-translation-groups.ts
var mergeTranslationGroups = (items) => {
const translations = [];
for (const item of items) {
const itemTranslations = remove_duplicates_default(item.translations);
for (const translation of itemTranslations) {
translations.push({
...translation,
key: item.key
});
}
}
return translations;
};
var merge_translation_groups_default = mergeTranslationGroups;
// src/utils/translations/get-unique-locale-codes.ts
var getUniqueLocaleCodes = (items) => {
const localeCodes = items.flatMap((t) => t.map((t2) => t2.localeCode));
return Array.from(new Set(localeCodes));
};
var get_unique_locale_codes_default = getUniqueLocaleCodes;
// src/utils/translations/should-update-translations.ts
var shouldUpdateTranslations = (item) => item.some((t) => t !== void 0 && t.length > 0);
var should_update_translations_default = shouldUpdateTranslations;
export {
UsersFormatter,
RolesFormatter,
SettingsFormatter,
PermissionsFormatter,
choose_accept_header_format_default,
generate_process_key_default,
create_cdn_url_default,
MediaFormatter,
LocalesFormatter,
EmailsFormatter,
CollectionsFormatter,
CollectionDocumentsFormatter,
CollectionDocumentVersions,
ClientIntegrationsFormatter,
formatters_default,
merge_translation_groups_default,
get_unique_locale_codes_default,
should_update_translations_default,
objectify_translations_default
};
//# sourceMappingURL=chunk-URI3PAN7.js.map