shelving
Version:
Toolkit for using data in JavaScript.
69 lines (68 loc) • 2.88 kB
JavaScript
import { getResponse } from "../util/http.js";
import { UNDEFINED } from "../util/validate.js";
/**
* An abstract API resource definition, used to specify types for e.g. serverless functions.
*
* @param method The method of the resource, e.g. `GET`
* @param path The path of the resource optionally including `{placeholder}` values, e.g. `/patient/{id}`
* @param payload A `Validator` for the payload of the resource.
* @param result A `Validator` for the result of the resource.
*/
export class Endpoint {
/** Endpoint method. */
method;
/** Endpoint path, e.g. `/patient/{id}` */
path;
/** Payload validator. */
payload;
/** Result validator. */
result;
constructor(method, path, payload, result) {
this.method = method;
this.path = path;
this.payload = payload;
this.result = result;
}
/**
* Return an `EndpointHandler` for this endpoint.
*
* @param callback The callback function that implements the logic for this endpoint by receiving the payload and returning the response.
*/
handler(callback) {
return { endpoint: this, callback };
}
/**
* Handle a request to this endpoint with a callback implementation, with a given payload and request.
*
* @param callback The endpoint callback function that implements the logic for this endpoint by receiving the payload and returning the response.
* @param unsafePayload The payload to pass into the callback (will be validated against this endpoint's payload schema).
* @param request The entire HTTP request that is being handled (payload was possibly extracted from this somehow).
*/
async handle(callback, unsafePayload, request) {
// Validate the payload against this endpoint's payload type.
const payload = this.payload.validate(unsafePayload);
// Call the callback with the validated payload to get the result.
const result = await callback(payload, request);
// Convert the result to a `Response` object.
return getResponse(result);
}
/** Convert to string, e.g. `GET /user/{id}` */
toString() {
return `${this.method} ${this.path}`;
}
}
export function GET(path, payload, result) {
return new Endpoint("GET", path, payload || UNDEFINED, result || UNDEFINED);
}
export function POST(path, payload, result) {
return new Endpoint("POST", path, payload || UNDEFINED, result || UNDEFINED);
}
export function PUT(path, payload, result) {
return new Endpoint("PUT", path, payload || UNDEFINED, result || UNDEFINED);
}
export function PATCH(path, payload, result) {
return new Endpoint("PATCH", path, payload || UNDEFINED, result || UNDEFINED);
}
export function DELETE(path, payload, result) {
return new Endpoint("DELETE", path, payload || UNDEFINED, result || UNDEFINED);
}