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 {
executePublishedClientOperationFromJson,
type PublishedClientJsonOperationArgs,
} from '@dossierhq/core';
app.get(
'/api/published/:operationName',
asyncHandler(async (req, res) => {
const publishedClient = getPublishedClientForRequest(server, req);
const { operationName } = req.params;
const operationArgs = decodeURLSearchParamsParam<PublishedClientJsonOperationArgs>(
req.query as Record<string, string>,
'args'
);
if (!operationArgs) {
sendResult(res, notOk.BadRequest('Missing args'));
} else {
sendResult(
res,
await executePublishedClientOperationFromJson(publishedClient, operationName, operationArgs)
);
}
})
);
And to create a published client in the frontend we add this to src/ClientUtils.ts
:
import {
convertJsonPublishedClientResult,
createBasePublishedClient,
type PublishedClientOperation,
} from '@dossierhq/core';
import type { AppPublishedClient } from './SchemaTypes.js';
export function usePublishedClient(): AppPublishedClient | null {
return useMemo(
() =>
createBasePublishedClient<ClientContext, AppPublishedClient>({
context: { logger },
pipeline: [createPublishedBackendMiddleware()],
}),
[]
);
}
function createPublishedBackendMiddleware() {
return async (context: ClientContext, operation: PublishedClientOperation): Promise<void> => {
const response = await fetch(
`/api/published/${operation.name}?${encodeObjectToURLSearchParams(
{ args: operation.args },
{ keepEmptyObjects: true }
)}`
);
const result = await getBodyAsJsonResult(response);
operation.resolve(convertJsonPublishedClientResult(operation.name, result));
};
}
In the next step we'll use the published client in the web interface.