UNPKG

@nahkies/typescript-koa-runtime

Version:

Runtime package for code generated by @nahkies/openapi-code-generator using the typescript-koa template

1 lines 14 kB
{"version":3,"file":"server.cjs","names":["KoaRuntimeError","Koa"],"sources":["../../../typescript-common-runtime/dist/esm/request-bodies/octet-stream.mjs","../../../typescript-common-runtime/dist/esm/types.mjs","../../../typescript-common-runtime/dist/esm/query-parser.mjs","../../src/server.ts"],"sourcesContent":["import getRawBody from \"raw-body\";\n//#region src/request-bodies/octet-stream.ts\nasync function parseOctetStreamRequestBody(req, opts) {\n\tconst contentLength = opts.contentLength ?? (req.headers[\"content-length\"] ? parseInt(req.headers[\"content-length\"], 10) : void 0);\n\tif (!contentLength) throw new Error(\"No content length provided\");\n\tconst body = await getRawBody(req, {\n\t\tlength: contentLength,\n\t\tlimit: opts.sizeLimit\n\t});\n\tif (!body) return;\n\tif (!Buffer.isBuffer(body)) throw new Error(\"body must be a buffer\");\n\treturn new Blob([new Uint8Array(body)], { type: \"application/octet-stream\" });\n}\n//#endregion\nexport { parseOctetStreamRequestBody };\n\n//# sourceMappingURL=octet-stream.mjs.map","//#region src/types.ts\nconst SkipResponse = Symbol.for(\"skip response processing\");\nfunction isNonEmptyArray(it) {\n\treturn Array.isArray(it) && it.length > 0;\n}\n//#endregion\nexport { SkipResponse, isNonEmptyArray };\n\n//# sourceMappingURL=types.mjs.map","//#region src/query-parser.ts\nconst separators = {\n\tdeepObject: \",\",\n\tform: \",\",\n\tpipeDelimited: \"|\",\n\tspaceDelimited: \" \"\n};\nfunction parseCsvPairsToObject(str, sep) {\n\tconst split = str.split(sep);\n\tconst result = {};\n\tfor (let i = 0; i < split.length; i += 2) {\n\t\tconst key = split[i];\n\t\tconst value = split[i + 1];\n\t\tif (key) result[key] = value;\n\t}\n\treturn result;\n}\nfunction escapeStringForRegExp(str) {\n\treturn str.replace(/[|\\\\{}()[\\]^$+*?.]/g, \"\\\\$&\").replace(/-/g, \"\\\\x2d\");\n}\n/**\n* Returns an ordered list of keys that match the provided key with array notation. E.g.,\n* For key \"foo\" return [\"foo[0]\", \"foo[1]\", \"foo[2]\", ...]\n*/\nfunction extractArrayNotationKeys(key, keys) {\n\tconst regex = new RegExp(`^${escapeStringForRegExp(key)}\\\\[[0-9]+]$`);\n\treturn Array.from(keys).filter((it) => regex.test(it)).sort();\n}\nfunction parseObjectQueryParameter(key, schema, encoding, query) {\n\tconst type = schema.type;\n\tif (encoding.explode) if (encoding.style === \"deepObject\") {\n\t\tif (type === \"object\") {\n\t\t\tconst result = {};\n\t\t\tfor (const [subKey, subSchema] of Object.entries(schema.properties)) if (subSchema.type === \"object\") result[subKey] = parseObjectQueryParameter(`${key}[${subKey}]`, subSchema, encoding, query);\n\t\t\telse result[subKey] = query.get(`${key}[${subKey}]`) ?? void 0;\n\t\t\treturn result;\n\t\t}\n\t\tthrow new Error(`[expected to be unreachable] parseObjectQueryParameter: unsupported parameter type: ${type} for explode: ${encoding.explode}, style: ${encoding.style}`);\n\t} else {\n\t\tif (type === \"object\") {\n\t\t\tconst result = {};\n\t\t\tfor (const it of Object.keys(schema.properties)) result[it] = query.get(it) ?? void 0;\n\t\t\treturn result;\n\t\t}\n\t\tthrow new Error(`[expected to be unreachable] parseObjectQueryParameter: unsupported parameter type: ${type} for explode: ${encoding.explode}, style: ${encoding.style}`);\n\t}\n\telse if ([\n\t\t\"form\",\n\t\t\"spaceDelimited\",\n\t\t\"pipeDelimited\"\n\t].includes(encoding.style)) {\n\t\tconst sep = separators[encoding.style];\n\t\treturn parseCsvPairsToObject(query.get(key) ?? \"\", sep);\n\t} else return JSON.parse(query.get(key) ?? \"null\");\n}\nfunction parseArrayQueryParameter(key, _schema, encoding, query) {\n\tif (encoding.explode) {\n\t\tif (encoding.style === \"deepObject\") return extractArrayNotationKeys(key, query.keys()).map((it) => query.get(it) ?? void 0);\n\t\treturn query.getAll(key);\n\t} else return query.get(key)?.split(separators[encoding.style]);\n}\nfunction parsePrimitiveQueryParameter(key, query) {\n\treturn query.get(key) ?? void 0;\n}\nfunction parseQueryParameter({ name, schema, explode, style }, query) {\n\tconst encoding = {\n\t\tstyle: style ?? \"form\",\n\t\texplode: explode ?? true\n\t};\n\tconst type = schema.type;\n\tswitch (type) {\n\t\tcase \"object\": return parseObjectQueryParameter(name, schema, encoding, query);\n\t\tcase \"array\": return parseArrayQueryParameter(name, schema, encoding, query);\n\t\tcase \"string\":\n\t\tcase \"number\":\n\t\tcase \"boolean\":\n\t\tcase \"null\": return parsePrimitiveQueryParameter(name, query);\n\t\tdefault: throw new Error(`unsupported parameter type: ${type}`);\n\t}\n}\nfunction parseQueryParameters(rawQuery, parameters) {\n\tconst query = new URLSearchParams(rawQuery);\n\tconst result = {};\n\tfor (const parameter of parameters) result[parameter.name] = parseQueryParameter(parameter, query);\n\treturn result;\n}\n//#endregion\nexport { extractArrayNotationKeys, parseCsvPairsToObject, parseQueryParameter, parseQueryParameters };\n\n//# sourceMappingURL=query-parser.mjs.map","import type {Server} from \"node:http\"\nimport type {AddressInfo, ListenOptions} from \"node:net\"\nimport Cors from \"@koa/cors\"\nimport type Router from \"@koa/router\"\nimport type {SizeLimit} from \"@nahkies/typescript-common-runtime/request-bodies/octet-stream\"\nimport {parseOctetStreamRequestBody} from \"@nahkies/typescript-common-runtime/request-bodies/octet-stream\"\nimport {\n type Res,\n SkipResponse,\n type StatusCode,\n} from \"@nahkies/typescript-common-runtime/types\"\nimport Koa, {type Context, type Middleware} from \"koa\"\nimport {type KoaBodyMiddlewareOptions, koaBody} from \"koa-body\"\nimport {KoaRuntimeError} from \"./errors.ts\"\n\nexport {parseQueryParameters} from \"@nahkies/typescript-common-runtime/query-parser\"\n\nexport {\n type Params,\n type Res,\n SkipResponse,\n type StatusCode,\n type StatusCode1xx,\n type StatusCode2xx,\n type StatusCode3xx,\n type StatusCode4xx,\n type StatusCode5xx,\n} from \"@nahkies/typescript-common-runtime/types\"\n\nexport class KoaRuntimeResponse<Type> {\n private _body?: Type\n\n constructor(private readonly status: StatusCode) {}\n\n body(body: Type): this {\n this._body = body\n return this\n }\n\n unpack(): Res<StatusCode, Type | undefined> {\n return {status: this.status, body: this._body}\n }\n}\n\nexport function handleResponse(\n ctx: Context,\n validator: (status: number, value: unknown) => unknown,\n) {\n return async (\n response:\n | KoaRuntimeResponse<unknown>\n | typeof SkipResponse\n | Res<StatusCode, unknown>,\n ): Promise<void> => {\n // escape hatch to allow responses to be sent by the implementation handler\n if (response === SkipResponse) {\n return\n }\n\n const {status, body} =\n response instanceof KoaRuntimeResponse ? response.unpack() : response\n\n ctx.body = validator(status, body)\n ctx.status = status\n }\n}\n\nexport function handleImplementationError(err: unknown): never {\n throw KoaRuntimeError.HandlerError(err)\n}\n\nexport type KoaRuntimeResponder<\n Status extends StatusCode = StatusCode,\n // biome-ignore lint/suspicious/noExplicitAny: needed\n Type = any,\n> = {\n withStatus: (status: Status) => KoaRuntimeResponse<Type>\n}\n\nexport type ServerConfig = {\n /**\n * set to \"disabled\" to disable cors middleware, omit or pass undefined for defaults\n *\n * the default behavior is to allow all origins\n **/\n cors?: \"disabled\" | Cors.Options | undefined\n\n /**\n * set to \"disabled\" to disable body parsing middleware, omit or pass undefined for defaults.\n *\n * if disabling, ensure you pass a body parsing middleware that places the parsed\n * body on `ctx.body` for request body processing to work.\n **/\n body?: \"disabled\" | Partial<KoaBodyMiddlewareOptions> | undefined\n\n /**\n * allows you to provide arbitrary koa middleware\n * useful for mounting logging, error handlers, 404 handling, alternative body parsers, etc.\n */\n middleware?: Middleware[]\n\n /**\n * the router to use, normally obtained by calling the generated `createRouter`\n * function\n */\n router: Router\n\n /**\n * the port to listen on, a randomly allocated port will be used if none passed\n * alternatively ListenOptions can be passed to control the network interface\n * bound to.\n */\n port?: number | ListenOptions\n}\n\nexport async function parseOctetStream(\n ctx: Context,\n sizeLimit: SizeLimit,\n): Promise<Blob | undefined> {\n const body = await parseOctetStreamRequestBody(ctx.req, {sizeLimit})\n ctx.body = body\n return body\n}\n\n/**\n * Starts a Koa server and listens on `port` or a randomly allocated port if none provided.\n * Enables CORS and body parsing by default. It's recommended to customize the CORS options\n * for production usage.\n *\n * If you need more control over your Koa server, you should avoid calling this function\n * and instead mount the router from your generated codes `createRouter` call directly\n * onto a server you have constructed.\n */\nexport async function startServer({\n middleware = [],\n cors = undefined,\n body = undefined,\n port = 0,\n router,\n}: ServerConfig): Promise<{\n app: Koa\n server: Server\n address: AddressInfo\n}> {\n const app = new Koa()\n\n if (cors !== \"disabled\") {\n app.use(Cors(cors))\n }\n\n if (body !== \"disabled\") {\n app.use(koaBody(body))\n }\n\n for (const it of middleware) {\n app.use(it)\n }\n\n app.use(router.routes())\n app.use(router.allowedMethods())\n\n return new Promise((resolve, reject) => {\n try {\n const server = app.listen(port)\n\n server.once(\"listening\", () => {\n try {\n const address = server.address()\n\n if (!address || typeof address !== \"object\") {\n throw new Error(\"failed to bind port\")\n }\n\n resolve({app, server, address})\n } catch (err) {\n reject(err)\n }\n })\n\n server.once(\"error\", (err) => {\n reject(err)\n })\n } catch (err) {\n reject(err)\n }\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,eAAe,4BAA4B,KAAK,MAAM;CACrD,MAAM,gBAAgB,KAAK,kBAAkB,IAAI,QAAQ,oBAAoB,SAAS,IAAI,QAAQ,mBAAmB,EAAE,IAAI,KAAK;CAChI,IAAI,CAAC,eAAe,MAAM,IAAI,MAAM,4BAA4B;CAChE,MAAM,OAAO,OAAA,GAAA,SAAA,SAAiB,KAAK;EAClC,QAAQ;EACR,OAAO,KAAK;CACb,CAAC;CACD,IAAI,CAAC,MAAM;CACX,IAAI,CAAC,OAAO,SAAS,IAAI,GAAG,MAAM,IAAI,MAAM,uBAAuB;CACnE,OAAO,IAAI,KAAK,CAAC,IAAI,WAAW,IAAI,CAAC,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAC7E;;;ACXA,MAAM,eAAe,OAAO,IAAI,0BAA0B;;;ACA1D,MAAM,aAAa;CAClB,YAAY;CACZ,MAAM;CACN,eAAe;CACf,gBAAgB;AACjB;AACA,SAAS,sBAAsB,KAAK,KAAK;CACxC,MAAM,QAAQ,IAAI,MAAM,GAAG;CAC3B,MAAM,SAAS,CAAC;CAChB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACzC,MAAM,MAAM,MAAM;EAClB,MAAM,QAAQ,MAAM,IAAI;EACxB,IAAI,KAAK,OAAO,OAAO;CACxB;CACA,OAAO;AACR;AACA,SAAS,sBAAsB,KAAK;CACnC,OAAO,IAAI,QAAQ,uBAAuB,MAAM,EAAE,QAAQ,MAAM,OAAO;AACxE;;;;;AAKA,SAAS,yBAAyB,KAAK,MAAM;CAC5C,MAAM,QAAQ,IAAI,OAAO,IAAI,sBAAsB,GAAG,EAAE,YAAY;CACpE,OAAO,MAAM,KAAK,IAAI,EAAE,QAAQ,OAAO,MAAM,KAAK,EAAE,CAAC,EAAE,KAAK;AAC7D;AACA,SAAS,0BAA0B,KAAK,QAAQ,UAAU,OAAO;CAChE,MAAM,OAAO,OAAO;CACpB,IAAI,SAAS,SAAS,IAAI,SAAS,UAAU,cAAc;EAC1D,IAAI,SAAS,UAAU;GACtB,MAAM,SAAS,CAAC;GAChB,KAAK,MAAM,CAAC,QAAQ,cAAc,OAAO,QAAQ,OAAO,UAAU,GAAG,IAAI,UAAU,SAAS,UAAU,OAAO,UAAU,0BAA0B,GAAG,IAAI,GAAG,OAAO,IAAI,WAAW,UAAU,KAAK;QAC3L,OAAO,UAAU,MAAM,IAAI,GAAG,IAAI,GAAG,OAAO,EAAE,KAAK,KAAK;GAC7D,OAAO;EACR;EACA,MAAM,IAAI,MAAM,uFAAuF,KAAK,gBAAgB,SAAS,QAAQ,WAAW,SAAS,OAAO;CACzK,OAAO;EACN,IAAI,SAAS,UAAU;GACtB,MAAM,SAAS,CAAC;GAChB,KAAK,MAAM,MAAM,OAAO,KAAK,OAAO,UAAU,GAAG,OAAO,MAAM,MAAM,IAAI,EAAE,KAAK,KAAK;GACpF,OAAO;EACR;EACA,MAAM,IAAI,MAAM,uFAAuF,KAAK,gBAAgB,SAAS,QAAQ,WAAW,SAAS,OAAO;CACzK;MACK,IAAI;EACR;EACA;EACA;CACD,EAAE,SAAS,SAAS,KAAK,GAAG;EAC3B,MAAM,MAAM,WAAW,SAAS;EAChC,OAAO,sBAAsB,MAAM,IAAI,GAAG,KAAK,IAAI,GAAG;CACvD,OAAO,OAAO,KAAK,MAAM,MAAM,IAAI,GAAG,KAAK,MAAM;AAClD;AACA,SAAS,yBAAyB,KAAK,SAAS,UAAU,OAAO;CAChE,IAAI,SAAS,SAAS;EACrB,IAAI,SAAS,UAAU,cAAc,OAAO,yBAAyB,KAAK,MAAM,KAAK,CAAC,EAAE,KAAK,OAAO,MAAM,IAAI,EAAE,KAAK,KAAK,CAAC;EAC3H,OAAO,MAAM,OAAO,GAAG;CACxB,OAAO,OAAO,MAAM,IAAI,GAAG,GAAG,MAAM,WAAW,SAAS,MAAM;AAC/D;AACA,SAAS,6BAA6B,KAAK,OAAO;CACjD,OAAO,MAAM,IAAI,GAAG,KAAK,KAAK;AAC/B;AACA,SAAS,oBAAoB,EAAE,MAAM,QAAQ,SAAS,SAAS,OAAO;CACrE,MAAM,WAAW;EAChB,OAAO,SAAS;EAChB,SAAS,WAAW;CACrB;CACA,MAAM,OAAO,OAAO;CACpB,QAAQ,MAAR;EACC,KAAK,UAAU,OAAO,0BAA0B,MAAM,QAAQ,UAAU,KAAK;EAC7E,KAAK,SAAS,OAAO,yBAAyB,MAAM,QAAQ,UAAU,KAAK;EAC3E,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,QAAQ,OAAO,6BAA6B,MAAM,KAAK;EAC5D,SAAS,MAAM,IAAI,MAAM,+BAA+B,MAAM;CAC/D;AACD;AACA,SAAS,qBAAqB,UAAU,YAAY;CACnD,MAAM,QAAQ,IAAI,gBAAgB,QAAQ;CAC1C,MAAM,SAAS,CAAC;CAChB,KAAK,MAAM,aAAa,YAAY,OAAO,UAAU,QAAQ,oBAAoB,WAAW,KAAK;CACjG,OAAO;AACR;;;ACxDA,IAAa,qBAAb,MAAsC;CAGP;CAF7B;CAEA,YAAY,QAAqC;EAApB,KAAA,SAAA;CAAqB;CAElD,KAAK,MAAkB;EACrB,KAAK,QAAQ;EACb,OAAO;CACT;CAEA,SAA4C;EAC1C,OAAO;GAAC,QAAQ,KAAK;GAAQ,MAAM,KAAK;EAAK;CAC/C;AACF;AAEA,SAAgB,eACd,KACA,WACA;CACA,OAAO,OACL,aAIkB;EAElB,IAAI,aAAa,cACf;EAGF,MAAM,EAAC,QAAQ,SACb,oBAAoB,qBAAqB,SAAS,OAAO,IAAI;EAE/D,IAAI,OAAO,UAAU,QAAQ,IAAI;EACjC,IAAI,SAAS;CACf;AACF;AAEA,SAAgB,0BAA0B,KAAqB;CAC7D,MAAMA,eAAAA,gBAAgB,aAAa,GAAG;AACxC;AA8CA,eAAsB,iBACpB,KACA,WAC2B;CAC3B,MAAM,OAAO,MAAM,4BAA4B,IAAI,KAAK,EAAC,UAAS,CAAC;CACnE,IAAI,OAAO;CACX,OAAO;AACT;;;;;;;;;;AAWA,eAAsB,YAAY,EAChC,aAAa,CAAC,GACd,OAAO,KAAA,GACP,OAAO,KAAA,GACP,OAAO,GACP,UAKC;CACD,MAAM,MAAM,IAAIC,IAAAA,QAAI;CAEpB,IAAI,SAAS,YACX,IAAI,KAAA,GAAA,UAAA,SAAS,IAAI,CAAC;CAGpB,IAAI,SAAS,YACX,IAAI,KAAA,GAAA,SAAA,SAAY,IAAI,CAAC;CAGvB,KAAK,MAAM,MAAM,YACf,IAAI,IAAI,EAAE;CAGZ,IAAI,IAAI,OAAO,OAAO,CAAC;CACvB,IAAI,IAAI,OAAO,eAAe,CAAC;CAE/B,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAI;GACF,MAAM,SAAS,IAAI,OAAO,IAAI;GAE9B,OAAO,KAAK,mBAAmB;IAC7B,IAAI;KACF,MAAM,UAAU,OAAO,QAAQ;KAE/B,IAAI,CAAC,WAAW,OAAO,YAAY,UACjC,MAAM,IAAI,MAAM,qBAAqB;KAGvC,QAAQ;MAAC;MAAK;MAAQ;KAAO,CAAC;IAChC,SAAS,KAAK;KACZ,OAAO,GAAG;IACZ;GACF,CAAC;GAED,OAAO,KAAK,UAAU,QAAQ;IAC5B,OAAO,GAAG;GACZ,CAAC;EACH,SAAS,KAAK;GACZ,OAAO,GAAG;EACZ;CACF,CAAC;AACH"}