/** * Static sites and apps as a server extension: the platform passes the * factory to core's `extensions` option. With a site domain the extension * serves sites on hostnames under it, backs the account page's sites list * and installs apps from manifests; without one it serves the installs * listing alone. Materialized queries are the part `queries` turns on. * * This module must stay free of node-only imports; it runs on Cloudflare * Workers. */ import { cborEncodeDagCbor, cidToString, createCid } from '@pdsjs/core/repo'; import { createSiteAccountRoutes } from './account.js'; import { createSiteBrowser } from './browser.js'; import { createSiteHandler } from './handler.js'; import { createSiteInstaller } from './installer.js'; import { QUERY_COLLECTION, SITE_COLLECTION } from './lexicons.js'; import { createQueryEngine } from './query.js'; /** * @param {Object} [options] * @param {string} [options.domain] - apex domain sites serve under; absent, no site is served * @param {string} [options.apexName] - site bound to the apex (default "home") * @param {boolean} [options.queries] - serve dev.pdsjs.query.run over this repo's dev.pdsjs.query.def records * @returns {import('@pdsjs/core/ports').ExtensionFactory} */ export function createSitesExtension({ domain, apexName, queries = false, } = {}) { return (host) => { const { actorStorage, blobs } = host; const siteCtx = domain ? { actorStorage, blobs, getDid: host.getDid, siteDomain: domain, apexName: apexName || undefined, } : null; const handleHost = siteCtx ? createSiteHandler(siteCtx) : null; const browser = siteCtx ? createSiteBrowser(siteCtx) : null; const installer = siteCtx ? createSiteInstaller({ actorStorage, blobs, getDid: host.getDid, createCommit: host.createCommit, linkBlob: (cid, uri, time) => actorStorage.linkBlobToRecord(cid, uri, time), encodeRecord: async (record) => { const bytes = cborEncodeDagCbor(record); return { cid: cidToString(await createCid(bytes)), bytes }; }, }) : null; const engine = queries ? createQueryEngine({ actorStorage, getDid: host.getDid }) : null; return { name: 'sites', // A query definition names the collection it reads, so with queries // on the engine may read any of them. collections: engine ? ['*'] : [ SITE_COLLECTION, QUERY_COLLECTION, 'dev.pdsjs.app.install', 'dev.pdsjs.app.manifest', ], routes: { ...createSiteAccountRoutes({ host, browser, installer }), ...(engine ? engine.routes : {}), }, features: { sites: Boolean(browser) }, ...(handleHost ? { handleHost } : {}), ...(engine ? { onCommit: engine.onCommit } : {}), }; }; }