@lucidcms/plugin-pages
Version:
The official Pages plugin for Lucid
1,015 lines (987 loc) • 38 kB
JavaScript
import { logger, z } from "@lucidcms/core";
import { prefixGeneratedColName } from "@lucidcms/core/helpers";
import { inspect } from "node:util";
//#region src/translations/en-gb.json
var cannot_find_collection = "Cannot find the collection of {{collection}}.";
var cannot_find_required_field_message = "Cannot find required fields for the pages plugin.";
var cannot_have_self_as_parent_page_message = "A page cannot be its own parent, please select a different parent page.";
var slug_cannot_be_slash_and_parent_page_set_message = "The slug cannot be / when a parent page is set.";
var duplicate_slug_field_found_message = "Please ensure the slug field is unique within the collection.";
var duplicate_slug_and_parent_page_field_found_message = "Another document in this collection has the same slug and parent page selected. Please ensure the slug field is unique within the collection.";
var an_unknown_error_occurred_checking_for_duplicate_slugs = "An error occurred while checking for duplicate slugs.";
var an_unknown_error_occurred_checking_for_circular_parents = "An error occurred while checking for circular parents.";
var circular_parents_error_message = "The selected page is either a child/grandchild of this one. Please select a different parent page.";
var parent_page_not_found_or_doesnt_have_a_published_version = "The parent page document of the same version (draft/published) was not found, or doesnt have a slug.";
var an_unknown_error_occurred_getting_parent_fields = "An error occurred while getting the parent page fields.";
var an_unknown_error_occurred_getting_descendant_fields = "An error occurred while getting the descendant page fields.";
var an_unknown_error_occurred_updating_fullslug_fields = "An error occurred while updating the fullSlug children fields.";
var slug_field_validation_error_message = "The slug field may only contain letters, numbers, underscores, and hyphens.";
var an_unknown_error_occurred_getting_document_version_fields = "An error occurred while getting the document version fields.";
var full_slug = "Full Slug";
var slug = "Slug";
var parent_page = "Parent Page";
var field_required = "This field is required.";
var en_gb_default = {
cannot_find_collection,
cannot_find_required_field_message,
cannot_have_self_as_parent_page_message,
slug_cannot_be_slash_and_parent_page_set_message,
duplicate_slug_field_found_message,
duplicate_slug_and_parent_page_field_found_message,
an_unknown_error_occurred_checking_for_duplicate_slugs,
an_unknown_error_occurred_checking_for_circular_parents,
circular_parents_error_message,
parent_page_not_found_or_doesnt_have_a_published_version,
an_unknown_error_occurred_getting_parent_fields,
an_unknown_error_occurred_getting_descendant_fields,
an_unknown_error_occurred_updating_fullslug_fields,
slug_field_validation_error_message,
an_unknown_error_occurred_getting_document_version_fields,
full_slug,
slug,
parent_page,
field_required
};
//#endregion
//#region src/translations/index.ts
const selectedLang = en_gb_default;
const T = (key, data) => {
const translation = selectedLang[key];
if (!translation) return key;
if (!data) return translation;
return translation.replace(/\{\{(\w+)\}\}/g, (_, p1) => data[p1]);
};
var translations_default = T;
//#endregion
//#region src/constants.ts
const PLUGIN_KEY = "plugin-pages";
const LUCID_VERSION = "0.x.x";
var constants_default = {
collectionFieldBrickId: "collection-pseudo-brick",
fields: {
parentPage: { key: "parentPage" },
slug: { key: "slug" },
fullSlug: { key: "fullSlug" }
}
};
//#endregion
//#region src/services/register-fields.ts
const registerFields = (collection, config) => {
collection.addText(constants_default.fields.fullSlug.key, {
details: { label: translations_default("full_slug") },
config: {
useTranslations: config.useTranslations,
isHidden: !config.displayFullSlug,
isDisabled: true
},
displayInListing: config.displayFullSlug
}).addText(constants_default.fields.slug.key, {
details: { label: translations_default("slug") },
config: {
useTranslations: config.useTranslations,
isHidden: false,
isDisabled: false
},
validation: {
required: true,
zod: z.union([z.literal("/"), z.string().regex(/^[a-zA-Z0-9_-]+$/, translations_default("slug_field_validation_error_message"))])
},
displayInListing: true
}).addDocument(constants_default.fields.parentPage.key, {
collection: collection.key,
details: { label: translations_default("parent_page") },
config: {
isHidden: false,
isDisabled: false
}
});
};
var register_fields_default = registerFields;
//#endregion
//#region src/services/plugin-options.ts
const pluginOptions = (given) => {
return { collections: given.collections.map((c) => ({
collectionKey: c.collectionKey,
useTranslations: c?.useTranslations ?? false,
displayFullSlug: c?.displayFullSlug ?? false
})) };
};
var plugin_options_default = pluginOptions;
//#endregion
//#region src/services/get-target-collection.ts
/**
* Fetches the target collection from the plugin options
*/
const getTargetCollection = (data) => {
const targetCollection = data.options.collections.find((c) => c.collectionKey === data.collectionKey);
if (!targetCollection) return {
error: {
type: "basic",
status: 500,
message: translations_default("cannot_find_collection", { collection: data.collectionKey })
},
data: void 0
};
return {
error: void 0,
data: targetCollection
};
};
var get_target_collection_default = getTargetCollection;
//#endregion
//#region src/services/get-parent-fields.ts
/**
* Get the parent document pages fields
*/
const getParentFields = async (context, data) => {
try {
const { version: versionTable, documentFields: fieldsTable } = data.tables;
const slugColumn = prefixGeneratedColName(constants_default.fields.slug.key);
const parentPageColumn = prefixGeneratedColName(constants_default.fields.parentPage.key);
const fullSlugColumn = prefixGeneratedColName(constants_default.fields.fullSlug.key);
const parentFields = await context.db.selectFrom(fieldsTable).innerJoin(versionTable, `${versionTable}.id`, `${fieldsTable}.document_version_id`).select([
`${fieldsTable}.${slugColumn}`,
`${fieldsTable}.${fullSlugColumn}`,
`${fieldsTable}.${parentPageColumn}`,
`${versionTable}.document_id`,
`${fieldsTable}.locale`
]).where(`${versionTable}.document_id`, "=", data.fields.parentPage.value).where(`${versionTable}.type`, "=", data.versionType).execute();
if (!parentFields || parentFields.length === 0) return {
error: {
type: "basic",
status: 404,
message: translations_default("parent_page_not_found_or_doesnt_have_a_published_version"),
errors: { body: { fields: [{
key: constants_default.fields.parentPage.key,
localeCode: data.defaultLocale,
message: translations_default("parent_page_not_found_or_doesnt_have_a_published_version")
}] } }
},
data: void 0
};
return {
error: void 0,
data: parentFields
};
} catch (error) {
return {
error: {
type: "basic",
status: 500,
message: translations_default("an_unknown_error_occurred_getting_parent_fields")
},
data: void 0
};
}
};
var get_parent_fields_default = getParentFields;
//#endregion
//#region src/utils/build-fullslug-from-fullslug.ts
const buildFullSlug = (data) => {
if (data.slug === null || data.slug === void 0) return null;
let result = data.slug;
const targetParentFullSlugField = data.parentFields.find((field) => {
return field.locale === data.targetLocale;
});
if (targetParentFullSlugField?._fullSlug) result = `${targetParentFullSlugField._fullSlug}/${data.slug}`;
if (!result.startsWith("/")) result = `/${result}`;
result = result.replace(/\/\//g, "/");
return result;
};
var build_fullslug_from_fullslug_default = buildFullSlug;
//#endregion
//#region src/services/construct-parent-fullslug.ts
/**
* Constructs the fullSlug from the slug and parentPage fields
*/
const constructParentFullSlug = (data) => {
const fullSlug = data.localisation.locales.reduce((acc, locale) => {
acc[locale.code] = null;
return acc;
}, {});
if (data.collection.useTranslations && data.fields.slug.translations) for (let i = 0; i < data.localisation.locales.length; i++) {
const locale = data.localisation.locales[i];
if (!locale) continue;
fullSlug[locale.code] = build_fullslug_from_fullslug_default({
parentFields: data.parentFields || [],
targetLocale: locale.code,
slug: data.fields.slug.translations[locale.code]
});
}
else fullSlug[data.localisation.defaultLocale] = build_fullslug_from_fullslug_default({
parentFields: data.parentFields || [],
targetLocale: data.localisation.defaultLocale,
slug: data.fields.slug.value
});
return {
error: void 0,
data: fullSlug
};
};
var construct_parent_fullslug_default = constructParentFullSlug;
//#endregion
//#region src/services/set-full-slug.ts
/**
* Update the fullSlug field with the computed value
*/
const setFullSlug = (data) => {
if (data.collection.useTranslations) data.fields.fullSlug.translations = data.fullSlug;
else data.fields.fullSlug.value = data.fullSlug[data.defaultLocale];
return {
error: void 0,
data: void 0
};
};
var set_full_slug_default = setFullSlug;
//#endregion
//#region src/services/get-descendant-fields.ts
/**
* Get the descendant document pages fields
*/
const getDescendantFields = async (context, data) => {
try {
const { documentFields: fieldsTable, version: versionTable } = data.tables;
const slugColumn = prefixGeneratedColName(constants_default.fields.slug.key);
const fullSlugColumn = prefixGeneratedColName(constants_default.fields.fullSlug.key);
const parentPageColumn = prefixGeneratedColName(constants_default.fields.parentPage.key);
const descendants = await context.db.withRecursive("recursive_cte", (db) => db.selectFrom(fieldsTable).innerJoin(versionTable, `${versionTable}.id`, `${fieldsTable}.document_version_id`).select([
`${versionTable}.document_id as document_id`,
`${fieldsTable}.${parentPageColumn} as parent_id`,
`${fieldsTable}.document_version_id`
]).where(({ eb }) => eb(`${fieldsTable}.${parentPageColumn}`, "in", data.ids)).where(`${versionTable}.type`, "=", data.versionType).unionAll(db.selectFrom(fieldsTable).innerJoin(versionTable, `${versionTable}.id`, `${fieldsTable}.document_version_id`).innerJoin("recursive_cte as rc", "rc.document_id", `${fieldsTable}.${parentPageColumn}`).select([
`${versionTable}.document_id as document_id`,
`${fieldsTable}.${parentPageColumn} as parent_id`,
`${fieldsTable}.document_version_id`
]).where(`${versionTable}.type`, "=", data.versionType))).selectFrom("recursive_cte").select((eb) => [
"document_id",
"document_version_id",
context.config.db.jsonArrayFrom(eb.selectFrom(fieldsTable).innerJoin(versionTable, `${versionTable}.id`, `${fieldsTable}.document_version_id`).select([
`${fieldsTable}.locale`,
`${fieldsTable}.${slugColumn} as _slug`,
`${fieldsTable}.${fullSlugColumn} as _fullSlug`,
`${fieldsTable}.${parentPageColumn} as _parentPage`
]).whereRef(`${versionTable}.document_id`, "=", "recursive_cte.document_id").where(`${versionTable}.type`, "=", data.versionType)).as("rows")
]).where(({ eb }) => eb("document_id", "not in", data.ids)).execute();
return {
error: void 0,
data: descendants.filter((d, i, self) => {
return self.findIndex((e) => e.document_id === d.document_id && e.document_version_id === d.document_version_id) === i;
})
};
} catch (error) {
console.log(inspect(error, {
depth: Number.POSITIVE_INFINITY,
colors: true
}));
return {
error: {
type: "basic",
status: 500,
message: translations_default("an_unknown_error_occurred_getting_descendant_fields")
},
data: void 0
};
}
};
var get_descendant_fields_default = getDescendantFields;
//#endregion
//#region src/utils/build-fullslug-from-slugs.ts
const buildFullSlugFromSlugs = (data) => {
const rowForLocale = data.currentDescendant.rows.find((row) => row.locale === data.targetLocale);
if (!rowForLocale || !rowForLocale._slug) return null;
const slugFieldValue = rowForLocale._slug;
const parentPageValue = rowForLocale._parentPage;
if (!parentPageValue) return postSlugFormat(joinSlugs(data.topLevelFullSlug || "", slugFieldValue));
const parentDescendant = data.descendants.find((descendant) => descendant.document_id === parentPageValue);
if (!parentDescendant) return postSlugFormat(joinSlugs(data.topLevelFullSlug || "", slugFieldValue));
const parentFullSlug = buildFullSlugFromSlugs({
targetLocale: data.targetLocale,
currentDescendant: parentDescendant,
descendants: data.descendants,
topLevelFullSlug: data.topLevelFullSlug
});
return postSlugFormat(joinSlugs(parentFullSlug || data.topLevelFullSlug || "", slugFieldValue));
};
const joinSlugs = (...parts) => {
return parts.filter(Boolean).join("/").replace(/\/+/g, "/");
};
const postSlugFormat = (slug$1) => {
if (!slug$1) return null;
let res = slug$1;
if (!res.startsWith("/")) res = `/${res}`;
return res.replace(/\/\//g, "/");
};
var build_fullslug_from_slugs_default = buildFullSlugFromSlugs;
//#endregion
//#region src/services/construct-child-fullslugs.ts
/**
* Constructs the fullSlug for the child documents
*/
const constructChildFullSlug = (data) => {
const documentFullSlugs = [];
for (const descendant of data.descendants) {
const fullSlug = {};
if (data.collection.useTranslations) {
if (data.parentFullSlugField !== void 0 && !data.parentFullSlugField.translations) break;
for (const locale of data.localisation.locales) {
const currentFullSlugValue = data.parentFullSlugField?.translations?.[locale.code];
if (data.parentFullSlugField !== void 0 && !currentFullSlugValue) continue;
fullSlug[locale.code] = build_fullslug_from_slugs_default({
targetLocale: locale.code,
currentDescendant: descendant,
descendants: data.descendants,
topLevelFullSlug: currentFullSlugValue
});
}
} else {
if (data.parentFullSlugField !== void 0 && !data.parentFullSlugField.value) break;
fullSlug[data.localisation.defaultLocale] = build_fullslug_from_slugs_default({
targetLocale: data.localisation.defaultLocale,
currentDescendant: descendant,
descendants: data.descendants,
topLevelFullSlug: data.parentFullSlugField?.value
});
}
documentFullSlugs.push({
documentId: descendant.document_id,
versionId: descendant.document_version_id,
fullSlugs: fullSlug
});
}
return {
error: void 0,
data: documentFullSlugs
};
};
var construct_child_fullslugs_default = constructChildFullSlug;
//#endregion
//#region src/services/update-fullslug-fields.ts
/**
* Update the fullSlug fields with the computed value
*/
const updateFullSlugFields = async (context, data) => {
try {
const { documentFields: fieldsTable, version: versionTable } = data.tables;
const fullSlugColumn = prefixGeneratedColName(constants_default.fields.fullSlug.key);
const updateFullSlugsPromises = [];
for (const doc of data.docFullSlugs) for (const [locale, fullSlug] of Object.entries(doc.fullSlugs)) updateFullSlugsPromises.push(context.db.updateTable(fieldsTable).set({ [fullSlugColumn]: fullSlug }).where((eb) => eb.exists(eb.selectFrom(versionTable).selectAll().where(`${versionTable}.id`, "=", doc.versionId).where(`${versionTable}.document_id`, "=", doc.documentId).where(`${versionTable}.type`, "=", data.versionType))).where("document_version_id", "=", doc.versionId).where("locale", "=", locale).execute());
await Promise.all(updateFullSlugsPromises);
return {
error: void 0,
data: void 0
};
} catch (error) {
return {
error: {
type: "basic",
status: 500,
message: translations_default("an_unknown_error_occurred_updating_fullslug_fields")
},
data: void 0
};
}
};
var update_fullslug_fields_default = updateFullSlugFields;
//#endregion
//#region src/services/get-document-version-fields.ts
/**
* Get the target document versions slug, fullSlug and parentPage fields
*/
const getDocumentVersionFields = async (context, data) => {
try {
const { version: versionTable, documentFields: fieldsTable } = data.tables;
const slugColumn = prefixGeneratedColName(constants_default.fields.slug.key);
const fullSlugColumn = prefixGeneratedColName(constants_default.fields.fullSlug.key);
const parentPageColumn = prefixGeneratedColName(constants_default.fields.parentPage.key);
const fields = await context.db.selectFrom(fieldsTable).innerJoin(versionTable, `${versionTable}.id`, `${fieldsTable}.document_version_id`).select([
`${fieldsTable}.locale`,
`${versionTable}.document_id`,
`${fieldsTable}.${slugColumn}`,
`${fieldsTable}.${fullSlugColumn}`,
`${fieldsTable}.${parentPageColumn}`
]).where(`${versionTable}.document_id`, "=", data.documentId).where(`${versionTable}.id`, "=", data.versionId).where(`${versionTable}.type`, "=", data.versionType).execute();
if (!fields || fields.length === 0) return {
error: void 0,
data: null
};
return {
error: void 0,
data: fields
};
} catch (error) {
return {
error: {
type: "basic",
status: 500,
message: translations_default("an_unknown_error_occurred_getting_document_version_fields")
},
data: void 0
};
}
};
var get_document_version_fields_default = getDocumentVersionFields;
//#endregion
//#region src/services/checks/duplicate-slug-parents.ts
/**
* Query for document fields that have same slug and parentPage for each slug translation (would cause duplicate fullSlug)
*/
const checkDuplicateSlugParents = async (context, data) => {
try {
const { document: documentTable, version: versionTable, documentFields: fieldsTable } = data.tables;
const slugConditions = Object.entries(data.fields.slug.translations || {}).map(([localeCode, slug$1]) => ({
localeCode,
slug: slug$1
}));
if (data.fields.slug.value) slugConditions.push({
localeCode: context.config.localisation.defaultLocale,
slug: data.fields.slug.value
});
const slugColumn = prefixGeneratedColName(constants_default.fields.slug.key);
const parentPageColumn = prefixGeneratedColName(constants_default.fields.parentPage.key);
const duplicates = await context.db.selectFrom(documentTable).leftJoin(versionTable, `${versionTable}.document_id`, `${documentTable}.id`).leftJoin(fieldsTable, `${fieldsTable}.document_version_id`, `${versionTable}.id`).select([
`${documentTable}.id`,
`${documentTable}.collection_key`,
`${fieldsTable}.${slugColumn}`,
`${fieldsTable}.locale`,
`${fieldsTable}.${parentPageColumn}`
]).where(({ eb, and, or }) => and([
or(slugConditions.map(({ localeCode, slug: slug$1 }) => and([eb(`${fieldsTable}.${slugColumn}`, "=", slug$1), localeCode ? eb(`${fieldsTable}.locale`, "=", localeCode) : eb(`${fieldsTable}.locale`, "is", null)]))),
data.fields.parentPage.value ? eb(`${fieldsTable}.${parentPageColumn}`, "=", data.fields.parentPage.value) : eb(`${fieldsTable}.${parentPageColumn}`, "is", null),
eb(`${versionTable}.type`, "=", data.versionType)
])).where(`${documentTable}.id`, "!=", data.documentId || null).where(`${documentTable}.collection_key`, "=", data.collectionKey).where(`${documentTable}.is_deleted`, "=", context.config.db.getDefault("boolean", "false")).execute();
if (duplicates.length > 0) {
const fieldErrors = [];
for (const duplicate of duplicates) fieldErrors.push({
key: constants_default.fields.slug.key,
localeCode: duplicate.locale || void 0,
message: duplicate[parentPageColumn] === null ? translations_default("duplicate_slug_field_found_message") : translations_default("duplicate_slug_and_parent_page_field_found_message")
});
return {
error: {
type: "basic",
status: 400,
message: translations_default("duplicate_slug_field_found_message"),
errors: { body: { fields: fieldErrors } }
},
data: void 0
};
}
return {
error: void 0,
data: void 0
};
} catch (error) {
return {
error: {
type: "basic",
status: 500,
message: translations_default("an_unknown_error_occurred_checking_for_duplicate_slugs")
},
data: void 0
};
}
};
var duplicate_slug_parents_default = checkDuplicateSlugParents;
//#endregion
//#region src/services/checks/root-slug-withparent.ts
/**
* If slug is / and parentPage is set (would cause fullSlug to be the same as parentPage just with trailing slash)
*/
const checkRootSlugWithParent = (data) => {
if (data.collection.useTranslations && data.fields.slug.translations) {
const fieldErrors = [];
for (const [key, value] of Object.entries(data.fields.slug.translations)) if (value === "/" && data.fields.parentPage.value) fieldErrors.push({
key: constants_default.fields.slug.key,
localeCode: key,
message: translations_default("slug_cannot_be_slash_and_parent_page_set_message")
});
if (fieldErrors.length > 0) return {
error: {
type: "basic",
status: 400,
message: translations_default("slug_cannot_be_slash_and_parent_page_set_message"),
errors: { body: { fields: fieldErrors } }
},
data: void 0
};
} else if (data.fields.slug.value === "/" && data.fields.parentPage.value) return {
error: {
type: "basic",
status: 400,
message: translations_default("slug_cannot_be_slash_and_parent_page_set_message"),
errors: { body: { fields: [{
key: constants_default.fields.parentPage.key,
message: translations_default("slug_cannot_be_slash_and_parent_page_set_message")
}] } }
},
data: void 0
};
return {
error: void 0,
data: void 0
};
};
var root_slug_withparent_default = checkRootSlugWithParent;
//#endregion
//#region src/services/checks/page-is-parent-of-self.ts
/**
* Returns an error if the parentPage field is set to the same document as the current document
*/
const checkParentIsPageOfSelf = (data) => {
if (data.fields.parentPage.value && data.fields.parentPage.value === data.documentId) return {
error: {
type: "basic",
status: 400,
message: translations_default("cannot_have_self_as_parent_page_message"),
errors: { body: { fields: [{
key: constants_default.fields.parentPage.key,
localeCode: data.defaultLocale,
message: translations_default("cannot_have_self_as_parent_page_message")
}] } }
},
data: void 0
};
return {
error: void 0,
data: void 0
};
};
var page_is_parent_of_self_default = checkParentIsPageOfSelf;
//#endregion
//#region src/services/checks/check-fields-exist.ts
/**
* Returns an error if the required fields do not exist
*/
const checkFieldsExist = (data) => {
const fieldErrors = [];
if (data.fields.slug === void 0) fieldErrors.push({
key: "slug",
localeCode: null,
message: translations_default("field_required")
});
if (data.fields.parentPage === void 0) fieldErrors.push({
key: "parentPage",
localeCode: null,
message: translations_default("field_required")
});
if (data.fields.fullSlug === void 0) fieldErrors.push({
key: "fullSlug",
localeCode: null,
message: translations_default("field_required")
});
if (fieldErrors.length) return {
error: {
type: "basic",
message: translations_default("cannot_find_required_field_message"),
status: 400,
errors: { body: { fields: fieldErrors } }
},
data: void 0
};
return {
error: void 0,
data: {
slug: data.fields.slug,
parentPage: data.fields.parentPage,
fullSlug: data.fields.fullSlug
}
};
};
var check_fields_exist_default = checkFieldsExist;
//#endregion
//#region src/services/checks/circular-parents.ts
/**
* Recursively checks all parent pages for a circular reference and errors in that case
*/
const checkCircularParents = async (context, data) => {
try {
if (!data.documentId || !data.fields.parentPage.value) return {
error: void 0,
data: void 0
};
const { version: versionTable, documentFields: fieldsTable } = data.tables;
const parentPageField = prefixGeneratedColName(constants_default.fields.parentPage.key);
const result = await context.db.withRecursive("ancestors", (db) => db.selectFrom(fieldsTable).innerJoin(versionTable, `${versionTable}.id`, `${fieldsTable}.document_version_id`).select([`${versionTable}.document_id as current_id`, `${fieldsTable}.${parentPageField} as parent_id`]).where(`${fieldsTable}.locale`, "=", data.defaultLocale).where(`${versionTable}.type`, "=", data.versionType).where(`${versionTable}.document_id`, "=", data.fields.parentPage.value).unionAll(db.selectFrom(fieldsTable).innerJoin(versionTable, `${versionTable}.id`, `${fieldsTable}.document_version_id`).innerJoin("ancestors", "ancestors.parent_id", `${versionTable}.document_id`).select([`${versionTable}.document_id as current_id`, `${fieldsTable}.${parentPageField} as parent_id`]).where(`${fieldsTable}.locale`, "=", data.defaultLocale).where(`${versionTable}.type`, "=", data.versionType))).selectFrom("ancestors").select("parent_id").where("parent_id", "=", data.documentId).executeTakeFirst();
if (result) return {
error: {
type: "basic",
status: 400,
message: translations_default("circular_parents_error_message"),
errors: { body: { fields: [{
key: constants_default.fields.parentPage.key,
localeCode: data.defaultLocale,
message: translations_default("circular_parents_error_message")
}] } }
},
data: void 0
};
return {
error: void 0,
data: void 0
};
} catch (error) {
return {
error: {
type: "basic",
status: 500,
message: translations_default("an_unknown_error_occurred_checking_for_circular_parents")
},
data: void 0
};
}
};
var circular_parents_default = checkCircularParents;
//#endregion
//#region src/services/hooks/before-upsert-handler.ts
const beforeUpsertHandler = (options) => async (context, data) => {
const targetCollectionRes = get_target_collection_default({
options,
collectionKey: data.meta.collectionKey
});
if (targetCollectionRes.error) return {
error: void 0,
data: data.data
};
const checkFieldsExistRes = check_fields_exist_default({ fields: {
slug: data.data.fields?.find((f) => f.key === constants_default.fields.slug.key && f.type === "text"),
parentPage: data.data.fields?.find((f) => f.key === constants_default.fields.parentPage.key && f.type === "document"),
fullSlug: data.data.fields?.find((f) => f.key === constants_default.fields.fullSlug.key && f.type === "text")
} });
if (checkFieldsExistRes.error) return checkFieldsExistRes;
const { slug: slug$1, parentPage, fullSlug } = checkFieldsExistRes.data;
const checkParentIsPageOfSelfRes = page_is_parent_of_self_default({
defaultLocale: context.config.localisation.defaultLocale,
documentId: data.data.documentId,
fields: { parentPage }
});
if (checkParentIsPageOfSelfRes.error) return checkParentIsPageOfSelfRes;
const checkRootSlugWithParentRes = root_slug_withparent_default({
collection: targetCollectionRes.data,
defaultLocale: context.config.localisation.defaultLocale,
fields: {
slug: slug$1,
parentPage
}
});
if (checkRootSlugWithParentRes.error) return checkRootSlugWithParentRes;
const checkDuplicateSlugParentsRes = await duplicate_slug_parents_default(context, {
documentId: data.data.documentId,
versionId: data.data.versionId,
versionType: data.data.versionType,
collectionKey: targetCollectionRes.data.collectionKey,
fields: {
slug: slug$1,
parentPage
},
tables: data.meta.collectionTableNames
});
if (checkDuplicateSlugParentsRes.error) return checkDuplicateSlugParentsRes;
let parentFieldsData = [];
if (parentPage.value) {
const circularParentsRes = await circular_parents_default(context, {
documentId: data.data.documentId,
versionType: data.data.versionType,
defaultLocale: context.config.localisation.defaultLocale,
fields: { parentPage },
tables: data.meta.collectionTableNames
});
if (circularParentsRes.error) return circularParentsRes;
const parentFieldsRes = await get_parent_fields_default(context, {
defaultLocale: context.config.localisation.defaultLocale,
versionType: data.data.versionType,
fields: { parentPage },
tables: data.meta.collectionTableNames
});
if (parentFieldsRes.error) return parentFieldsRes;
parentFieldsData = parentFieldsRes.data;
}
const fullSlugRes = construct_parent_fullslug_default({
parentFields: parentFieldsData,
localisation: context.config.localisation,
collection: targetCollectionRes.data,
fields: { slug: slug$1 }
});
if (fullSlugRes.error) return fullSlugRes;
set_full_slug_default({
fullSlug: fullSlugRes.data,
defaultLocale: context.config.localisation.defaultLocale,
collection: targetCollectionRes.data,
fields: { fullSlug }
});
return {
error: void 0,
data: data.data
};
};
var before_upsert_handler_default = beforeUpsertHandler;
//#endregion
//#region src/services/hooks/after-upsert-handler.ts
const afterUpsertHandler = (options) => async (context, data) => {
const targetCollectionRes = get_target_collection_default({
options,
collectionKey: data.meta.collectionKey
});
if (targetCollectionRes.error) return {
error: void 0,
data: void 0
};
const descendantsRes = await get_descendant_fields_default(context, {
ids: [data.data.documentId],
versionType: data.data.versionType,
tables: data.meta.collectionTableNames
});
if (descendantsRes.error) return descendantsRes;
if (descendantsRes.data.length === 0) return {
error: void 0,
data: void 0
};
const currentFullSlugField = data.data.fields.find((field) => {
return field.key === constants_default.fields.fullSlug.key;
});
if (!currentFullSlugField) return {
error: void 0,
data: void 0
};
const docFullSlugsRes = construct_child_fullslugs_default({
descendants: descendantsRes.data,
localisation: context.config.localisation,
parentFullSlugField: currentFullSlugField,
collection: targetCollectionRes.data
});
if (docFullSlugsRes.error) return docFullSlugsRes;
await update_fullslug_fields_default(context, {
docFullSlugs: docFullSlugsRes.data,
versionType: data.data.versionType,
tables: data.meta.collectionTableNames
});
return {
error: void 0,
data: void 0
};
};
var after_upsert_handler_default = afterUpsertHandler;
//#endregion
//#region src/services/hooks/before-delete-handler.ts
const beforeDeleteHandler = (options) => async (context, data) => {
const targetCollectionRes = get_target_collection_default({
options,
collectionKey: data.meta.collectionKey
});
if (targetCollectionRes.error) return {
error: void 0,
data: void 0
};
const versionTypes = ["draft", "published"];
for (const versionType of versionTypes) {
const descendantsRes = await get_descendant_fields_default(context, {
ids: data.data.ids,
versionType,
tables: data.meta.collectionTableNames
});
if (descendantsRes.error) return descendantsRes;
if (descendantsRes.data.length === 0) continue;
const docFullSlugsRes = construct_child_fullslugs_default({
descendants: descendantsRes.data,
localisation: context.config.localisation,
collection: targetCollectionRes.data
});
if (docFullSlugsRes.error) return docFullSlugsRes;
await update_fullslug_fields_default(context, {
docFullSlugs: docFullSlugsRes.data,
versionType,
tables: data.meta.collectionTableNames
});
}
return {
error: void 0,
data: void 0
};
};
var before_delete_handler_default = beforeDeleteHandler;
//#endregion
//#region src/utils/field-res-to-schema.ts
const fieldResToSchema = (key, useTranslations, defaultLocale, items) => {
const fieldType = getFieldTypeFromKey(key);
if (!fieldType) throw new Error(`Unable to determine field type for key: ${key}`);
const result = {
key,
type: fieldType
};
if (useTranslations) {
result.translations = {};
for (const item of items) if (fieldType === "text") result.translations[item.locale] = item[`_${key}`];
else if (fieldType === "document") result.translations[item.locale] = item[`_${key}`];
} else {
const defaultItem = items.find((item) => item.locale === defaultLocale) || items[0];
if (fieldType === "text") result.value = defaultItem[`_${key}`];
else if (fieldType === "document") result.value = defaultItem[`_${key}`];
}
return result;
};
function getFieldTypeFromKey(key) {
switch (key) {
case "slug":
case "fullSlug": return "text";
case "parentPage": return "document";
default: return void 0;
}
}
var field_res_to_schema_default = fieldResToSchema;
//#endregion
//#region src/services/hooks/version-promote.ts
const versionPromoteHandler = (options) => async (context, data) => {
const targetCollectionRes = get_target_collection_default({
options,
collectionKey: data.meta.collectionKey
});
if (targetCollectionRes.error) return {
error: void 0,
data: void 0
};
let createFullSlug = true;
const docVersionFieldRes = await get_document_version_fields_default(context, {
documentId: data.data.documentId,
versionId: data.data.versionId,
versionType: data.data.versionType,
tables: data.meta.collectionTableNames
});
if (docVersionFieldRes.error) return docVersionFieldRes;
if (docVersionFieldRes.data === null) createFullSlug = false;
const checkFieldsExistRes = check_fields_exist_default({ fields: {
slug: field_res_to_schema_default(constants_default.fields.slug.key, targetCollectionRes.data.useTranslations, context.config.localisation.defaultLocale, docVersionFieldRes.data || []),
parentPage: field_res_to_schema_default(constants_default.fields.parentPage.key, false, context.config.localisation.defaultLocale, docVersionFieldRes.data || []),
fullSlug: field_res_to_schema_default(constants_default.fields.fullSlug.key, targetCollectionRes.data.useTranslations, context.config.localisation.defaultLocale, docVersionFieldRes.data || [])
} });
if (checkFieldsExistRes.error) return checkFieldsExistRes;
const { slug: slug$1, parentPage, fullSlug } = checkFieldsExistRes.data;
if (createFullSlug) {
const checkDuplicateSlugParentsRes = await duplicate_slug_parents_default(context, {
documentId: data.data.documentId,
versionId: data.data.versionId,
versionType: data.data.versionType,
collectionKey: targetCollectionRes.data.collectionKey,
fields: {
slug: slug$1,
parentPage
},
tables: data.meta.collectionTableNames
});
if (checkDuplicateSlugParentsRes.error) return checkDuplicateSlugParentsRes;
let parentFieldsData = [];
if (parentPage.value) {
const circularParentsRes = await circular_parents_default(context, {
documentId: data.data.documentId,
versionType: data.data.versionType,
defaultLocale: context.config.localisation.defaultLocale,
fields: { parentPage },
tables: data.meta.collectionTableNames
});
if (circularParentsRes.error) return circularParentsRes;
const parentFieldsRes = await get_parent_fields_default(context, {
defaultLocale: context.config.localisation.defaultLocale,
versionType: data.data.versionType,
fields: { parentPage },
tables: data.meta.collectionTableNames
});
if (parentFieldsRes.error) return parentFieldsRes;
parentFieldsData = parentFieldsRes.data;
}
const fullSlugRes = construct_parent_fullslug_default({
parentFields: parentFieldsData,
localisation: context.config.localisation,
collection: targetCollectionRes.data,
fields: { slug: slug$1 }
});
if (fullSlugRes.error) return fullSlugRes;
set_full_slug_default({
fullSlug: fullSlugRes.data,
defaultLocale: context.config.localisation.defaultLocale,
collection: targetCollectionRes.data,
fields: { fullSlug }
});
const updateFullSlugRes = await update_fullslug_fields_default(context, {
docFullSlugs: [{
documentId: data.data.documentId,
versionId: data.data.versionId,
fullSlugs: fullSlugRes.data
}],
versionType: data.data.versionType,
tables: data.meta.collectionTableNames
});
if (updateFullSlugRes.error) return updateFullSlugRes;
}
await after_upsert_handler_default(options)(context, {
meta: {
collection: data.meta.collection,
collectionKey: data.meta.collectionKey,
userId: data.meta.userId,
collectionTableNames: data.meta.collectionTableNames
},
data: {
documentId: data.data.documentId,
versionId: data.data.versionId,
versionType: data.data.versionType,
bricks: [],
fields: [
slug$1,
parentPage,
fullSlug
]
}
});
return {
error: void 0,
data: void 0
};
};
var version_promote_default = versionPromoteHandler;
//#endregion
//#region src/plugin.ts
const plugin = async (config, plugin$1) => {
const options = plugin_options_default(plugin$1);
for (const collectionConfig of options.collections) {
const collectionInstance = config.collections.find((c) => c.key === collectionConfig.collectionKey);
if (!collectionInstance) {
logger.warn({
message: translations_default("cannot_find_collection", { collection: collectionConfig.collectionKey }),
scope: PLUGIN_KEY
});
continue;
}
register_fields_default(collectionInstance, collectionConfig);
if (!collectionInstance.config.hooks) collectionInstance.config.hooks = [];
}
config.hooks.push({
service: "documents",
event: "beforeUpsert",
handler: before_upsert_handler_default(options)
});
config.hooks.push({
service: "documents",
event: "afterUpsert",
handler: after_upsert_handler_default(options)
});
config.hooks.push({
service: "documents",
event: "beforeDelete",
handler: before_delete_handler_default(options)
});
config.hooks.push({
service: "documents",
event: "versionPromote",
handler: version_promote_default(options)
});
return {
key: PLUGIN_KEY,
lucid: LUCID_VERSION,
config
};
};
var plugin_default = plugin;
//#endregion
//#region src/index.ts
const lucidPagesPlugin = (pluginOptions$1) => (config) => plugin_default(config, pluginOptions$1);
var src_default = lucidPagesPlugin;
//#endregion
export { src_default as default };
//# sourceMappingURL=index.js.map