@nahkies/typescript-express-runtime
Version:
Runtime package for code generated by @nahkies/openapi-code-generator using the typescript-express template
236 lines (235 loc) • 8.5 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
const require_errors = require("./errors-tNsCEbdN.cjs");
let cors = require("cors");
cors = __toESM(cors, 1);
let express = require("express");
express = __toESM(express, 1);
let raw_body = require("raw-body");
raw_body = __toESM(raw_body, 1);
//#region ../typescript-common-runtime/dist/esm/types.mjs
const SkipResponse = Symbol.for("skip response processing");
//#endregion
//#region ../typescript-common-runtime/dist/esm/query-parser.mjs
const separators = {
deepObject: ",",
form: ",",
pipeDelimited: "|",
spaceDelimited: " "
};
function parseCsvPairsToObject(str, sep) {
const split = str.split(sep);
const result = {};
for (let i = 0; i < split.length; i += 2) {
const key = split[i];
const value = split[i + 1];
if (key) result[key] = value;
}
return result;
}
function escapeStringForRegExp(str) {
return str.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
}
/**
* Returns an ordered list of keys that match the provided key with array notation. E.g.,
* For key "foo" return ["foo[0]", "foo[1]", "foo[2]", ...]
*/
function extractArrayNotationKeys(key, keys) {
const regex = new RegExp(`^${escapeStringForRegExp(key)}\\[[0-9]+]$`);
return Array.from(keys).filter((it) => regex.test(it)).sort();
}
function parseObjectQueryParameter(key, schema, encoding, query) {
const type = schema.type;
if (encoding.explode) if (encoding.style === "deepObject") {
if (type === "object") {
const result = {};
for (const [subKey, subSchema] of Object.entries(schema.properties)) if (subSchema.type === "object") result[subKey] = parseObjectQueryParameter(`${key}[${subKey}]`, subSchema, encoding, query);
else result[subKey] = query.get(`${key}[${subKey}]`) ?? void 0;
return result;
}
throw new Error(`[expected to be unreachable] parseObjectQueryParameter: unsupported parameter type: ${type} for explode: ${encoding.explode}, style: ${encoding.style}`);
} else {
if (type === "object") {
const result = {};
for (const it of Object.keys(schema.properties)) result[it] = query.get(it) ?? void 0;
return result;
}
throw new Error(`[expected to be unreachable] parseObjectQueryParameter: unsupported parameter type: ${type} for explode: ${encoding.explode}, style: ${encoding.style}`);
}
else if ([
"form",
"spaceDelimited",
"pipeDelimited"
].includes(encoding.style)) {
const sep = separators[encoding.style];
return parseCsvPairsToObject(query.get(key) ?? "", sep);
} else return JSON.parse(query.get(key) ?? "null");
}
function parseArrayQueryParameter(key, _schema, encoding, query) {
if (encoding.explode) {
if (encoding.style === "deepObject") return extractArrayNotationKeys(key, query.keys()).map((it) => query.get(it) ?? void 0);
return query.getAll(key);
} else return query.get(key)?.split(separators[encoding.style]);
}
function parsePrimitiveQueryParameter(key, query) {
return query.get(key) ?? void 0;
}
function parseQueryParameter({ name, schema, explode, style }, query) {
const encoding = {
style: style ?? "form",
explode: explode ?? true
};
const type = schema.type;
switch (type) {
case "object": return parseObjectQueryParameter(name, schema, encoding, query);
case "array": return parseArrayQueryParameter(name, schema, encoding, query);
case "string":
case "number":
case "boolean":
case "null": return parsePrimitiveQueryParameter(name, query);
default: throw new Error(`unsupported parameter type: ${type}`);
}
}
function parseQueryParameters(rawQuery, parameters) {
const query = new URLSearchParams(rawQuery);
const result = {};
for (const parameter of parameters) result[parameter.name] = parseQueryParameter(parameter, query);
return result;
}
//#endregion
//#region ../typescript-common-runtime/dist/esm/request-bodies/octet-stream.mjs
async function parseOctetStreamRequestBody(req, opts) {
const contentLength = opts.contentLength ?? (req.headers["content-length"] ? parseInt(req.headers["content-length"], 10) : void 0);
if (!contentLength) throw new Error("No content length provided");
const body = await (0, raw_body.default)(req, {
length: contentLength,
limit: opts.sizeLimit
});
if (!body) return;
if (!Buffer.isBuffer(body)) throw new Error("body must be a buffer");
return new Blob([new Uint8Array(body)], { type: "application/octet-stream" });
}
//#endregion
//#region src/server.ts
var ExpressRuntimeResponse = class {
status;
_body;
constructor(status) {
this.status = status;
}
body(body) {
this._body = body;
return this;
}
unpack() {
return {
status: this.status,
body: this._body
};
}
};
function handleResponse(res, validator) {
return async (response) => {
if (response === SkipResponse) return;
const { status, body } = response instanceof ExpressRuntimeResponse ? response.unpack() : response;
res.status(status);
if (body === void 0) {
res.end();
return;
}
if (body instanceof Blob) await sendBlob(res, body);
else res.json(validator(status, body));
};
}
function handleImplementationError(err) {
throw require_errors.ExpressRuntimeError.HandlerError(err);
}
/**
* Starts an Express server and listens on `port` or a randomly allocated port if none provided.
* Enables CORS and body parsing by default. It's recommended to customize the CORS options
* for production usage.
*
* If you need more control over your Express server you should avoid calling this function,
* and instead mount the router from your generated codes `createRouter` call directly
* onto a server you have constructed.
*/
async function startServer({ middleware = [], cors: cors$1 = void 0, body = void 0, port = 0, router, notFoundHandler, errorHandler }) {
const app = (0, express.default)();
if (cors$1 !== "disabled") {
app.use((0, cors.default)(cors$1));
app.options("*route", (0, cors.default)(cors$1));
}
if (body !== "disabled") {
app.use(express.default.json(body?.json));
app.use(express.default.text(body?.text));
app.use(express.default.urlencoded(body?.urlencoded ?? { extended: true }));
}
if (middleware) for (const it of middleware) app.use(it);
app.use(router);
if (notFoundHandler) app.use(notFoundHandler);
if (errorHandler) app.use(errorHandler);
return new Promise((resolve, reject) => {
try {
const server = app.listen(port);
server.once("listening", () => {
try {
const address = server.address();
if (!address || typeof address !== "object") throw new Error("failed to bind port");
resolve({
app,
server,
address
});
} catch (err) {
reject(err);
}
});
server.once("error", (err) => {
reject(err);
});
} catch (err) {
reject(err);
}
});
}
async function parseOctetStream(req, sizeLimit) {
return parseOctetStreamRequestBody(req, { sizeLimit });
}
async function sendBlob(res, body) {
const arrayBuffer = await body.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
res.setHeader("Content-Type", body.type ?? "application/octet-stream");
res.setHeader("Content-Length", buffer.length);
res.send(buffer);
}
//#endregion
exports.ExpressRuntimeResponse = ExpressRuntimeResponse;
exports.SkipResponse = SkipResponse;
exports.handleImplementationError = handleImplementationError;
exports.handleResponse = handleResponse;
exports.parseOctetStream = parseOctetStream;
exports.parseQueryParameters = parseQueryParameters;
exports.sendBlob = sendBlob;
exports.startServer = startServer;
//# sourceMappingURL=server.cjs.map