UNPKG

@lucidcms/core

Version:

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

623 lines (613 loc) 30.9 kB
// src/translations/en-gb.json var en_gb_default = { headers_already_sent: "Headers were already sent.", default_error_name: "An error occurred!", default_error_message: "An error occurred! Please try again later.", validation_error: "Validation Error", authorisation_error: "Authorisation Error", forbidden_error: "Forbidden Error", an_unknown_error_occurred: "An unknown error occurred.", option_error_occured_saving_default: "An error occurred while saving the default option.", roles_error_occured_saving_default: "An error occurred while saving the default roles.", user_error_occured_saving_default: "An error occurred while saving the default user.", locale_error_occured_saving_default: "An error occurred while saving the default locales.", an_error_occurred_clearing_expired_tokens: "An error occurred while clearing expired tokens.", an_error_occurred_clearing_expired_locales: "An error occurred while clearing expired locales.", swagger_response_200: "Successfull response", swagger_response_201: "Resource created response", swagger_response_204: "No content response", swagger_response_400: "Bad request response", swagger_response_401: "Unauthorised response", swagger_response_403: "Forbidden response", swagger_response_404: "Not found response", swagger_response_500: "Internal server error response", swagger_csrf_header_description: "A token that is used to protect against CSRF attacks. CSRF middleware expects this value to be passed in the header so it can be compared to the httpOnly _csrf cookie.", swagger_access_header_description: "Stores the access token that is used to authenticate requests.", swagger_refresh_header_description: "Stores the refresh token that can be used to obtain a new access token when the current one expires.", swagger_query_string_include_description: "Seperate values by a comma if you want to include multiple values", swagger_query_string_filter_description: "Seperate values by a comma if you want to filter by multiple values", swagger_query_string_sort_description: "Prefix the value with a minus sign (-) to sort in descending order and seperate values by a comma if you want to sort by multiple values", swagger_query_string_page_description: "The page number of the paginated response", swagger_query_string_per_page_description: "The number of items per page in the paginated response", swagger_content_locale_header_description: "The locale code of the content you wish to filter translations by. If left empty, the default language will be used.", swagger_client_key_header_description: "The client key for the client integration.", swagger_authorization_header_description: "The Authorization header is required for client integrations and should take the API key as the value.", login_suspended_error_message: "Your account has been suspended. Please contact an administrator.", validation_body_error_message: "Please check the request body and try again.", multipart_body_validation_error_message: "Please ensure the multipart/form-data body value is valid JSON.", published_version_not_created_message: "The published version was not created.", validation_query_error_message: "Please check the query parameters and try again.", draft_version_not_moved_to_revision_message: "The draft version was not moved to a revision.", revision_version_not_restored_message: "The revision version was not restored.", revisions_not_enabled_error_name: "Revisions Not Enabled", revisions_not_enabled_message: "Revisions are not enabled for this collection.", validation_params_error_message: "Please check the request parameters and try again.", access_token_error_name: "There was an error obtaining an access token.", access_token_error_message: "There was an error obtaining an access token. Please try logging in again.", refresh_token_error_name: "There was an error obtaining a new access token.", refresh_token_error_message: "There was an error obtaining a new access token. Please try logging in again.", not_authorised_to_perform_action: "You are not authorised to perform this action.", failed_to_validate_csrf_token: "Failed to validate CSRF token.", duplicate_entry_error_message: "An entry with the same value already exists.", this_collection_has_a_document_already: "This collection has a document already.", the_permission_is_invalid_against_mesage: "The permission '{{permission}}' is invalid.", not_unique_error_message: "Please ensure that the value is unique and try again.", this_email_is_already_in_use: "This email address is already in use.", this_username_is_already_in_use: "This username is already in use.", you_do_not_have_permission_to_perform_this_action: "You do not have permission to perform this action.", db_connection_error: "An error occurred while connecting to the database.", if_account_exists_with_email_not_found: "If an account exists with the email provided, a password reset link will be sent to the email address.", reset_password_email_subject: "Reset your password", user_invite_email_subject: "You have been invited to join a Lucid project", password_reset_success_subject: "Password reset successful", email_update_success_subject: "Email update successful", please_ensure_passwords_match: "Please ensure that the passwords match and try again.", ensure_file_has_been_uploaded: "Please ensure that a file has been uploaded and try again.", make_sure_all_translations_locales_exist: "Please make sure all translation locales exist.", file_too_large_max_size_is: "File is too large. Max file size is {{size}} bytes.", file_exceeds_storage_limit_max_limit_is: "Files exceed storage limit. Max storage limit is {{size}} bytes.", only_found_ids_error_message: "Only found the following ids: {{ids}}", error_saving_page_brick_couldnt_find_brick_config: "We couln't find the brick config for the brick key of: '{{key}}'. Ensure you are using the correct key for the brick defined in your lucid.config file.", field_validation_error_name: "Field Validation Error", field_validation_error_message: "There was an error validating some fields.", config_duplicate_keys: "Duplicate keys found for {{builder}} builder.", cannot_find_config_path: "Cannot find the lucid.config.ts or lucid.config.js file at the root of your project.", cannot_find_repository: "Cannot find the repository for the {{name}}.", cannot_find_formatter: "Cannot find the formatter for the {{name}}.", config_error_name: "Configuration Error", cannot_promote_to_same_version_message: "You cannot promote to the same version type.", email_not_configured_message: "Email functionality is disabled because the email configuration is missing. Please provide the necessary email settings in the 'lucid.config.ts/js' file to enable email features.", media_strategy_not_configured_message: "Media functionality is disabled because the media strategy configuration is missing.", db_migration_failed: "Database migration failed.", duplicate_field_keys_message: "Duplicate field keys found ({{keys}}) in {{type}}: {{typeKey}}.", repeater_depth_message: "Repeater depth is too high in {{type}}: {{typeKey}} with key: {{repeaterKey}}. Please reduce the depth from {{depth}} to {{maxRepeaterDepth}}.", plugin_version_not_supported: "This plugin does not support version {{version}} of Lucid, only versions {{supportedVersions}}.", an_error_occurred_updating_media_storage: "An error occurred while updating the media storage option.", an_error_occurred_deleting_expired_media: "An error occurred while deleting expired media.", no_records_provided: "No records provided.", failed_to_create_document_or_version: "Failed to create document or version.", media_name_invalid: "Invalid media name.", media_name_invalid_message: "The media name is invalid. Please ensure the media name is a valid string.", permission_error_name: "Permission Error", error_locked_collection_name: "Collection Locked", start_error_name: "Start Task Error", error_locked_collection_message: "The collection is locked and cannot be updated.", error_locked_collection_message_delete: "The collection is locked and cannot be deleted.", config_locales_empty: "Please ensure the locales array is not empty.", config_default_locale_undefined: "Please ensure the defaultLocale is defined.", config_default_locale_not_found: "Please ensure the defaultLocale exists in the locales array.", config_duplicate_locale: "Please ensure the locales array does not contain duplicate values.", error_cant_update_yourself: "You can't update yourself.", error_cant_delete_yourself: "You can't delete yourself.", error_cant_delete_last_user: "You can't delete the last remaining user.", no_refresh_token_found: "No refresh token found.", please_ensure_password_is_correct: "Please ensure the password is correct and try again.", please_provide_new_password: "Please provide a new password.", please_provide_current_password: "Please provide your current password.", generic_field_required: "Please enter a value for this field", checkbox_field_required: "Please ensure the checkbox is checked", select_field_required: "Please select an option", generic_field_invalid: "Please enter a valid value for this field", please_ensure_a_valid_option_is_selected: "Please ensure a valid option is selected", cannot_find_field_in_collection_or_brick: "Cannot find field within the collection or brick. Please ensure a field with this key exists.", an_unknown_error_occurred_validating_the_field: "An unknown error occured when validating the field.", field_media_min_width: "Media width must be greater than {{min}}px", field_media_max_width: "Media width must be less than {{max}}px", field_media_min_height: "Media height must be greater than {{min}}px", field_media_max_height: "Media height must be less than {{max}}px", field_media_type: 'Media must be of type "{{type}}"', field_media_extension: "Media must be one of the following extensions: {{extensions}}", field_media_not_found: "We couldn't find the media you selected", field_user_not_found: "We couldn't find the user you selected", field_document_not_found: "We couldn't find the document you selected", field_media_doenst_have_type: "This media does not have a type", field_media_doenst_have_width: "This media does not have a width", field_media_doenst_have_height: "This media does not have a height", field_type_mismatch: 'The type of the field does not match the type of the config field. Received: "{{received}}" Expected: "{{expected}}"', field_date_invalid: "Please ensure the date you have entered is valid", field_link_target_error_message: "Please set the target to one of the following: {{valid}}", generic_field_data_type_mismatch: "The data type is incorrect", unknown_service_error: "An unknown error occurred", unknown_service_error_message: "An unknown error occurred. Please try again later.", processed_images_size_limit_exceeded: "Processed image size limit exceeded.", route_user_fetch_error_name: "User(s) Fetch Error", route_user_fetch_error_message: "An error occurred while fetching the user(s).", route_user_create_error_name: "User Create Error", route_user_create_error_message: "An error occurred while creating the user.", route_user_delete_error_name: "User Delete Error", route_user_delete_error_message: "An error occurred while deleting the user.", route_user_update_error_name: "User Update Error", route_user_update_error_message: "An error occurred while updating the user.", route_user_me_update_error_name: "User Update Error", route_user_me_update_error_message: "An error occurred while updating your account.", route_reset_password_error_name: "Reset Password Error", route_reset_password_error_message: "An error occurred while resetting the password.", route_send_password_reset_error_name: "Send Password Reset Error", route_send_password_reset_error_message: "An error occurred while sending the password reset link.", route_verify_password_reset_error_name: "Verify Password Reset Error", route_verify_password_reset_error_message: "An error occurred while verifying the password reset link.", route_login_error_name: "Login Error", route_login_error_message: "An error occurred while logging in.", route_document_delete_error_name: "Document(s) Delete Error", route_document_delete_error_message: "An error occurred while deleting the document(s).", route_document_restore_revision_error_name: "Document(s) Restore Revision Error", route_document_restore_revision_error_message: "An error occurred while restoring the document revision.", route_document_revision_fetch_error_name: "Document Revision(s) Fetch Error", route_document_revision_fetch_error_message: "An error occurred while fetching the document revision(s).", route_document_promote_version_error_name: "Document(s) Promote Version Error", route_document_promote_version_error_message: "An error occurred while promoting the document version.", route_document_fetch_error_name: "Document(s) Fetch Error", route_document_fetch_error_message: "An error occurred while fetching the document(s).", route_document_update_error_name: "Document Update Error", route_document_update_error_message: "An error occurred while updating the document.", route_document_create_error_name: "Document Create Error", route_document_create_error_message: "An error occurred while creating the document.", route_collection_fetch_error_name: "Collection(s) Fetch Error", route_collection_fetch_error_message: "An error occurred while fetching the collection(s).", route_email_delete_error_name: "Email Delete Error", route_email_delete_error_message: "An error occurred while deleting the email.", route_email_fetch_error_name: "Email(s) Fetch Error", route_email_fetch_error_message: "An error occurred while fetching the email(s).", route_email_resend_error_name: "Email Resend Error", route_email_resend_error_message: "An error occurred while resending the email.", route_locale_fetch_error_name: "Locale(s) Fetch Error", route_locale_fetch_error_message: "An error occurred while fetching the locale(s).", route_media_clear_processed_error_name: "Processed Image(s) Clear Error", route_media_clear_processed_error_message: "An error occurred while clearing the processed image(s).", route_media_delete_error_name: "Media Delete Error", route_media_delete_error_message: "An error occurred while deleting the media.", route_media_fetch_error_name: "Media(s) Fetch Error", route_media_fetch_error_message: "An error occurred while fetching the media(s).", route_media_update_error_name: "Media Update Error", route_media_update_error_message: "An error occurred while updating the media.", route_media_upload_error_name: "Media Upload Error", route_media_upload_error_message: "An error occurred while uploading the media.", route_roles_create_error_name: "Role Create Error", route_roles_create_error_message: "An error occurred while creating the role.", route_roles_delete_error_name: "Role Delete Error", route_roles_delete_error_message: "An error occurred while deleting the role.", route_roles_fetch_error_name: "Role(s) Fetch Error", route_roles_fetch_error_message: "An error occurred while fetching the role(s).", route_roles_update_error_name: "Role Update Error", route_roles_update_error_message: "An error occurred while updating the role.", route_settings_fetch_error_name: "Settings Fetch Error", route_settings_fetch_error_message: "An error occurred while fetching the settings.", route_client_integrations_create_error_name: "Client Integration Create Error", route_client_integrations_create_error_message: "An error occurred while creating the client integration.", route_client_integrations_fetch_error_name: "Client Integration(s) Fetch Error", route_client_integrations_fetch_error_message: "An error occurred while fetching the client integration(s).", route_client_integrations_delete_error_name: "Client Integration Delete Error", route_client_integrations_delete_error_message: "An error occurred while deleting the client integration.", route_client_integrations_update_error_name: "Client Integration Update Error", route_client_integrations_update_error_message: "An error occurred while updating the client integration.", account_not_found_message: "The account you are trying to access does not exist.", media_not_found_message: "The media you are trying to access does not exist.", document_not_found_message: "The document you are trying to access does not exist.", document_version_not_found_message: "The document version you are trying to access does not exist.", collection_not_found_message: "The collection you are trying to access does not exist.", email_not_found_message: "The email you are trying to access does not exist.", locale_not_found_message: "The locale you are trying to access does not exist.", option_not_found_message: "The option you are trying to access does not exist.", role_not_found_message: "The role you are trying to access does not exist.", token_not_found_message: "The token you are trying to access does not exist.", user_not_found_message: "The user you are trying to access does not exist.", client_integration_not_found_message: "The client integration you are trying to access does not exist.", template_not_found_message: "The template you are trying to use cannot be found.", error_saving_bricks: "Error Saving Bricks", error_saving_page_duplicate_order: "Duplicate builder orders found: {{order}}.", login_error_message: "The username/email or password you entered is incorrect.", cron_job_error_name: "Cron Job Error", cron_job_error_message: "An error occurred while running/registering the cron jobs.", running_cron_jobs: "Running cron jobs...", media_error_missing_file_name: "If you are updating the media file, a file name must be provided.", seed_error_name: "Seed Error", seed_error_message: "An error occurred while seeding the database.", running_database_seed_jobs: "Running database seed jobs...", lucid_server_unknow_error: "An error occurred during the initialisation of the Lucid server", lucid_server_unknow_build_error: "An error occured during the vite admin SPA build step", media_error_getting_metadata: "An error occurred while getting the media metadata.", client_integration_key_already_exists: "The unique key for the client integration already exists, please re-send the request", client_integration_key_missing: "The client key header is missing", cannot_find_client_integration: "The client you are trying to authenticate with does not exist", client_integration_is_disabled: "The client integration is disabled. Please enable it and try again.", client_integration_api_key_missing: "The client integration API key is missing from the authorisation header.", invalid_client_integration_api_key: "The client integration API key is invalid. Please ensure it is correct and try again.", client_integration_error: "An error occurred while verifying the client integration API key.", rate_limit_error_name: "Rate Limit Error", route_not_found: "Route Not Found", route_not_found_message: "The route you are trying to access does not exist.", cannot_promote_revision_message: "You cannot promote a revision to a new version type. Please use the restore revision endpoint instead.", cannot_promote_to_draft_message: "You cannot promote to a draft as the collection is not configured to use drafts.", page_not_found: "The page you are trying to access does not exist.", toolkit_error_name: "Toolkit Error", toolkit_error_message: "An error occurred while using the toolkit", validation_error_message: "Please ensure the data you have provided is correct.", authorisation_error_message: "Please ensure you are logged in and have the correct permissions.", forbidden_error_message: "You do not have permission to perform this action.", send_email_error_name: "Send Email Error", field_document_collection_not_found: "The collection '{{collection}}' does not exist or is not of mode multiple for the document field '{{field}}'.", field_has_relation_data: "The is missing relation data", field_document_collection_key_mismatch: "The collection of this document does not match the collection set against the field. Received: '{{received}}' Expected: '{{expected}}'", invalid_encrypted_secret: "The encrypted secret is invalid.", media_duplicate_key_error_name: "Media Duplicate Key Error", media_duplicate_key_error_message: "The media key you have provided already exists.", route_media_create_error_name: "Media Create Error", route_media_create_error_message: "There was an error creating the media item.", media_error_not_awaiting_sync: "The media key has either expired, been created already or has been deleted.", vite_build_error_name: "Vite Build Error", vite_build_error_copy_assets_error: "An error occured while copying over a @lucidcms/admin asset export to the Vite build directory.", vite_build_error_message: "An unknown error occured while building the SPA via Vite.", vite_build_meta_generation_error: "An unknown error occured while generating the client build metadata file.", vite_client_mount_generation_error: "An unknown error occured while generating the admin client JS mount.", vite_client_index_generation_error: "An unknown error occured while generating the admin index.html entry.", vite_build_meta_read_error: "An unknown error occured while reading the client build metadata file." }; // src/translations/index.ts var selectedLang = en_gb_default; var 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; // src/utils/errors/error-type-defaults.ts var errorTypeDefaults = (error) => { switch (error.type) { case "validation": { return { status: 400, name: error.name ?? translations_default("validation_error"), message: error.message ?? translations_default("validation_error_message") }; } case "authorisation": { return { status: 401, name: error.name ?? translations_default("authorisation_error"), message: error.message ?? translations_default("authorisation_error_message") }; } case "forbidden": { return { status: 403, name: error.name ?? translations_default("forbidden_error"), message: error.message ?? translations_default("forbidden_error_message") }; } default: { return { status: error.status, name: error.name, message: error.message }; } } }; var error_type_defaults_default = errorTypeDefaults; // src/constants/permission-groups.ts var permissionGroups = { users: { key: "users_permissions", permissions: ["create_user", "update_user", "delete_user"] }, roles: { key: "roles_permissions", permissions: ["create_role", "update_role", "delete_role"] }, media: { key: "media_permissions", permissions: ["create_media", "update_media", "delete_media"] }, emails: { key: "emails_permissions", permissions: ["read_email", "delete_email", "send_email"] }, content: { key: "content_permissions", permissions: [ "create_content", "update_content", "delete_content", "restore_content", "publish_content" ] }, "client-integrations": { key: "client-integrations_permissions", permissions: [ "create_client_integration", "update_client_integration", "delete_client_integration", "regenerate_client_integration" ] } }; var permission_groups_default = permissionGroups; // src/constants/constants.ts var constants_default = { locales: ["en"], tempDir: "./tmp", swaggerRoutePrefix: "/documentation", headers: { accessToken: "_access", csrf: "_csrf", refreshToken: "_refresh", clientIntegrationKey: "lucid-client-key", contentLocale: "lucid-content-locale" }, seedDefaults: { user: { firstName: "Lucid", lastName: "CMS", email: "admin@lucidcms.io", username: "admin", password: "password", superAdmin: 1 }, roles: [ { name: "Admin", description: "The admin role has permissions to do everything.", permissions: [ ...permission_groups_default.users.permissions, ...permission_groups_default.roles.permissions, ...permission_groups_default.media.permissions, ...permission_groups_default.emails.permissions, ...permission_groups_default.content.permissions, ...permission_groups_default["client-integrations"].permissions ] }, { name: "Editor", description: "The editor role has permissions to manage content.", permissions: [ ...permission_groups_default.media.permissions, ...permission_groups_default.content.permissions ] } ] }, fieldBuiler: { maxRepeaterDepth: 3 }, collectionBuilder: { isLocked: false, useDrafts: false, useRevisions: false, useTranslations: false }, customFields: { link: { targets: ["_self", "_blank", "_parent", "_top", "framename"] } }, query: { page: 1, perPage: 10 }, locations: { resetPassword: "/admin/reset-password" }, errors: { name: translations_default("default_error_name"), message: translations_default("default_error_message"), status: 500, code: void 0, errorResponse: void 0 }, emailTemplates: { resetPassword: "reset-password", userInvite: "user-invite", passwordResetSuccess: "password-reset-success", emailChanged: "email-changed" }, rateLimit: { max: 100, timeWindow: "1 minute" // ms format - https://github.com/vercel/ms }, runtimeStore: { dist: ".lucid" }, vite: { outputDir: "client", dist: "dist", mount: "mount.jsx", html: "index.html", rootSelector: "root", buildMetadata: "build-metadata.json", port: 24678 }, arguments: { noCache: "--no-cache" }, brickTypes: { builder: "builder", fixed: "fixed", collectionFields: "collection-fields" }, cronSchedule: "0 0 * * *", csrfExpiration: 604800, // 7 days in seconds refreshTokenExpiration: 604800, // 7 days in seconds accessTokenExpiration: 300, // 5 minutes in seconds passwordResetTokenExpirationMinutes: 15, // 15 minutes userInviteTokenExpirationMinutes: 1440, // 24 hours in minutes documentation: "https://lucidcms.io/getting-started", lucidUi: "https://lucidui.io/", mediaAwaitingSyncInterval: 36e5, // 1 hour in ms fastify: { version: "4.x" } }; // src/utils/errors/lucid-api-error.ts var LucidAPIError = class _LucidAPIError extends Error { error; constructor(error) { super(error.message); this.error = error; if (error.zod !== void 0) { this.error.errorResponse = _LucidAPIError.formatZodErrors( error.zod?.issues || [] ); } const errorTypeRes = error_type_defaults_default(error); this.error.status = errorTypeRes.status; this.name = errorTypeRes.name ?? constants_default.errors.name; this.message = errorTypeRes.message ?? constants_default.errors.message; } // static static formatZodErrors(error) { const result = {}; for (const item of error) { let current = result; for (const key of item.path) { if (typeof key === "number") { current = current.children || (current.children = []); current = current[key] || (current[key] = {}); } else { current = current[key] || (current[key] = {}); } } current.code = item.code; current.message = item.message; } return result ?? void 0; } }; var lucid_api_error_default = LucidAPIError; // src/utils/logging/logger.ts import winston from "winston"; var winstonLogger = winston.createLogger({ level: "info", format: winston.format.json() }); if (process.env.NODE_ENV !== "production") { winstonLogger.add( new winston.transports.Console({ format: winston.format.combine( winston.format.colorize(), winston.format.simple() ) }) ); } var logger_default = winstonLogger; // src/utils/logging/index.ts var logger = (level, data) => { let logFn = logger_default.error; switch (level) { case "error": logFn = logger_default.error; break; case "warn": logFn = logger_default.warn; break; case "info": logFn = logger_default.info; break; case "debug": logFn = logger_default.debug; break; default: logFn = logger_default.error; break; } logFn(messageFormat(data), data.data); }; var messageFormat = (data) => { if (data.scope) { return `[${data.scope}]: ${data.message}`; } return data.message; }; var logging_default = logger; // src/utils/errors/lucid-error.ts var LucidError = class extends Error { scope; kill; constructor(data) { super(data.message); this.scope = data.scope; this.kill = data.kill; logging_default("error", { message: this.message, scope: this.scope, data: data.data ?? void 0 }); if (this.kill) process.exit(1); } }; var lucid_error_default = LucidError; // src/utils/errors/decode-error.ts var decodeError = (error) => { if (error instanceof lucid_api_error_default) { return { name: error.error.name, message: error.error.message, status: error.error.status, errorResponse: error.error.errorResponse, code: error.error.code }; } if (error?.statusCode === 429) { return { code: "rate_limit", name: translations_default("rate_limit_error_name"), message: error.message || constants_default.errors.message, status: 429 }; } return { name: constants_default.errors.name, message: error.message || constants_default.errors.message, status: constants_default.errors.status, errorResponse: constants_default.errors.errorResponse, code: constants_default.errors.code }; }; var decode_error_default = decodeError; export { translations_default, permission_groups_default, constants_default, decode_error_default, error_type_defaults_default, lucid_api_error_default, logging_default, lucid_error_default }; //# sourceMappingURL=chunk-ZMWDUGJW.js.map