UNPKG

@lucidcms/core

Version:

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

2 lines 8.81 kB
import e from"../../constants/constants.mjs";import t from"../../utils/errors/lucid-api-error.mjs";import n,{destroyLogger as r}from"../logger/index.mjs";import i from"../../utils/errors/translate-error-data.mjs";import{createTranslator as a,resolveInterfaceLocale as o}from"../i18n/translate.mjs";import{normalizeHost as s}from"../../utils/helpers/get-base-url.mjs";import{version as c}from"../../packages/core/package.mjs";import{destroyMediaAdapter as l,getInitializedMediaAdapter as u}from"../media/lifecycle.mjs";import{destroyKVAdapter as d,getInitializedKVAdapter as f}from"../kv/lifecycle.mjs";import{destroyQueueAdapter as p,getInitializedQueueAdapter as m}from"../queue/lifecycle.mjs";import h from"./middleware/log-route.mjs";import{destroyEmailAdapter as g,getInitializedEmailAdapter as _}from"../email/lifecycle.mjs";import{destroyImageProcessor as v,getInitializedImageProcessor as y}from"../image-processor/lifecycle.mjs";import b from"./routes/index.mjs";import x from"./utils/feature-support-checks.mjs";import S from"./utils/register-custom-routes.mjs";import C from"./utils/run-http-extensions.mjs";import{contextStorage as w}from"hono/context-storage";import{Scalar as T}from"@scalar/hono-api-reference";import{Hono as E}from"hono";import{cors as D}from"hono/cors";import{requestId as O}from"hono/request-id";import{secureHeaders as k}from"hono/secure-headers";import{openAPIRouteHandler as A}from"hono-openapi";const j=Symbol(`@lucidcms/core:http-invocation`),M=(e,t)=>{let n=Object.create(e.env??null);return t&&Object.defineProperties(n,Object.getOwnPropertyDescriptors(t)),Object.defineProperty(n,j,{value:e}),n},N=async N=>{let P=new E,F=N.config.host?.trim()?s(N.config.host):void 0;P.use(O({headerName:e.headers.requestId})).use(w()),await C({app:P,config:N.config,priority:0,extensions:[...N.http?.extensions??[],...N.config.http.extensions]});let I,L,R,z,B,V=()=>Promise.allSettled([p(L,{config:N.config,env:N.env,runtimeContext:N.runtimeContext}),d(I,{config:N.config,env:N.env,runtimeContext:N.runtimeContext}),l(R,{config:N.config,env:N.env,runtimeContext:N.runtimeContext}),g(z,{config:N.config,env:N.env,runtimeContext:N.runtimeContext}),v(B,{config:N.config,env:N.env,runtimeContext:N.runtimeContext})]);try{I=await f(N.config,{env:N.env,runtimeContext:N.runtimeContext}),L=await m(N.config,{env:N.env,runtimeContext:N.runtimeContext}),R=await u(N.config,{env:N.env,runtimeContext:N.runtimeContext}),z=await _(N.config,{env:N.env,runtimeContext:N.runtimeContext}),B=await y(N.config,{env:N.env,runtimeContext:N.runtimeContext})}catch(e){throw await V(),await r(),e}if(!I||!L||!z||!B)throw Error(`Lucid could not initialize its application adapters.`);P.use(h).use(D({origin:[`http://localhost:3000`,...F?[F]:[],...N.config.http.security.cors?.origin||[]],allowMethods:[`GET`,`POST`,`PUT`,`DELETE`,`PATCH`],allowHeaders:[`Content-Type`,`Authorization`,`Content-Length`,...Object.values(e.headers),...N.config.http.security.cors?.allowHeaders||[]],exposeHeaders:[e.headers.requestId],credentials:!0})).use(k(N.config.http.security.headers??{crossOriginResourcePolicy:!1})).use(async(e,t)=>{let n=e.env?.[j];if(!n)throw Error(`Lucid HTTP requests must be handled with an active runtime invocation.`);e.set(`config`,N.config),e.set(`database`,n.database),e.set(`translationStore`,N.translationStore),e.set(`runtimeContext`,N.runtimeContext),e.set(`queue`,L),e.set(`kv`,I),e.set(`media`,R),e.set(`email`,z),e.set(`env`,n.env??null),e.set(`cf`,e.get(`cf`)??null),e.set(`caches`,e.get(`caches`)??null),e.set(`ctx`,e.get(`ctx`)??null),await t()}).route(`/`,b).onError(async(r,s)=>{let c=o({config:N.config,locale:s.req.header(e.headers.interfaceLocale),acceptLanguage:s.req.header(`Accept-Language`)}),l=a({store:N.translationStore,locale:c});if(r instanceof t){let e=i(r.error,l);return s.status(e.status),s.json({name:e.name,message:e.message,status:e.status,errors:e.errors,code:e.code,key:e.key})}if(n.error({error:r,event:`http.unhandled.error`,message:r.message,scope:e.logScopes.http}),r?.statusCode===429){let e=s.res.headers.get(`Retry-After`)??0;return s.status(429),s.json({code:`rate_limit`,name:l(`server:core.rate.limit.error.name`),message:l(`server:core.rate.limit.exceeded.message`,{data:{resetSeconds:e}}),status:429})}return s.status(500),s.json({name:l(`server:core.errors.default.name`),message:r.message?r.message:l(`server:core.errors.default.message`),status:e.errors.status,errors:e.errors.errors,code:e.errors.code})}).notFound(t=>{let n=o({config:N.config,locale:t.req.header(e.headers.interfaceLocale),acceptLanguage:t.req.header(`Accept-Language`)}),r=a({store:N.translationStore,locale:n});return t.req.url.includes(`/${e.directories.base}/api`)?t.json({status:404,code:`not_found`,name:r(`server:core.routes.not.found`),message:r(`server:core.routes.not.found.message`)}):(t.status(404),t.text(r(`server:core.pages.not.found`)))});try{S(P,N.config.http.routes),await C({app:P,config:N.config,priority:1,extensions:[...N.config.http.extensions,...N.http?.extensions??[]]}),N.config.http.openAPI?.enabled&&(P.get(`/${e.directories.base}/openapi`,A(P,{documentation:{openapi:`3.0.0`,info:{title:`Lucid CMS`,description:`A modern headless CMS offering a delightful developer experience. Tailor Lucid CMS seamlessly to your client and frontend requirements with our expressive brick and collection builders and extensive configuration.`,version:c},tags:[{name:`auth`,description:`Authentication endpoints including login, token management, CSRF protection and logout functionality.`},{name:`account`,description:`User account management endpoints for user details, password resets and updating personal settings.`},{name:`collections`,description:`Collection endpoints for returning all of the collection configuration, such as their details, config and supported bricks and fields.`},{name:`documents`,description:`Document endpoints for creating, deleting, updating and promoting/restoring versions.`},{name:`media`,description:`Media endpoints for creating, updating, deleting, creating upload sessions and clearing processed images.`},{name:`media-folders`,description:`Media folder endpoints for creating, updating, deleting and fetching media folders.`},{name:`media-share-links`,description:`Media share link endpoints for creating, updating, deleting and fetching media share links.`},{name:`emails`,description:`Email endpoints for fetching, deleting and resending emails.`},{name:`users`,description:`User endpoints for inviting, deleting and updating.`},{name:`roles`,description:`Role endpoints for fetching, creating, updating and deleting.`},{name:`permissions`,description:`Permission endpoints for fetching all available permissions.`},{name:`locales`,description:`Locale endpoints for fetching active locales. These are the locales available for your content to be written in.`},{name:`jobs`,description:`Job endpoints for fetching existing jobs so you can monitor them and their status.`},{name:`cdn`,description:`CDN endpoints for streaming media files. This handles media retrieval and optional on-request image processing.`},{name:`share`,description:`Share endpoints for accessing shared media files.`},{name:`settings`,description:`Setting endpoints to recieve current settings and meta data on Lucid.`},{name:`license`,description:`License endpoints for managing the license key and verifying its validity.`},{name:`ai`,description:`AI endpoints for generating CMS content with Lucid AI features.`},{name:`client-integrations`,description:`Endpoints for managing client integration credentials used to authenticate external applications accessing CMS content via client endpoints.`},{name:`client-documents`,description:`Client document endpoints for fetching single and multiple documents via the client integration authentication.`},{name:`client-previews`,description:`Client preview endpoints for resolving preview metadata in browser applications.`},{name:`client-locales`,description:`Client locale endpoints for fetching locale information.`}],servers:F?[{url:F.includes(`[::1]`)?F.replace(`[::1]`,`localhost`):F,description:`Development server`}]:[]}})),P.get(e.openAPIDocsRoute,T({url:`/${e.directories.base}/openapi`,theme:`saturn`,defaultHttpClient:{targetKey:`node`,clientKey:`fetch`}}))),await C({app:P,config:N.config,priority:2,extensions:[...N.config.http.extensions,...N.http?.extensions??[]]})}catch(e){throw await V(),await r(),e}let H=x({queue:L.key,kv:I.key,media:R?.key??null,email:z.key,database:N.config.db.adapter},N.runtimeContext.support),U;return{handle:e=>P.fetch(e.request,M({database:e.database,env:e.env},e.requestBindings),e.executionContext),queue:L,kv:I,media:R,email:z,issues:H.issues,destroy:()=>(U??=(async()=>{await V(),await r()})(),U)}};export{N as default}; //# sourceMappingURL=app.mjs.map