chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
/**
* 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 } : {}),
};
};
}