// @ts-check
import { randomUUID } from 'node:crypto';
/**
* Common HTTP envelope for the new Members service endpoints (Projects, Shares,
* Snapshots, Event replay). See 080-Workspaces/018-Cross-Service-Contracts.mdx.
*
* Success: { success: true, result, request_id, schema_version }
* Error: { success: false, error: { code, message, details }, request_id, schema_version }
*
* Legacy routes keep their own envelope; only the new endpoints use this one.
*/
export const SCHEMA_VERSION = 1;
/** @param {import('express').Request} req */
const requestId = (req) => req?.headers?.['x-request-id'] || `req-${randomUUID()}`;
/**
* Send a successful response using the contract envelope.
* @param {import('express').Response} res
* @param {any} result
*/
export const sendOk = (res, result) => {
res.json({
success: true,
result,
request_id: requestId(res.req),
schema_version: SCHEMA_VERSION,
});
};
/**
* Send an error response using the contract envelope.
* @param {import('express').Response} res
* @param {number} status
* @param {string} code
* @param {string} message
* @param {any} [details]
*/
export const sendError = (res, status, code, message, details = undefined) => {
res.status(status).json({
success: false,
error: { code, message, details },
request_id: requestId(res.req),
schema_version: SCHEMA_VERSION,
});
};
/**
* Normalize a thrown error into a contract error response. Errors that already
* carry an ApiError shape (code/status) are honoured; everything else becomes 500.
* @param {import('express').Response} res
* @param {any} error
*/
export const sendErrorFrom = (res, error) => {
if (error && error.status && error.code) {
sendError(res, error.status, error.code, error.message, error.details);
return;
}
sendError(res, 500, 'INTERNAL_ERROR', error?.message || 'Internal server error');
};
/**
* Create an ApiError carrying an HTTP status and a machine-readable code.
* @param {number} status
* @param {string} code
* @param {string} message
* @param {any} [details]
*/
export const apiError = (status, code, message, details = undefined) => {
const err = new Error(message);
err.status = status;
err.code = code;
err.details = details;
return err;
};