Tutorial – Published REST API

Goal for this step 🏁: Add a REST API to the backend for published client.

Similarly we can setup the published REST API. In backend/main.ts we expose a GET endpoint at /api/published/:operationName:

import {
executeJsonPublishedDossierClientOperation,
type JsonPublishedDossierClientOperationArgs,
} from '@dossierhq/core';

app.get(
'/api/published/:operationName',
asyncHandler(async (req, res) => {
const publishedClient = getPublishedClientForRequest(server, req);
const { operationName } = req.params;
const operationArgs = decodeURLSearchParamsParam<JsonPublishedDossierClientOperationArgs>(
req.query as Record<string, string>,
'args'
);
if (!operationArgs) {
sendResult(res, notOk.BadRequest('Missing args'));
} else {
sendResult(
res,
await executeJsonPublishedDossierClientOperation(publishedClient, operationName, operationArgs)
);
}
})
);

And to create a published client in the frontend we add this to src/ClientUtils.ts:

import {
convertJsonPublishedDossierClientResult,
createBasePublishedDossierClient,
type PublishedDossierClientOperation,
} from '@dossierhq/core';
import type { AppPublishedDossierClient } from './SchemaTypes.js';

export function usePublishedClient(): AppPublishedDossierClient | null {
return useMemo(
() =>
createBasePublishedDossierClient<ClientContext, AppPublishedDossierClient>({
context: { logger },
pipeline: [createPublishedBackendMiddleware()],
}),
[]
);
}

function createPublishedBackendMiddleware() {
return async (context: ClientContext, operation: PublishedDossierClientOperation): Promise<void> => {
const response = await fetch(
`/api/published/${operation.name}?${encodeObjectToURLSearchParams(
{ args: operation.args },
{ keepEmptyObjects: true }
)}`
);
const result = await getBodyAsJsonResult(response);
operation.resolve(convertJsonPublishedDossierClientResult(operation.name, result));
};
}

In the next step we'll use the published client in the web interface.