import { crudEventNames } from '../db/schema.ts'; import type { Connection } from '../protocol/connection.ts'; import { MESSAGE_TYPE } from '../protocol/messageTypes.ts'; import type { GenesisMessage, MockServerConfig, ResourceItem } from '../types.ts'; // GenesisResources (foundation-comms/src/resources/genesis/genesis.ts) gates // every datasource/request-reply/commit call on this list first — an empty // or missing RESOURCES_REQUEST_ACK.RESOURCES makes every resource silently // "not exist" client-side, before META_REQUEST or DATA_LOGON is ever tried. // Auto-derive it from config.queries/requestReplies/eventHandlers (same // philosophy as db/metadata.ts's field inference) so projects don't have to // hand-maintain a redundant list; set config.resources explicitly to override, // or config.additionalResources to add to it. function deriveResources(config: MockServerConfig): ResourceItem[] { const resources: ResourceItem[] = []; for (const name of Object.keys(config.queries ?? {})) { resources.push({ RESOURCE_NAME: name, RESOURCE_TYPE: 'DATASERVER' }); } for (const name of Object.keys(config.requestReplies ?? {})) { resources.push({ RESOURCE_NAME: name, RESOURCE_TYPE: 'REQUEST_SERVER' }); } const eventNames = new Set([ ...Object.keys(config.eventHandlers ?? {}), // The generic CRUD events tables register through TableDef.events. ...crudEventNames(config), // Events served only by eventSchemas + defaultEventHandler still need to // be discoverable, or the client-side resource gate blocks them before // the commit is ever sent. ...Object.keys(config.eventSchemas ?? {}), ]); for (const name of eventNames) { resources.push({ RESOURCE_NAME: name, RESOURCE_TYPE: 'EVENT_HANDLER' }); } return resources; } const resourceKey = (resource: ResourceItem) => `${resource.RESOURCE_TYPE}:${resource.RESOURCE_NAME}`; // The derived resources, then config.additionalResources not among them. export function listResources(config: MockServerConfig): ResourceItem[] { if (config.resources) return config.resources; const resources = deriveResources(config); const listed = new Set(resources.map(resourceKey)); for (const resource of config.additionalResources ?? []) { if (listed.has(resourceKey(resource))) continue; listed.add(resourceKey(resource)); resources.push(resource); } return resources; } export function handleResourcesRequest( message: GenesisMessage, connection: Connection, config: MockServerConfig, ): void { connection.reply(message, { MESSAGE_TYPE: MESSAGE_TYPE.RESOURCES_REQUEST_ACK, RESOURCES: listResources(config), }); }