@kosmojs/api 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "type": "module",
3
+ "name": "@kosmojs/api",
4
+ "version": "0.0.0",
5
+ "author": "Slee Woo",
6
+ "license": "MIT",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "files": [
11
+ "pkg/*"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./pkg/src/index.d.ts",
16
+ "default": "./pkg/index.js"
17
+ },
18
+ "./bodyparser": {
19
+ "types": "./pkg/src/bodyparser/index.d.ts",
20
+ "default": "./pkg/bodyparser/index.js"
21
+ },
22
+ "./queryparser": {
23
+ "types": "./pkg/src/queryparser/index.d.ts",
24
+ "default": "./pkg/queryparser/index.js"
25
+ },
26
+ "./debug": {
27
+ "types": "./pkg/src/debug.d.ts",
28
+ "default": "./pkg/debug.js"
29
+ }
30
+ },
31
+ "dependencies": {
32
+ "@koa/router": "^14.0.0",
33
+ "formidable": "^3.5.4",
34
+ "koa": "^3.1.1",
35
+ "picomatch": "^4.0.3",
36
+ "qs": "^6.14.0",
37
+ "raw-body": "^3.0.1",
38
+ "string-width": "^8.1.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/formidable": "^3.4.6",
42
+ "@types/koa": "^3.0.1",
43
+ "@types/koa__router": "^12.0.5",
44
+ "@types/picomatch": "^4.0.2",
45
+ "@types/qs": "^6.14.0",
46
+ "@kosmojs/config": "^0.0.0",
47
+ "@kosmojs/devlib": "^0.0.0"
48
+ },
49
+ "scripts": {
50
+ "build": "esbuilder src/index.ts src/bodyparser/index.ts src/queryparser/index.ts src/debug.ts",
51
+ "test": "vitest --root ../../.. --project core/api"
52
+ }
53
+ }
@@ -0,0 +1,111 @@
1
+ // src/bodyparser/index.ts
2
+ import zlib from "node:zlib";
3
+ import IncomingForm from "formidable";
4
+ import rawParser from "raw-body";
5
+
6
+ // src/bodyparser/config.ts
7
+ var json = {
8
+ limit: 1024 ** 2,
9
+ trim: ["*"]
10
+ };
11
+ var form = {
12
+ limit: 1024 ** 2
13
+ };
14
+ var raw = {
15
+ limit: 1024 ** 2
16
+ };
17
+ var config_default = {
18
+ json,
19
+ form,
20
+ raw
21
+ };
22
+
23
+ // src/bodyparser/index.ts
24
+ var bodyparser_default = { json: json2, form: form2, raw: raw2 };
25
+ function json2(opts = {}) {
26
+ return [
27
+ async (ctx, next) => {
28
+ const form3 = IncomingForm({
29
+ maxFieldsSize: opts.limit || config_default.json.limit,
30
+ ...opts
31
+ });
32
+ const trimmer = trimmerFactory(opts.trim);
33
+ ctx.request.body = await new Promise((resolve, reject) => {
34
+ form3.parse(ctx.request.req, (err, fields) => {
35
+ if (err) {
36
+ return reject(err);
37
+ }
38
+ resolve(trimmer ? trimmer(fields) : fields);
39
+ });
40
+ });
41
+ return next();
42
+ }
43
+ ];
44
+ }
45
+ function form2(opts = {}) {
46
+ return [
47
+ async (ctx, next) => {
48
+ const form3 = IncomingForm({
49
+ maxFieldsSize: opts.limit || config_default.form.limit,
50
+ maxFileSize: opts.limit || config_default.form.limit,
51
+ ...opts
52
+ });
53
+ let trimmer = trimmerFactory(opts.trim);
54
+ if (opts.multipart || opts.urlencoded) {
55
+ trimmer = void 0;
56
+ }
57
+ ctx.request.body = await new Promise((resolve, reject) => {
58
+ form3.parse(ctx.request.req, (err, fields, files) => {
59
+ if (err) {
60
+ return reject(err);
61
+ }
62
+ resolve({
63
+ fields: trimmer ? trimmer(fields) : fields,
64
+ files
65
+ });
66
+ });
67
+ });
68
+ return next();
69
+ }
70
+ ];
71
+ }
72
+ function raw2(opts = {}) {
73
+ return [
74
+ async (ctx, next) => {
75
+ const { chunkSize, ...rawParserOptions } = { ...config_default.raw, ...opts };
76
+ const stream = ctx.request.req.pipe(zlib.createUnzip({ chunkSize }));
77
+ ctx.request.body = await rawParser(stream, rawParserOptions);
78
+ return next();
79
+ }
80
+ ];
81
+ }
82
+ function trimmerFactory(trimOption) {
83
+ if (!Array.isArray(trimOption) || !trimOption.length) {
84
+ return;
85
+ }
86
+ const trimableKeys = trimOption.reduce((m, k) => {
87
+ m[k] = true;
88
+ return m;
89
+ }, {});
90
+ const trim = (key, val) => {
91
+ return typeof val === "string" ? trimableKeys[key] || trimableKeys["*"] ? val.trim() : val : val;
92
+ };
93
+ const reducer = (memo, [key, val]) => {
94
+ memo[key] = trim(key, val);
95
+ return memo;
96
+ };
97
+ return (payload) => Object.entries(payload).reduce(
98
+ reducer,
99
+ // accumulator is set to payload intentionally, to avoid duplication of big strings.
100
+ // if using a new object for accumulator then trimmed strings will be duplicated?
101
+ payload
102
+ );
103
+ }
104
+ export {
105
+ config_default as config,
106
+ bodyparser_default as default,
107
+ form2 as form,
108
+ json2 as json,
109
+ raw2 as raw
110
+ };
111
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/bodyparser/index.ts", "../../src/bodyparser/config.ts"],
4
+ "sourcesContent": ["import zlib from \"node:zlib\";\n\nimport IncomingForm from \"formidable\";\nimport rawParser from \"raw-body\";\n\nimport type { Middleware } from \"@kosmojs/api\";\n\nimport config from \"./config\";\nimport type {\n FormOptions,\n JsonOptions,\n RawOptions,\n Trimmer,\n TrimOption,\n} from \"./types\";\n\nexport * from \"./types\";\nexport { config };\nexport default { json, form, raw };\n\nexport function json(opts: JsonOptions = {}): Array<Middleware> {\n return [\n async (ctx, next) => {\n const form = IncomingForm({\n maxFieldsSize: opts.limit || config.json.limit,\n ...opts,\n });\n\n const trimmer = trimmerFactory(opts.trim);\n\n ctx.request.body = await new Promise((resolve, reject) => {\n form.parse(ctx.request.req, (err, fields) => {\n if (err) {\n return reject(err);\n }\n\n resolve(trimmer ? trimmer(fields) : fields);\n });\n });\n\n return next();\n },\n ];\n}\n\nexport function form(opts: FormOptions = {}): Array<Middleware> {\n return [\n async (ctx, next) => {\n const form = IncomingForm({\n maxFieldsSize: opts.limit || config.form.limit,\n maxFileSize: opts.limit || config.form.limit,\n ...opts,\n });\n\n let trimmer = trimmerFactory(opts.trim);\n\n if (opts.multipart || opts.urlencoded) {\n trimmer = undefined;\n }\n\n ctx.request.body = await new Promise((resolve, reject) => {\n form.parse(ctx.request.req, (err, fields, files) => {\n if (err) {\n return reject(err);\n }\n\n resolve({\n fields: trimmer ? trimmer(fields) : fields,\n files,\n });\n });\n });\n\n return next();\n },\n ];\n}\n\nexport function raw(opts: RawOptions = {}): Array<Middleware> {\n return [\n async (ctx, next) => {\n const { chunkSize, ...rawParserOptions } = { ...config.raw, ...opts };\n\n const stream = ctx.request.req.pipe(zlib.createUnzip({ chunkSize }));\n ctx.request.body = await rawParser(stream, rawParserOptions);\n\n return next();\n },\n ];\n}\n\nfunction trimmerFactory(\n trimOption: TrimOption | undefined,\n): Trimmer | undefined {\n if (!Array.isArray(trimOption) || !trimOption.length) {\n return;\n }\n\n const trimableKeys: {\n [key: string]: boolean;\n } = trimOption.reduce((m: Record<string, boolean>, k) => {\n m[k] = true;\n return m;\n }, {});\n\n const trim = (key: string, val: unknown) => {\n return typeof val === \"string\"\n ? trimableKeys[key] || trimableKeys[\"*\"]\n ? val.trim()\n : val\n : val;\n };\n\n const reducer = (\n memo: Record<string, unknown>,\n [key, val]: [string, unknown],\n ) => {\n memo[key] = trim(key, val);\n return memo;\n };\n\n return (payload) =>\n Object.entries(payload).reduce(\n reducer,\n // accumulator is set to payload intentionally, to avoid duplication of big strings.\n // if using a new object for accumulator then trimmed strings will be duplicated?\n payload,\n );\n}\n", "import type { FormOptions, JsonOptions, RawOptions } from \"./types\";\n\nexport const json: JsonOptions = {\n limit: 1024 ** 2,\n trim: [\"*\"],\n};\n\nexport const form: FormOptions = {\n limit: 1024 ** 2,\n};\n\nexport const raw: RawOptions = {\n limit: 1024 ** 2,\n};\n\nexport default {\n json,\n form,\n raw,\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["json", "form", "raw"]
7
+ }
package/pkg/debug.js ADDED
@@ -0,0 +1,62 @@
1
+ // src/debug.ts
2
+ import { styleText } from "node:util";
3
+ import picomatch from "picomatch";
4
+ import stringWidth from "string-width";
5
+ var dot = "\xB7";
6
+ var colorizeMethod = (method) => {
7
+ const color = {
8
+ HEAD: "grey",
9
+ GET: "green",
10
+ POST: "blue",
11
+ PATCH: "blue",
12
+ PUT: "blue",
13
+ DELETE: "red"
14
+ }[method];
15
+ return color ? styleText(color, method) : method;
16
+ };
17
+ var debug_default = (routes, printer, patterns) => {
18
+ const patternMatchers = patterns?.flatMap((pattern) => {
19
+ return pattern?.trim?.() ? [picomatch(pattern)] : [];
20
+ });
21
+ for (const { path, file, methods, slot, debug, kind } of routes.filter(
22
+ ({ name, path: path2 }) => {
23
+ return patternMatchers?.length ? patternMatchers.some((isMatch) => isMatch(name) || isMatch(path2)) : true;
24
+ }
25
+ )) {
26
+ const lines = [];
27
+ lines.push(
28
+ `[ ${styleText("bgBlue", styleText("black", ` ${path} `))} ] ${styleText("gray", file)}`
29
+ );
30
+ const methodsLine = methods.map((method) => {
31
+ const coloredMethod = colorizeMethod(method);
32
+ if (method === "GET" && kind === "handler") {
33
+ return coloredMethod + styleText("gray", "|HEAD");
34
+ }
35
+ return coloredMethod;
36
+ }).join(" ");
37
+ lines.push(`${styleText("dim", " methods:")} ${methodsLine}`);
38
+ if (slot) {
39
+ lines.push(
40
+ `${styleText("dim", " slot: ")} ${styleText("cyan", slot)}`
41
+ );
42
+ }
43
+ if (debug) {
44
+ lines.push(` ${styleText("cyan", debug)}`);
45
+ }
46
+ const maxColumns = process.stdout.isTTY ? Number(process.stdout.columns || 80) : 80;
47
+ for (const line of lines.map((e) => `${e} `)) {
48
+ const freeColumns = maxColumns - stringWidth(line);
49
+ printer(
50
+ freeColumns > 0 ? line + styleText(
51
+ "dim",
52
+ styleText("gray", Array(freeColumns).fill(dot).join(""))
53
+ ) : line
54
+ );
55
+ }
56
+ printer("\n");
57
+ }
58
+ };
59
+ export {
60
+ debug_default as default
61
+ };
62
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/debug.ts"],
4
+ "sourcesContent": ["import { styleText } from \"node:util\";\n\nimport picomatch from \"picomatch\";\nimport stringWidth from \"string-width\";\n\nimport type { RouterRoute } from \"./types\";\n\ntype Printer = (line: string) => void;\n\nconst dot = \"\u00B7\";\n\nconst colorizeMethod = (method: string): string => {\n const color = (\n {\n HEAD: \"grey\",\n GET: \"green\",\n POST: \"blue\",\n PATCH: \"blue\",\n PUT: \"blue\",\n DELETE: \"red\",\n } as const\n )[method];\n return color ? styleText(color, method) : method;\n};\n\nexport default (\n routes: Array<RouterRoute>,\n printer: Printer,\n patterns?: Array<string> | undefined, // picomatch patterns\n) => {\n const patternMatchers = patterns?.flatMap((pattern) => {\n return pattern?.trim?.() ? [picomatch(pattern)] : [];\n });\n\n for (const { path, file, methods, slot, debug, kind } of routes.filter(\n ({ name, path }) => {\n return patternMatchers?.length\n ? patternMatchers.some((isMatch) => isMatch(name) || isMatch(path))\n : true;\n },\n )) {\n const lines: Array<string> = [];\n\n lines.push(\n `[ ${styleText(\"bgBlue\", styleText(\"black\", ` ${path} `))} ] ${styleText(\"gray\", file)}`,\n );\n\n const methodsLine = methods\n .map((method) => {\n const coloredMethod = colorizeMethod(method);\n if (method === \"GET\" && kind === \"handler\") {\n return coloredMethod + styleText(\"gray\", \"|HEAD\");\n }\n return coloredMethod;\n })\n .join(\" \");\n\n lines.push(`${styleText(\"dim\", \" methods:\")} ${methodsLine}`);\n\n if (slot) {\n lines.push(\n `${styleText(\"dim\", \" slot: \")} ${styleText(\"cyan\", slot)}`,\n );\n }\n\n if (debug) {\n lines.push(` ${styleText(\"cyan\", debug)}`);\n }\n\n const maxColumns = process.stdout.isTTY\n ? Number(process.stdout.columns || 80)\n : 80;\n\n for (const line of lines.map((e) => `${e} `)) {\n const freeColumns = maxColumns - stringWidth(line);\n printer(\n freeColumns > 0 //\n ? line +\n styleText(\n \"dim\",\n styleText(\"gray\", Array(freeColumns).fill(dot).join(\"\")),\n )\n : line,\n );\n }\n\n printer(\"\\n\");\n }\n};\n"],
5
+ "mappings": ";AAAA,SAAS,iBAAiB;AAE1B,OAAO,eAAe;AACtB,OAAO,iBAAiB;AAMxB,IAAM,MAAM;AAEZ,IAAM,iBAAiB,CAAC,WAA2B;AACjD,QAAM,QACJ;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,QAAQ;AAAA,EACV,EACA,MAAM;AACR,SAAO,QAAQ,UAAU,OAAO,MAAM,IAAI;AAC5C;AAEA,IAAO,gBAAQ,CACb,QACA,SACA,aACG;AACH,QAAM,kBAAkB,UAAU,QAAQ,CAAC,YAAY;AACrD,WAAO,SAAS,OAAO,IAAI,CAAC,UAAU,OAAO,CAAC,IAAI,CAAC;AAAA,EACrD,CAAC;AAED,aAAW,EAAE,MAAM,MAAM,SAAS,MAAM,OAAO,KAAK,KAAK,OAAO;AAAA,IAC9D,CAAC,EAAE,MAAM,MAAAA,MAAK,MAAM;AAClB,aAAO,iBAAiB,SACpB,gBAAgB,KAAK,CAAC,YAAY,QAAQ,IAAI,KAAK,QAAQA,KAAI,CAAC,IAChE;AAAA,IACN;AAAA,EACF,GAAG;AACD,UAAM,QAAuB,CAAC;AAE9B,UAAM;AAAA,MACJ,KAAK,UAAU,UAAU,UAAU,SAAS,IAAI,IAAI,GAAG,CAAC,CAAC,MAAM,UAAU,QAAQ,IAAI,CAAC;AAAA,IACxF;AAEA,UAAM,cAAc,QACjB,IAAI,CAAC,WAAW;AACf,YAAM,gBAAgB,eAAe,MAAM;AAC3C,UAAI,WAAW,SAAS,SAAS,WAAW;AAC1C,eAAO,gBAAgB,UAAU,QAAQ,OAAO;AAAA,MAClD;AACA,aAAO;AAAA,IACT,CAAC,EACA,KAAK,GAAG;AAEX,UAAM,KAAK,GAAG,UAAU,OAAO,YAAY,CAAC,IAAI,WAAW,EAAE;AAE7D,QAAI,MAAM;AACR,YAAM;AAAA,QACJ,GAAG,UAAU,OAAO,YAAY,CAAC,IAAI,UAAU,QAAQ,IAAI,CAAC;AAAA,MAC9D;AAAA,IACF;AAEA,QAAI,OAAO;AACT,YAAM,KAAK,KAAK,UAAU,QAAQ,KAAK,CAAC,EAAE;AAAA,IAC5C;AAEA,UAAM,aAAa,QAAQ,OAAO,QAC9B,OAAO,QAAQ,OAAO,WAAW,EAAE,IACnC;AAEJ,eAAW,QAAQ,MAAM,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG;AAC5C,YAAM,cAAc,aAAa,YAAY,IAAI;AACjD;AAAA,QACE,cAAc,IACV,OACE;AAAA,UACE;AAAA,UACA,UAAU,QAAQ,MAAM,WAAW,EAAE,KAAK,GAAG,EAAE,KAAK,EAAE,CAAC;AAAA,QACzD,IACF;AAAA,MACN;AAAA,IACF;AAEA,YAAQ,IAAI;AAAA,EACd;AACF;",
6
+ "names": ["path"]
7
+ }
package/pkg/index.js ADDED
@@ -0,0 +1,281 @@
1
+ // src/app.ts
2
+ import Koa from "koa";
3
+ import withQueryparser from "@kosmojs/api/queryparser";
4
+ var createApp = (options) => {
5
+ return withQueryparser(new Koa(options));
6
+ };
7
+
8
+ // src/errors.ts
9
+ var ValidationError = class extends Error {
10
+ scope;
11
+ errors = [];
12
+ errorMessage;
13
+ errorSummary;
14
+ constructor([scope, { errors, errorMessage, errorSummary }]) {
15
+ super(JSON.stringify(errors, null, 2));
16
+ this.name = `${scope}ValidationError`;
17
+ this.scope = scope;
18
+ this.errors = errors;
19
+ this.errorMessage = errorMessage;
20
+ this.errorSummary = errorSummary;
21
+ }
22
+ };
23
+
24
+ // src/router.ts
25
+ import Router from "@koa/router";
26
+
27
+ // src/types.ts
28
+ var HTTPMethods = /* @__PURE__ */ ((HTTPMethods2) => {
29
+ HTTPMethods2["HEAD"] = "HEAD";
30
+ HTTPMethods2["OPTIONS"] = "OPTIONS";
31
+ HTTPMethods2["GET"] = "GET";
32
+ HTTPMethods2["PUT"] = "PUT";
33
+ HTTPMethods2["PATCH"] = "PATCH";
34
+ HTTPMethods2["POST"] = "POST";
35
+ HTTPMethods2["DELETE"] = "DELETE";
36
+ return HTTPMethods2;
37
+ })(HTTPMethods || {});
38
+
39
+ // src/use.ts
40
+ var use = (middleware, options) => {
41
+ return {
42
+ kind: "middleware",
43
+ middleware: [middleware].flat(),
44
+ options
45
+ };
46
+ };
47
+
48
+ // src/router.ts
49
+ var createRouter = (options) => {
50
+ return new Router(options);
51
+ };
52
+ var defineRoute = (factory) => {
53
+ return factory({
54
+ use(middleware, options) {
55
+ return {
56
+ kind: "middleware",
57
+ middleware: [middleware].flat(),
58
+ options
59
+ };
60
+ },
61
+ HEAD(middleware) {
62
+ return {
63
+ kind: "handler",
64
+ middleware: [middleware].flat(),
65
+ method: "HEAD"
66
+ };
67
+ },
68
+ OPTIONS(middleware) {
69
+ return {
70
+ kind: "handler",
71
+ middleware: [middleware].flat(),
72
+ method: "OPTIONS"
73
+ };
74
+ },
75
+ GET(middleware) {
76
+ return {
77
+ kind: "handler",
78
+ middleware: [middleware].flat(),
79
+ method: "GET"
80
+ };
81
+ },
82
+ POST(middleware) {
83
+ return {
84
+ kind: "handler",
85
+ middleware: [middleware].flat(),
86
+ method: "POST"
87
+ };
88
+ },
89
+ PUT(middleware) {
90
+ return {
91
+ kind: "handler",
92
+ middleware: [middleware].flat(),
93
+ method: "PUT"
94
+ };
95
+ },
96
+ PATCH(middleware) {
97
+ return {
98
+ kind: "handler",
99
+ middleware: [middleware].flat(),
100
+ method: "PATCH"
101
+ };
102
+ },
103
+ DELETE(middleware) {
104
+ return {
105
+ kind: "handler",
106
+ middleware: [middleware].flat(),
107
+ method: "DELETE"
108
+ };
109
+ }
110
+ });
111
+ };
112
+ var routerRoutesFactory = (routeSources, {
113
+ // Global middleware applied to every route (e.g., logging)
114
+ coreMiddleware
115
+ }) => {
116
+ const prioritizedSlots = [
117
+ "params",
118
+ // Path params processing
119
+ "validateParams",
120
+ // Path params validation
121
+ "bodyparser",
122
+ // Raw request body parsing
123
+ "payload",
124
+ // Set ctx.payload
125
+ "validatePayload",
126
+ // Payload validation
127
+ "validateResponse"
128
+ // Response validation
129
+ ];
130
+ const stack = [];
131
+ for (const route of routeSources) {
132
+ const {
133
+ name,
134
+ path,
135
+ file,
136
+ definitionItems,
137
+ // Includes both middleware and HTTP method handlers
138
+ params,
139
+ numericParams,
140
+ validationSchemas
141
+ } = route;
142
+ const routeMiddleware = definitionItems.filter(
143
+ (e) => e.kind === "middleware"
144
+ );
145
+ const middlewareStack = [
146
+ ...paramsMiddlewareFactory(params, numericParams),
147
+ ...validationMiddlewareFactory(validationSchemas),
148
+ // core middleware overrides builtin middleware (of same slot)
149
+ ...coreMiddleware,
150
+ // route middleware overrides core middleware (of same slot)
151
+ ...routeMiddleware
152
+ ];
153
+ const routeStack = [
154
+ ...prioritizedSlots.flatMap((slot) => {
155
+ const middleware = middlewareStack.findLast(
156
+ // Using findLast to pick the latest entry,
157
+ // ensuring later entries override earlier ones.
158
+ (e) => e.options?.slot === slot
159
+ );
160
+ return middleware ? [middleware] : [];
161
+ }),
162
+ ...coreMiddleware.flatMap((entry) => {
163
+ if (!entry.options?.slot) {
164
+ return [entry];
165
+ }
166
+ if (prioritizedSlots.includes(entry.options?.slot)) {
167
+ return [];
168
+ }
169
+ const override = routeMiddleware.findLast(
170
+ // Using findLast to pick the latest entry,
171
+ // ensuring later entries override earlier ones.
172
+ (e) => e.options?.slot === entry.options?.slot
173
+ );
174
+ return [override || entry];
175
+ }),
176
+ ...definitionItems.flatMap((entry) => {
177
+ const slot = entry.kind === "middleware" ? entry.options?.slot : void 0;
178
+ if (slot) {
179
+ if (prioritizedSlots.includes(slot)) {
180
+ return [];
181
+ }
182
+ if (coreMiddleware.some((e) => e.options?.slot === slot)) {
183
+ return [];
184
+ }
185
+ }
186
+ return [entry];
187
+ })
188
+ ];
189
+ for (const entry of routeStack) {
190
+ if (entry.kind === "middleware") {
191
+ stack.push({
192
+ name,
193
+ path,
194
+ file,
195
+ methods: entry.options?.on || Object.keys(HTTPMethods),
196
+ middleware: entry.middleware,
197
+ kind: entry.kind,
198
+ slot: entry.options?.slot,
199
+ debug: entry.options?.debug
200
+ });
201
+ } else if (entry.kind === "handler") {
202
+ stack.push({
203
+ name,
204
+ path,
205
+ file,
206
+ methods: [entry.method],
207
+ middleware: entry.middleware,
208
+ kind: entry.kind
209
+ });
210
+ }
211
+ }
212
+ }
213
+ return stack;
214
+ };
215
+ var paramsMiddlewareFactory = (params, numericParams) => [
216
+ use(
217
+ (ctx, next) => {
218
+ ctx.typedParams = params.reduce(
219
+ (map, [name, isRest]) => {
220
+ const value = ctx.params[name];
221
+ if (value) {
222
+ if (isRest) {
223
+ map[name] = numericParams.includes(name) ? value.split("/").map(Number) : value.split("/");
224
+ } else {
225
+ map[name] = numericParams.includes(name) ? Number(value) : value;
226
+ }
227
+ } else {
228
+ map[name] = value;
229
+ }
230
+ return map;
231
+ },
232
+ {}
233
+ );
234
+ return next();
235
+ },
236
+ { slot: "params" }
237
+ )
238
+ ];
239
+ var validationMiddlewareFactory = (validationSchemas) => [
240
+ use(
241
+ (ctx, next) => {
242
+ validationSchemas.params?.validate(ctx.typedParams);
243
+ return next();
244
+ },
245
+ { slot: "validateParams" }
246
+ ),
247
+ use(
248
+ (ctx, next) => {
249
+ validationSchemas.payload?.[ctx.method]?.validate(ctx.payload);
250
+ return next();
251
+ },
252
+ {
253
+ slot: "validatePayload",
254
+ on: Object.keys(validationSchemas.payload || {})
255
+ }
256
+ ),
257
+ use(
258
+ async (ctx, next) => {
259
+ if (validationSchemas.response?.[ctx.method]) {
260
+ await next();
261
+ validationSchemas.response?.[ctx.method]?.validate(ctx.body);
262
+ } else {
263
+ return next();
264
+ }
265
+ },
266
+ {
267
+ slot: "validateResponse",
268
+ on: Object.keys(validationSchemas.response || {})
269
+ }
270
+ )
271
+ ];
272
+ export {
273
+ HTTPMethods,
274
+ ValidationError,
275
+ createApp,
276
+ createRouter,
277
+ defineRoute,
278
+ routerRoutesFactory,
279
+ use
280
+ };
281
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/app.ts", "../src/errors.ts", "../src/router.ts", "../src/types.ts", "../src/use.ts"],
4
+ "sourcesContent": ["import Koa from \"koa\";\n\nimport withQueryparser from \"@kosmojs/api/queryparser\";\n\nimport type { CreateApp } from \"./types\";\n\nexport const createApp: CreateApp = (options) => {\n return withQueryparser(new Koa(options));\n};\n", "import type {\n ValidationErrorData,\n ValidationErrorEntry,\n ValidationErrorScope,\n} from \"./types\";\n\n/**\n * Standardized error wrapper used by validation generators.\n *\n * Instances of this class are thrown whenever validation fails,\n * carrying both the error scope (e.g. `\"params\"`, `\"payload\"`)\n * and the list of validation error details.\n */\nexport class ValidationError extends Error {\n public scope: ValidationErrorScope;\n public errors: Array<ValidationErrorEntry> = [];\n public errorMessage: string;\n public errorSummary: string;\n\n constructor([scope, { errors, errorMessage, errorSummary }]: [\n ValidationErrorScope,\n ValidationErrorData,\n ]) {\n super(JSON.stringify(errors, null, 2));\n this.name = `${scope}ValidationError`;\n this.scope = scope;\n this.errors = errors;\n this.errorMessage = errorMessage;\n this.errorSummary = errorSummary;\n }\n}\n", "import Router from \"@koa/router\";\n\nimport {\n type CreateRouter,\n type DefineRoute,\n type HandlerDefinition,\n HTTPMethods,\n type MiddlewareDefinition,\n type RouterRoute,\n type RouterRouteSource,\n type UseSlots,\n type ValidationSchemas,\n} from \"./types\";\nimport { use } from \"./use\";\n\nexport const createRouter: CreateRouter = (options) => {\n return new Router(options);\n};\n\nexport const defineRoute: DefineRoute = (factory) => {\n return factory({\n use(middleware, options) {\n return {\n kind: \"middleware\",\n middleware: [middleware as never].flat(),\n options,\n };\n },\n HEAD(middleware) {\n return {\n kind: \"handler\",\n middleware: [middleware as never].flat(),\n method: \"HEAD\",\n };\n },\n OPTIONS(middleware) {\n return {\n kind: \"handler\",\n middleware: [middleware as never].flat(),\n method: \"OPTIONS\",\n };\n },\n GET(middleware) {\n return {\n kind: \"handler\",\n middleware: [middleware as never].flat(),\n method: \"GET\",\n };\n },\n POST(middleware) {\n return {\n kind: \"handler\",\n middleware: [middleware as never].flat(),\n method: \"POST\",\n };\n },\n PUT(middleware) {\n return {\n kind: \"handler\",\n middleware: [middleware as never].flat(),\n method: \"PUT\",\n };\n },\n PATCH(middleware) {\n return {\n kind: \"handler\",\n middleware: [middleware as never].flat(),\n method: \"PATCH\",\n };\n },\n DELETE(middleware) {\n return {\n kind: \"handler\",\n middleware: [middleware as never].flat(),\n method: \"DELETE\",\n };\n },\n });\n};\n\nexport const routerRoutesFactory = (\n routeSources: Array<RouterRouteSource>,\n {\n // Global middleware applied to every route (e.g., logging)\n coreMiddleware,\n }: {\n coreMiddleware: Array<MiddlewareDefinition>;\n },\n) => {\n // WARN:: prioritized middleware must run in this exact order!\n const prioritizedSlots: Array<keyof UseSlots> = [\n \"params\", // Path params processing\n \"validateParams\", // Path params validation\n \"bodyparser\", // Raw request body parsing\n \"payload\", // Set ctx.payload\n \"validatePayload\", // Payload validation\n \"validateResponse\", // Response validation\n ];\n\n const stack: Array<RouterRoute> = [];\n\n // Iterate over each route definition\n for (const route of routeSources) {\n const {\n name,\n path,\n file,\n definitionItems, // Includes both middleware and HTTP method handlers\n params,\n numericParams,\n validationSchemas,\n } = route;\n\n const routeMiddleware: Array<MiddlewareDefinition> = definitionItems.filter(\n (e) => e.kind === \"middleware\",\n );\n\n // WARN: the order is critical!\n // the last defined middleware will take precedence.\n const middlewareStack: Array<MiddlewareDefinition> = [\n ...paramsMiddlewareFactory(params, numericParams),\n ...validationMiddlewareFactory(validationSchemas),\n // core middleware overrides builtin middleware (of same slot)\n ...coreMiddleware,\n // route middleware overrides core middleware (of same slot)\n ...routeMiddleware,\n ];\n\n const routeStack: Array<MiddlewareDefinition | HandlerDefinition> = [\n ...prioritizedSlots.flatMap((slot) => {\n const middleware = middlewareStack.findLast(\n // Using findLast to pick the latest entry,\n // ensuring later entries override earlier ones.\n (e) => e.options?.slot === slot,\n );\n return middleware //\n ? [middleware]\n : [];\n }),\n\n ...coreMiddleware.flatMap((entry) => {\n if (!entry.options?.slot) {\n // no slot, including regardless\n return [entry];\n }\n if (prioritizedSlots.includes(entry.options?.slot)) {\n // already picked when inserted prioritized middleware, excluding\n return [];\n }\n const override = routeMiddleware.findLast(\n // Using findLast to pick the latest entry,\n // ensuring later entries override earlier ones.\n (e) => e.options?.slot === entry.options?.slot,\n );\n return [override || entry];\n }),\n\n ...definitionItems.flatMap((entry) => {\n const slot =\n entry.kind === \"middleware\" //\n ? entry.options?.slot\n : undefined;\n\n if (slot) {\n if (prioritizedSlots.includes(slot)) {\n // already picked when inserted prioritized middleware, excluding\n return [];\n }\n if (coreMiddleware.some((e) => e.options?.slot === slot)) {\n // already picked when inserted core middleware, excluding\n return [];\n }\n }\n\n return [entry];\n }),\n ];\n\n for (const entry of routeStack) {\n if (entry.kind === \"middleware\") {\n stack.push({\n name,\n path,\n file,\n methods: entry.options?.on || Object.keys(HTTPMethods),\n middleware: entry.middleware,\n kind: entry.kind,\n slot: entry.options?.slot,\n debug: entry.options?.debug,\n });\n } else if (entry.kind === \"handler\") {\n stack.push({\n name,\n path,\n file,\n methods: [entry.method],\n middleware: entry.middleware,\n kind: entry.kind,\n });\n }\n }\n }\n\n return stack;\n};\n\nconst paramsMiddlewareFactory = (\n params: RouterRouteSource[\"params\"],\n numericParams: RouterRouteSource[\"numericParams\"],\n) => [\n use(\n (ctx, next) => {\n ctx.typedParams = params.reduce(\n (map: Record<string, unknown>, [name, isRest]) => {\n const value = ctx.params[name];\n if (value) {\n if (isRest) {\n map[name] = numericParams.includes(name)\n ? value.split(\"/\").map(Number)\n : value.split(\"/\");\n } else {\n map[name] = numericParams.includes(name) ? Number(value) : value;\n }\n } else {\n map[name] = value;\n }\n return map;\n },\n {},\n ) as never;\n return next();\n },\n { slot: \"params\" },\n ),\n];\n\nconst validationMiddlewareFactory = (validationSchemas: ValidationSchemas) => [\n use(\n (ctx, next) => {\n validationSchemas.params?.validate(ctx.typedParams);\n return next();\n },\n { slot: \"validateParams\" },\n ),\n\n use(\n (ctx, next) => {\n validationSchemas.payload?.[ctx.method]?.validate(ctx.payload);\n return next();\n },\n {\n slot: \"validatePayload\",\n on: Object.keys(validationSchemas.payload || {}) as never,\n },\n ),\n\n use(\n async (ctx, next) => {\n if (validationSchemas.response?.[ctx.method]) {\n await next();\n validationSchemas.response?.[ctx.method]?.validate(ctx.body);\n } else {\n return next();\n }\n },\n {\n slot: \"validateResponse\",\n on: Object.keys(validationSchemas.response || {}) as never,\n },\n ),\n];\n", "import type {\n Middleware,\n RouterOptions,\n RouterParamContext,\n} from \"@koa/router\";\nimport type { Next } from \"koa\";\n\ndeclare module \"koa\" {\n interface Request {\n body?: unknown;\n rawBody: string;\n }\n}\n\nexport interface DefaultState {}\nexport interface DefaultContext {}\n\nexport enum HTTPMethods {\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n GET = \"GET\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n POST = \"POST\",\n DELETE = \"DELETE\",\n}\n\nexport type { Middleware };\n\nexport type HTTPMethod = keyof typeof HTTPMethods;\n\nexport type ParameterizedContext<\n ParamsT,\n StateT,\n ContextT,\n PayloadT = unknown,\n ResponseT = unknown,\n> = import(\"koa\").ParameterizedContext<\n DefaultState & StateT,\n RouterParamContext<StateT, ContextT> &\n DefaultContext &\n ContextT & {\n typedParams: ParamsT;\n payload: PayloadT;\n },\n ResponseT\n>;\n\ntype RouteMiddleware<ParamsT, StateT, ContextT> = (\n ctx: ParameterizedContext<ParamsT, StateT, ContextT>,\n next: Next,\n) => Promise<void> | void;\n\nexport type RouteHandler<\n ParamsT,\n StateT,\n ContextT,\n PayloadT = unknown,\n ResponseT = unknown,\n> = (\n ctx: ParameterizedContext<ParamsT, StateT, ContextT, PayloadT, ResponseT>,\n next: Next,\n) => Promise<void> | void;\n\nexport type MiddlewareDefinition = {\n kind: \"middleware\";\n middleware: Array<Middleware>;\n options?: UseOptions | undefined;\n};\n\nexport type HandlerDefinition = {\n kind: \"handler\";\n middleware: Array<Middleware>;\n method: HTTPMethod;\n};\n\nexport type RouteDefinitionItem = MiddlewareDefinition | HandlerDefinition;\n\nexport type DefineRouteHelpers<\n ParamsT,\n StateT,\n ContextT,\n OptionalHandlers = undefined,\n> = {\n // INFO: The `use` helper intentionally does not accept type parameters.\n // PayloadT and ResponseT are only relevant to route handlers,\n // as different request methods receive different payloads and return different responses.\n // Allowing these type parameters on `use` would be misleading,\n // since middleware operates across multiple request methods with varying types.\n use: (\n middleware:\n | RouteMiddleware<ParamsT, StateT, ContextT>\n | Array<RouteMiddleware<ParamsT, StateT, ContextT>>,\n options?: UseOptions,\n ) => RouteDefinitionItem;\n} & {\n [M in HTTPMethod]: M extends OptionalHandlers\n ? <PayloadT = unknown, ResponseT = unknown>(\n handler?:\n | RouteHandler<ParamsT, StateT, ContextT, PayloadT, ResponseT>\n | Array<RouteHandler<ParamsT, StateT, ContextT, PayloadT, ResponseT>>,\n ) => RouteDefinitionItem\n : <PayloadT = unknown, ResponseT = unknown>(\n handler:\n | RouteHandler<ParamsT, StateT, ContextT, PayloadT, ResponseT>\n | Array<RouteHandler<ParamsT, StateT, ContextT, PayloadT, ResponseT>>,\n ) => RouteDefinitionItem;\n};\n\nexport type DefineRoute = <\n ParamsT = Record<string, string>,\n StateT = object,\n ContextT = object,\n>(\n factory: (\n helpers: DefineRouteHelpers<ParamsT, StateT, ContextT>,\n ) => Array<RouteDefinitionItem>,\n) => Array<RouteDefinitionItem>;\n\nexport interface UseSlots {\n params: string;\n validateParams: string;\n bodyparser: string;\n payload: string;\n validatePayload: string;\n validateResponse: string;\n}\n\nexport type UseOptions = {\n on?: Array<HTTPMethod>;\n slot?: keyof UseSlots;\n debug?: string | undefined;\n};\n\nexport type Use = <StateT = DefaultState, ContextT = DefaultContext>(\n middleware:\n | RouteMiddleware<Record<string, string>, StateT, ContextT>\n | Array<RouteMiddleware<Record<string, string>, StateT, ContextT>>,\n options?: UseOptions,\n) => MiddlewareDefinition;\n\nexport type RouterRouteSource = {\n name: string;\n path: string;\n file: string;\n definitionItems: Array<RouteDefinitionItem>;\n params: Array<[name: string, isRest?: boolean]>;\n numericParams: Array<string>;\n validationSchemas: ValidationSchemas;\n meta?: Record<string, unknown>;\n};\n\nexport type RouterRoute = {\n name: string;\n path: string;\n file: string;\n methods: Array<string>;\n middleware: Array<Middleware>;\n kind: \"middleware\" | \"handler\";\n slot?: keyof UseSlots | undefined;\n debug?: string | undefined;\n};\n\nimport type Koa from \"koa\";\nexport type App = Koa<DefaultState, DefaultContext>;\nexport type AppOptions = ConstructorParameters<typeof import(\"koa\")>[0];\nexport type CreateApp = (options?: AppOptions) => App;\n\nimport type KoaRouter from \"@koa/router\";\nexport type Router = KoaRouter<DefaultState, DefaultContext>;\nexport type { RouterOptions };\nexport type CreateRouter = (options?: RouterOptions) => Router;\n\nexport type DevMiddlewareFactory = (\n app: App,\n) => (\n req: import(\"node:http\").IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n next: () => Promise<void>,\n) => Promise<void>;\nexport type TeardownHandler = (app: App) => void | Promise<void>;\n\nexport type ValidationSchema = {\n check: (data: unknown) => boolean;\n errors: (data: unknown) => Array<ValidationErrorEntry>;\n errorMessage: (data: unknown) => string;\n errorSummary: (data: unknown) => string;\n validate: (data: unknown) => void;\n};\n\nexport type ValidationSchemas<Extend = object> = {\n params?: ValidationSchema & Extend;\n payload?: Record<string, ValidationSchema & Extend>;\n response?: Record<string, ValidationSchema & Extend>;\n};\n\nexport type ValidationErrorScope = \"params\" | \"payload\" | \"response\";\n\n/**\n * Shape of individual validation errors emitted by generators.\n */\nexport type ValidationErrorEntry = {\n /** JSON Schema keyword that triggered the error (e.g. `format`, `maxItems`, `maxLength`). */\n keyword: string;\n /** JSON Pointer\u2013style path to the invalid field (matches JSON Schema `instancePath`). */\n path: string;\n /** Human-readable error message. */\n message: string;\n /** Constraint parameters (e.g. `{ limit: 5 }`, `{ format: \"email\" }`). */\n params?: Record<string, unknown>;\n /** Optional error code for i18n/l10n or custom handling. */\n code?: string;\n};\n\nexport type ValidationErrorData = {\n errors: Array<ValidationErrorEntry>;\n /**\n * Formats errors into a single human-readable message.\n * @example: Validation failed: user: missing required properties: \"email\", \"name\"; password: must be at least 8 characters long\n */\n errorMessage: string;\n /**\n * Gets a simple error summary for quick feedback.\n * @example: 2 validation errors found across 2 fields\n */\n errorSummary: string;\n};\n", "import type { Use } from \"./types\";\n\nexport const use: Use = (middleware, options) => {\n return {\n kind: \"middleware\",\n middleware: [middleware].flat() as never,\n options,\n };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["HTTPMethods"]
7
+ }
@@ -0,0 +1,37 @@
1
+ // src/queryparser/index.ts
2
+ import { parse, stringify } from "qs";
3
+ var queryparser_default = (app, _parseOptions = {}, _stringifyOptions = {}) => {
4
+ const parseOptions = {
5
+ ignoreQueryPrefix: true,
6
+ parseArrays: true,
7
+ arrayLimit: 100,
8
+ parameterLimit: 100,
9
+ depth: 5,
10
+ ..._parseOptions
11
+ };
12
+ const stringifyOptions = {
13
+ encodeValuesOnly: true,
14
+ arrayFormat: "brackets",
15
+ ..._stringifyOptions
16
+ };
17
+ const obj = {
18
+ get query() {
19
+ return parse(this.querystring || "", parseOptions);
20
+ },
21
+ set query(obj2) {
22
+ this.querystring = stringify(obj2, stringifyOptions);
23
+ }
24
+ };
25
+ const entries = Object.getOwnPropertyNames(obj).map((name) => [
26
+ name,
27
+ Object.getOwnPropertyDescriptor(obj, name)
28
+ ]);
29
+ for (const [name, desc] of entries) {
30
+ Object.defineProperty(app.request, name, desc);
31
+ }
32
+ return app;
33
+ };
34
+ export {
35
+ queryparser_default as default
36
+ };
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/queryparser/index.ts"],
4
+ "sourcesContent": ["import type Koa from \"koa\";\nimport type { IParseOptions, IStringifyOptions } from \"qs\";\nimport { parse, stringify } from \"qs\";\n\nimport type { DefaultContext, DefaultState } from \"@/types\";\n\nexport default <\n T extends InstanceType<typeof Koa<DefaultState, DefaultContext>> = never,\n>(\n app: T,\n _parseOptions: IParseOptions = {},\n _stringifyOptions: IStringifyOptions = {},\n) => {\n const parseOptions = {\n ignoreQueryPrefix: true,\n parseArrays: true,\n arrayLimit: 100,\n parameterLimit: 100,\n depth: 5,\n ..._parseOptions,\n };\n\n const stringifyOptions = {\n encodeValuesOnly: true,\n arrayFormat: \"brackets\",\n ..._stringifyOptions,\n } as const;\n\n const obj = {\n get query() {\n return parse((this as Koa.Request).querystring || \"\", parseOptions);\n },\n\n set query(obj: object) {\n (this as Koa.Request).querystring = stringify(obj, stringifyOptions);\n },\n };\n\n const entries = Object.getOwnPropertyNames(obj).map((name) => [\n name,\n Object.getOwnPropertyDescriptor(obj, name),\n ]) as [name: string, desc: PropertyDescriptor][];\n\n for (const [name, desc] of entries) {\n Object.defineProperty(app.request, name, desc);\n }\n\n return app;\n};\n"],
5
+ "mappings": ";AAEA,SAAS,OAAO,iBAAiB;AAIjC,IAAO,sBAAQ,CAGb,KACA,gBAA+B,CAAC,GAChC,oBAAuC,CAAC,MACrC;AACH,QAAM,eAAe;AAAA,IACnB,mBAAmB;AAAA,IACnB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,GAAG;AAAA,EACL;AAEA,QAAM,mBAAmB;AAAA,IACvB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,GAAG;AAAA,EACL;AAEA,QAAM,MAAM;AAAA,IACV,IAAI,QAAQ;AACV,aAAO,MAAO,KAAqB,eAAe,IAAI,YAAY;AAAA,IACpE;AAAA,IAEA,IAAI,MAAMA,MAAa;AACrB,MAAC,KAAqB,cAAc,UAAUA,MAAK,gBAAgB;AAAA,IACrE;AAAA,EACF;AAEA,QAAM,UAAU,OAAO,oBAAoB,GAAG,EAAE,IAAI,CAAC,SAAS;AAAA,IAC5D;AAAA,IACA,OAAO,yBAAyB,KAAK,IAAI;AAAA,EAC3C,CAAC;AAED,aAAW,CAAC,MAAM,IAAI,KAAK,SAAS;AAClC,WAAO,eAAe,IAAI,SAAS,MAAM,IAAI;AAAA,EAC/C;AAEA,SAAO;AACT;",
6
+ "names": ["obj"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import type { CreateApp } from "./types";
2
+ export declare const createApp: CreateApp;
@@ -0,0 +1,10 @@
1
+ import type { FormOptions, JsonOptions, RawOptions } from "./types";
2
+ export declare const json: JsonOptions;
3
+ export declare const form: FormOptions;
4
+ export declare const raw: RawOptions;
5
+ declare const _default: {
6
+ json: JsonOptions;
7
+ form: FormOptions;
8
+ raw: RawOptions;
9
+ };
10
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import type { Middleware } from "@kosmojs/api";
2
+ import config from "./config";
3
+ import type { FormOptions, JsonOptions, RawOptions } from "./types";
4
+ export * from "./types";
5
+ export { config };
6
+ declare const _default: {
7
+ json: typeof json;
8
+ form: typeof form;
9
+ raw: typeof raw;
10
+ };
11
+ export default _default;
12
+ export declare function json(opts?: JsonOptions): Array<Middleware>;
13
+ export declare function form(opts?: FormOptions): Array<Middleware>;
14
+ export declare function raw(opts?: RawOptions): Array<Middleware>;
@@ -0,0 +1,39 @@
1
+ import type { Options as FormidableOptions } from "formidable";
2
+ export type TrimOption = Array<string>;
3
+ export type Trimmer = (fields: Record<string, unknown>) => Record<string, unknown>;
4
+ type GenericOptions = {
5
+ limit?: number;
6
+ trim?: TrimOption;
7
+ };
8
+ export type JsonOptions = FormidableOptions & GenericOptions;
9
+ export type FormOptions = FormidableOptions & GenericOptions & {
10
+ uploadDir?: string;
11
+ multipart?: boolean;
12
+ urlencoded?: boolean;
13
+ };
14
+ export type RawOptions = {
15
+ /**
16
+ * The byte limit of the body.
17
+ * If the body ends up being larger than this limit, a 413 error code is returned.
18
+ * */
19
+ limit?: number;
20
+ /**
21
+ * The length of the stream.
22
+ * If the contents of the stream do not add up to this length,
23
+ * an 400 error code is returned
24
+ * */
25
+ length?: number;
26
+ /**
27
+ * The encoding to use to decode the body into a string.
28
+ * By default, a Buffer instance will be returned when no encoding is specified.
29
+ * utf-8 would decode as plain text.
30
+ * use any encoding supported by iconv-lite.
31
+ * */
32
+ encoding?: string;
33
+ /**
34
+ * zlib options
35
+ * */
36
+ chunkSize?: number;
37
+ };
38
+ export type Options = JsonOptions | FormOptions | RawOptions;
39
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { RouterRoute } from "./types";
2
+ type Printer = (line: string) => void;
3
+ declare const _default: (routes: Array<RouterRoute>, printer: Printer, patterns?: Array<string> | undefined) => void;
4
+ export default _default;
@@ -0,0 +1,18 @@
1
+ import type { ValidationErrorData, ValidationErrorEntry, ValidationErrorScope } from "./types";
2
+ /**
3
+ * Standardized error wrapper used by validation generators.
4
+ *
5
+ * Instances of this class are thrown whenever validation fails,
6
+ * carrying both the error scope (e.g. `"params"`, `"payload"`)
7
+ * and the list of validation error details.
8
+ */
9
+ export declare class ValidationError extends Error {
10
+ scope: ValidationErrorScope;
11
+ errors: Array<ValidationErrorEntry>;
12
+ errorMessage: string;
13
+ errorSummary: string;
14
+ constructor([scope, { errors, errorMessage, errorSummary }]: [
15
+ ValidationErrorScope,
16
+ ValidationErrorData
17
+ ]);
18
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./app";
2
+ export * from "./errors";
3
+ export * from "./router";
4
+ export * from "./types";
5
+ export * from "./use";
@@ -0,0 +1,5 @@
1
+ import type Koa from "koa";
2
+ import type { IParseOptions, IStringifyOptions } from "qs";
3
+ import type { DefaultContext, DefaultState } from "../types";
4
+ declare const _default: <T extends InstanceType<typeof Koa<DefaultState, DefaultContext>> = never>(app: T, _parseOptions?: IParseOptions, _stringifyOptions?: IStringifyOptions) => T;
5
+ export default _default;
@@ -0,0 +1,6 @@
1
+ import { type CreateRouter, type DefineRoute, type MiddlewareDefinition, type RouterRoute, type RouterRouteSource } from "./types";
2
+ export declare const createRouter: CreateRouter;
3
+ export declare const defineRoute: DefineRoute;
4
+ export declare const routerRoutesFactory: (routeSources: Array<RouterRouteSource>, { coreMiddleware, }: {
5
+ coreMiddleware: Array<MiddlewareDefinition>;
6
+ }) => RouterRoute[];
@@ -0,0 +1,131 @@
1
+ import type { Middleware, RouterOptions, RouterParamContext } from "@koa/router";
2
+ import type { Next } from "koa";
3
+ declare module "koa" {
4
+ interface Request {
5
+ body?: unknown;
6
+ rawBody: string;
7
+ }
8
+ }
9
+ export interface DefaultState {
10
+ }
11
+ export interface DefaultContext {
12
+ }
13
+ export declare enum HTTPMethods {
14
+ HEAD = "HEAD",
15
+ OPTIONS = "OPTIONS",
16
+ GET = "GET",
17
+ PUT = "PUT",
18
+ PATCH = "PATCH",
19
+ POST = "POST",
20
+ DELETE = "DELETE"
21
+ }
22
+ export type { Middleware };
23
+ export type HTTPMethod = keyof typeof HTTPMethods;
24
+ export type ParameterizedContext<ParamsT, StateT, ContextT, PayloadT = unknown, ResponseT = unknown> = import("koa").ParameterizedContext<DefaultState & StateT, RouterParamContext<StateT, ContextT> & DefaultContext & ContextT & {
25
+ typedParams: ParamsT;
26
+ payload: PayloadT;
27
+ }, ResponseT>;
28
+ type RouteMiddleware<ParamsT, StateT, ContextT> = (ctx: ParameterizedContext<ParamsT, StateT, ContextT>, next: Next) => Promise<void> | void;
29
+ export type RouteHandler<ParamsT, StateT, ContextT, PayloadT = unknown, ResponseT = unknown> = (ctx: ParameterizedContext<ParamsT, StateT, ContextT, PayloadT, ResponseT>, next: Next) => Promise<void> | void;
30
+ export type MiddlewareDefinition = {
31
+ kind: "middleware";
32
+ middleware: Array<Middleware>;
33
+ options?: UseOptions | undefined;
34
+ };
35
+ export type HandlerDefinition = {
36
+ kind: "handler";
37
+ middleware: Array<Middleware>;
38
+ method: HTTPMethod;
39
+ };
40
+ export type RouteDefinitionItem = MiddlewareDefinition | HandlerDefinition;
41
+ export type DefineRouteHelpers<ParamsT, StateT, ContextT, OptionalHandlers = undefined> = {
42
+ use: (middleware: RouteMiddleware<ParamsT, StateT, ContextT> | Array<RouteMiddleware<ParamsT, StateT, ContextT>>, options?: UseOptions) => RouteDefinitionItem;
43
+ } & {
44
+ [M in HTTPMethod]: M extends OptionalHandlers ? <PayloadT = unknown, ResponseT = unknown>(handler?: RouteHandler<ParamsT, StateT, ContextT, PayloadT, ResponseT> | Array<RouteHandler<ParamsT, StateT, ContextT, PayloadT, ResponseT>>) => RouteDefinitionItem : <PayloadT = unknown, ResponseT = unknown>(handler: RouteHandler<ParamsT, StateT, ContextT, PayloadT, ResponseT> | Array<RouteHandler<ParamsT, StateT, ContextT, PayloadT, ResponseT>>) => RouteDefinitionItem;
45
+ };
46
+ export type DefineRoute = <ParamsT = Record<string, string>, StateT = object, ContextT = object>(factory: (helpers: DefineRouteHelpers<ParamsT, StateT, ContextT>) => Array<RouteDefinitionItem>) => Array<RouteDefinitionItem>;
47
+ export interface UseSlots {
48
+ params: string;
49
+ validateParams: string;
50
+ bodyparser: string;
51
+ payload: string;
52
+ validatePayload: string;
53
+ validateResponse: string;
54
+ }
55
+ export type UseOptions = {
56
+ on?: Array<HTTPMethod>;
57
+ slot?: keyof UseSlots;
58
+ debug?: string | undefined;
59
+ };
60
+ export type Use = <StateT = DefaultState, ContextT = DefaultContext>(middleware: RouteMiddleware<Record<string, string>, StateT, ContextT> | Array<RouteMiddleware<Record<string, string>, StateT, ContextT>>, options?: UseOptions) => MiddlewareDefinition;
61
+ export type RouterRouteSource = {
62
+ name: string;
63
+ path: string;
64
+ file: string;
65
+ definitionItems: Array<RouteDefinitionItem>;
66
+ params: Array<[name: string, isRest?: boolean]>;
67
+ numericParams: Array<string>;
68
+ validationSchemas: ValidationSchemas;
69
+ meta?: Record<string, unknown>;
70
+ };
71
+ export type RouterRoute = {
72
+ name: string;
73
+ path: string;
74
+ file: string;
75
+ methods: Array<string>;
76
+ middleware: Array<Middleware>;
77
+ kind: "middleware" | "handler";
78
+ slot?: keyof UseSlots | undefined;
79
+ debug?: string | undefined;
80
+ };
81
+ import type Koa from "koa";
82
+ export type App = Koa<DefaultState, DefaultContext>;
83
+ export type AppOptions = ConstructorParameters<typeof import("koa")>[0];
84
+ export type CreateApp = (options?: AppOptions) => App;
85
+ import type KoaRouter from "@koa/router";
86
+ export type Router = KoaRouter<DefaultState, DefaultContext>;
87
+ export type { RouterOptions };
88
+ export type CreateRouter = (options?: RouterOptions) => Router;
89
+ export type DevMiddlewareFactory = (app: App) => (req: import("node:http").IncomingMessage, res: import("node:http").ServerResponse, next: () => Promise<void>) => Promise<void>;
90
+ export type TeardownHandler = (app: App) => void | Promise<void>;
91
+ export type ValidationSchema = {
92
+ check: (data: unknown) => boolean;
93
+ errors: (data: unknown) => Array<ValidationErrorEntry>;
94
+ errorMessage: (data: unknown) => string;
95
+ errorSummary: (data: unknown) => string;
96
+ validate: (data: unknown) => void;
97
+ };
98
+ export type ValidationSchemas<Extend = object> = {
99
+ params?: ValidationSchema & Extend;
100
+ payload?: Record<string, ValidationSchema & Extend>;
101
+ response?: Record<string, ValidationSchema & Extend>;
102
+ };
103
+ export type ValidationErrorScope = "params" | "payload" | "response";
104
+ /**
105
+ * Shape of individual validation errors emitted by generators.
106
+ */
107
+ export type ValidationErrorEntry = {
108
+ /** JSON Schema keyword that triggered the error (e.g. `format`, `maxItems`, `maxLength`). */
109
+ keyword: string;
110
+ /** JSON Pointer–style path to the invalid field (matches JSON Schema `instancePath`). */
111
+ path: string;
112
+ /** Human-readable error message. */
113
+ message: string;
114
+ /** Constraint parameters (e.g. `{ limit: 5 }`, `{ format: "email" }`). */
115
+ params?: Record<string, unknown>;
116
+ /** Optional error code for i18n/l10n or custom handling. */
117
+ code?: string;
118
+ };
119
+ export type ValidationErrorData = {
120
+ errors: Array<ValidationErrorEntry>;
121
+ /**
122
+ * Formats errors into a single human-readable message.
123
+ * @example: Validation failed: user: missing required properties: "email", "name"; password: must be at least 8 characters long
124
+ */
125
+ errorMessage: string;
126
+ /**
127
+ * Gets a simple error summary for quick feedback.
128
+ * @example: 2 validation errors found across 2 fields
129
+ */
130
+ errorSummary: string;
131
+ };
@@ -0,0 +1,2 @@
1
+ import type { Use } from "./types";
2
+ export declare const use: Use;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import { type MiddlewareDefinition, type RouterRouteSource } from "../src/types";
2
+ export declare const defaultMethods: string[];
3
+ export declare const middlewareStackBuilder: (a: Array<Partial<RouterRouteSource>>, b: {
4
+ coreMiddleware?: Array<MiddlewareDefinition>;
5
+ }) => import("../src/types").RouterRoute[];
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};