@maroonedsoftware/koa 1.1.1 → 1.2.1

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/dist/index.d.ts CHANGED
@@ -5,5 +5,14 @@ export * from './middleware/server/cors.middleware.js';
5
5
  export * from './middleware/server/error.middleware.js';
6
6
  export * from './middleware/server/rate.limiter.middleware.js';
7
7
  export * from './middleware/server/serverkit.context.middleware.js';
8
+ export * from './middleware/server/authentication.middleware.js';
8
9
  export * from './middleware/router/body.parser.middleware.js';
10
+ export * from './parsers/serverkit.parser.js';
11
+ export * from './serverkit.bodyparser.js';
12
+ export * from './parsers/json.parser.js';
13
+ export * from './parsers/text.parser.js';
14
+ export * from './parsers/form.parser.js';
15
+ export * from './parsers/multipart.parser.js';
16
+ export * from './parsers/binary.parser.js';
17
+ export * from './parsers.setup.js';
9
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,qDAAqD,CAAC;AACpE,cAAc,+CAA+C,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,qDAAqD,CAAC;AACpE,cAAc,kDAAkD,CAAC;AACjE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -114,64 +114,422 @@ var serverKitContextMiddleware = /* @__PURE__ */ __name((container) => {
114
114
  };
115
115
  }, "serverKitContextMiddleware");
116
116
 
117
+ // src/middleware/server/authentication.middleware.ts
118
+ import { AuthenticationSchemeHandler, invalidAuthenticationContext } from "@maroonedsoftware/authentication";
119
+ var authenticationMiddleware = /* @__PURE__ */ __name(() => {
120
+ return async (ctx, next) => {
121
+ ctx.authenticationContext = invalidAuthenticationContext;
122
+ const authorizationHeader = ctx.req.headers.authorization;
123
+ delete ctx.req.headers.authorization;
124
+ const schemeHandler = ctx.serviceLocator.get(AuthenticationSchemeHandler);
125
+ ctx.authenticationContext = await schemeHandler.handle(authorizationHeader);
126
+ await next();
127
+ };
128
+ }, "authenticationMiddleware");
129
+
130
+ // src/middleware/router/body.parser.middleware.ts
131
+ import { httpError as httpError3, IsHttpError as IsHttpError2 } from "@maroonedsoftware/errors";
132
+
133
+ // src/serverkit.bodyparser.ts
134
+ import { Injectable } from "injectkit";
135
+ import { unique } from "@maroonedsoftware/utilities";
136
+ import { httpError as httpError2 } from "@maroonedsoftware/errors";
137
+ function _ts_decorate(decorators, target, key, desc) {
138
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
139
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
140
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
141
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
142
+ }
143
+ __name(_ts_decorate, "_ts_decorate");
144
+ function _ts_metadata(k, v) {
145
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
146
+ }
147
+ __name(_ts_metadata, "_ts_metadata");
148
+ var ServerKitParserMappings = class extends Map {
149
+ static {
150
+ __name(this, "ServerKitParserMappings");
151
+ }
152
+ };
153
+ ServerKitParserMappings = _ts_decorate([
154
+ Injectable()
155
+ ], ServerKitParserMappings);
156
+ var ServerKitBodyParser = class {
157
+ static {
158
+ __name(this, "ServerKitBodyParser");
159
+ }
160
+ parsers;
161
+ mimeTypes;
162
+ constructor(parsers) {
163
+ this.parsers = parsers;
164
+ this.mimeTypes = unique(Array.from(this.parsers.keys()));
165
+ }
166
+ async parse(ctx) {
167
+ const mimeType = ctx.request.is(this.mimeTypes);
168
+ if (!mimeType) {
169
+ throw httpError2(415).withDetails({
170
+ body: "Unsupported media type"
171
+ });
172
+ }
173
+ const parser = this.parsers.get(mimeType);
174
+ if (!parser) {
175
+ throw httpError2(415).withDetails({
176
+ body: "Unsupported media type"
177
+ });
178
+ }
179
+ return parser.parse(ctx.req);
180
+ }
181
+ };
182
+ ServerKitBodyParser = _ts_decorate([
183
+ Injectable(),
184
+ _ts_metadata("design:type", Function),
185
+ _ts_metadata("design:paramtypes", [
186
+ typeof ServerKitParserMappings === "undefined" ? Object : ServerKitParserMappings
187
+ ])
188
+ ], ServerKitBodyParser);
189
+
117
190
  // src/middleware/router/body.parser.middleware.ts
118
- import coBody from "co-body";
119
- import { httpError as httpError2, IsHttpError as IsHttpError2 } from "@maroonedsoftware/errors";
120
- import { MultipartBody } from "@maroonedsoftware/multipart";
121
- import rawBody from "raw-body";
122
191
  var bodyParserMiddleware = /* @__PURE__ */ __name((contentTypes) => {
123
192
  return async (ctx, next) => {
124
193
  if (contentTypes.length === 0) {
125
194
  if (ctx.request.length > 0) {
126
- throw httpError2(400).withDetails({
195
+ throw httpError3(400).withDetails({
127
196
  body: "Unexpected body"
128
197
  });
129
198
  }
130
199
  } else {
131
200
  if (ctx.request.length > 0) {
132
201
  if (!ctx.request.is(contentTypes)) {
133
- throw httpError2(415).withDetails({
202
+ throw httpError3(415).withDetails({
134
203
  "content-type": `must be ${contentTypes.length > 1 ? "one of " : ""}${contentTypes.join(", ")}`,
135
204
  value: ctx.request.type
136
205
  });
137
206
  }
138
207
  try {
139
- if (ctx.request.is("json", "application/*+json")) {
140
- ctx.body = await coBody.json(ctx);
141
- } else if (ctx.request.is("urlencoded")) {
142
- ctx.body = await coBody.form(ctx);
143
- } else if (ctx.request.is("text/*")) {
144
- ctx.body = await coBody.text(ctx);
145
- } else if (ctx.request.is("multipart")) {
146
- ctx.body = new MultipartBody(ctx.req);
147
- } else if (ctx.request.is("pdf")) {
148
- ctx.body = await rawBody(ctx.req);
149
- } else {
150
- throw httpError2(422).withDetails({
151
- body: "Unsupported media type"
152
- });
153
- }
208
+ const parser = ctx.container.get(ServerKitBodyParser);
209
+ const result = await parser.parse(ctx);
210
+ ctx.body = result.parsed;
211
+ ctx.rawBody = result.raw;
154
212
  } catch (error) {
155
213
  if (IsHttpError2(error)) {
156
214
  throw error;
157
215
  }
158
- throw httpError2(422).withCause(error).withDetails({
216
+ throw httpError3(422).withCause(error).withDetails({
159
217
  body: "Invalid request body format"
160
218
  });
161
219
  }
162
220
  } else {
163
- throw httpError2(411);
221
+ throw httpError3(411);
164
222
  }
165
223
  }
166
224
  await next();
167
225
  };
168
226
  }, "bodyParserMiddleware");
227
+
228
+ // src/parsers/serverkit.parser.ts
229
+ import { Injectable as Injectable2 } from "injectkit";
230
+ function _ts_decorate2(decorators, target, key, desc) {
231
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
232
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
233
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
234
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
235
+ }
236
+ __name(_ts_decorate2, "_ts_decorate");
237
+ var ServerKitParser = class {
238
+ static {
239
+ __name(this, "ServerKitParser");
240
+ }
241
+ };
242
+ ServerKitParser = _ts_decorate2([
243
+ Injectable2()
244
+ ], ServerKitParser);
245
+
246
+ // src/parsers/json.parser.ts
247
+ import { parse } from "@hapi/bourne";
248
+ import raw from "raw-body";
249
+ import inflate from "inflation";
250
+ import { httpError as httpError4 } from "@maroonedsoftware/errors";
251
+ import { Injectable as Injectable3 } from "injectkit";
252
+ function _ts_decorate3(decorators, target, key, desc) {
253
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
254
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
255
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
256
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
257
+ }
258
+ __name(_ts_decorate3, "_ts_decorate");
259
+ function _ts_metadata2(k, v) {
260
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
261
+ }
262
+ __name(_ts_metadata2, "_ts_metadata");
263
+ var strictJSONReg = /^[\x20\x09\x0a\x0d]*(\[|\{)/;
264
+ var JsonParser = class extends ServerKitParser {
265
+ static {
266
+ __name(this, "JsonParser");
267
+ }
268
+ options;
269
+ constructor(options = {}) {
270
+ super(), this.options = options;
271
+ }
272
+ async parse(req) {
273
+ const len = req.headers["content-length"];
274
+ const contentEncoding = req.headers["content-encoding"] || "identity";
275
+ const length = len && contentEncoding === "identity" ? ~~len : void 0;
276
+ const encoding = this.options.encoding ?? "utf8";
277
+ const limit = this.options.limit ?? "1mb";
278
+ const strict = this.options.strict ?? true;
279
+ const protoAction = this.options.protoAction ?? "error";
280
+ const str = await raw(inflate(req), {
281
+ encoding,
282
+ limit,
283
+ length
284
+ });
285
+ const doParse = /* @__PURE__ */ __name((str2) => {
286
+ try {
287
+ if (this.options.reviver) {
288
+ return parse(str2, this.options.reviver, {
289
+ protoAction
290
+ });
291
+ }
292
+ return parse(str2, {
293
+ protoAction
294
+ });
295
+ } catch (err) {
296
+ throw httpError4(400).withCause(err);
297
+ }
298
+ }, "doParse");
299
+ if (!strict) {
300
+ return str ? {
301
+ parsed: doParse(str),
302
+ raw: str
303
+ } : {
304
+ parsed: void 0,
305
+ raw: str
306
+ };
307
+ } else if (!str) {
308
+ return {
309
+ parsed: void 0,
310
+ raw: str
311
+ };
312
+ } else if (!strictJSONReg.test(str)) {
313
+ throw httpError4(400).withDetails({
314
+ body: "Invalid JSON, only supports object and array"
315
+ });
316
+ }
317
+ return {
318
+ parsed: doParse(str),
319
+ raw: str
320
+ };
321
+ }
322
+ };
323
+ JsonParser = _ts_decorate3([
324
+ Injectable3(),
325
+ _ts_metadata2("design:type", Function),
326
+ _ts_metadata2("design:paramtypes", [
327
+ typeof JsonParserOptions === "undefined" ? Object : JsonParserOptions
328
+ ])
329
+ ], JsonParser);
330
+
331
+ // src/parsers/text.parser.ts
332
+ import { Injectable as Injectable4 } from "injectkit";
333
+ import raw2 from "raw-body";
334
+ import inflate2 from "inflation";
335
+ function _ts_decorate4(decorators, target, key, desc) {
336
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
337
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
338
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
339
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
340
+ }
341
+ __name(_ts_decorate4, "_ts_decorate");
342
+ function _ts_metadata3(k, v) {
343
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
344
+ }
345
+ __name(_ts_metadata3, "_ts_metadata");
346
+ var TextParser = class extends ServerKitParser {
347
+ static {
348
+ __name(this, "TextParser");
349
+ }
350
+ options;
351
+ constructor(options = {}) {
352
+ super(), this.options = options;
353
+ }
354
+ async parse(req) {
355
+ const len = req.headers["content-length"];
356
+ const contentEncoding = req.headers["content-encoding"] || "identity";
357
+ const length = len && contentEncoding === "identity" ? ~~len : void 0;
358
+ const encoding = this.options.encoding ?? "utf8";
359
+ const limit = this.options.limit ?? "1mb";
360
+ const str = await raw2(inflate2(req), {
361
+ encoding,
362
+ limit,
363
+ length
364
+ });
365
+ return {
366
+ parsed: str,
367
+ raw: str
368
+ };
369
+ }
370
+ };
371
+ TextParser = _ts_decorate4([
372
+ Injectable4(),
373
+ _ts_metadata3("design:type", Function),
374
+ _ts_metadata3("design:paramtypes", [
375
+ typeof TextParserOptions === "undefined" ? Object : TextParserOptions
376
+ ])
377
+ ], TextParser);
378
+
379
+ // src/parsers/form.parser.ts
380
+ import { httpError as httpError5 } from "@maroonedsoftware/errors";
381
+ import { Injectable as Injectable5 } from "injectkit";
382
+ import { parse as parse2 } from "qs";
383
+ import raw3 from "raw-body";
384
+ import inflate3 from "inflation";
385
+ function _ts_decorate5(decorators, target, key, desc) {
386
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
387
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
388
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
389
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
390
+ }
391
+ __name(_ts_decorate5, "_ts_decorate");
392
+ function _ts_metadata4(k, v) {
393
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
394
+ }
395
+ __name(_ts_metadata4, "_ts_metadata");
396
+ var FormParser = class extends ServerKitParser {
397
+ static {
398
+ __name(this, "FormParser");
399
+ }
400
+ options;
401
+ constructor(options = {}) {
402
+ super(), this.options = options;
403
+ }
404
+ async parse(req) {
405
+ const len = req.headers["content-length"];
406
+ const contentEncoding = req.headers["content-encoding"] || "identity";
407
+ const length = len && contentEncoding === "identity" ? ~~len : void 0;
408
+ const encoding = this.options.encoding ?? "utf8";
409
+ const limit = this.options.limit ?? "56kb";
410
+ const str = await raw3(inflate3(req), {
411
+ encoding,
412
+ limit,
413
+ length
414
+ });
415
+ try {
416
+ return {
417
+ parsed: parse2(str, this.options),
418
+ raw: str
419
+ };
420
+ } catch (err) {
421
+ throw httpError5(400).withCause(err);
422
+ }
423
+ }
424
+ };
425
+ FormParser = _ts_decorate5([
426
+ Injectable5(),
427
+ _ts_metadata4("design:type", Function),
428
+ _ts_metadata4("design:paramtypes", [
429
+ typeof FormParserOptions === "undefined" ? Object : FormParserOptions
430
+ ])
431
+ ], FormParser);
432
+
433
+ // src/parsers/multipart.parser.ts
434
+ import { Injectable as Injectable6 } from "injectkit";
435
+ import { MultipartBody } from "@maroonedsoftware/multipart";
436
+ function _ts_decorate6(decorators, target, key, desc) {
437
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
438
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
439
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
440
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
441
+ }
442
+ __name(_ts_decorate6, "_ts_decorate");
443
+ var MultipartParser = class extends ServerKitParser {
444
+ static {
445
+ __name(this, "MultipartParser");
446
+ }
447
+ async parse(req) {
448
+ return {
449
+ parsed: new MultipartBody(req),
450
+ raw: void 0
451
+ };
452
+ }
453
+ };
454
+ MultipartParser = _ts_decorate6([
455
+ Injectable6()
456
+ ], MultipartParser);
457
+
458
+ // src/parsers/binary.parser.ts
459
+ import { Injectable as Injectable7 } from "injectkit";
460
+ import raw4 from "raw-body";
461
+ import inflate4 from "inflation";
462
+ function _ts_decorate7(decorators, target, key, desc) {
463
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
464
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
465
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
466
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
467
+ }
468
+ __name(_ts_decorate7, "_ts_decorate");
469
+ var BinaryParser = class extends ServerKitParser {
470
+ static {
471
+ __name(this, "BinaryParser");
472
+ }
473
+ async parse(req) {
474
+ return {
475
+ parsed: await raw4(inflate4(req)),
476
+ raw: void 0
477
+ };
478
+ }
479
+ };
480
+ BinaryParser = _ts_decorate7([
481
+ Injectable7()
482
+ ], BinaryParser);
483
+
484
+ // src/parsers.setup.ts
485
+ var defaultParserMappings = {
486
+ "json": JsonParser,
487
+ "application/*+json": JsonParser,
488
+ "urlencoded": FormParser,
489
+ "text": TextParser,
490
+ "multipart": MultipartParser
491
+ };
492
+ var defaultParserClasses = [
493
+ JsonParser,
494
+ FormParser,
495
+ TextParser,
496
+ MultipartParser,
497
+ BinaryParser
498
+ ];
499
+ var setupParsers = /* @__PURE__ */ __name((registry, overrides = {}) => {
500
+ const merged = {
501
+ ...defaultParserMappings,
502
+ ...overrides
503
+ };
504
+ const mapRegistration = registry.register(ServerKitParserMappings).useMap(ServerKitParserMappings);
505
+ for (const [key, parser] of Object.entries(merged)) {
506
+ mapRegistration.set(key, parser);
507
+ }
508
+ const parserClasses = /* @__PURE__ */ new Set([
509
+ ...defaultParserClasses,
510
+ ...Object.values(overrides)
511
+ ]);
512
+ for (const parserClass of parserClasses) {
513
+ registry.register(parserClass).useClass(parserClass).asSingleton();
514
+ }
515
+ registry.register(ServerKitBodyParser).useClass(ServerKitBodyParser).asSingleton();
516
+ }, "setupParsers");
169
517
  export {
518
+ BinaryParser,
519
+ FormParser,
520
+ JsonParser,
521
+ MultipartParser,
522
+ ServerKitBodyParser,
523
+ ServerKitParser,
524
+ ServerKitParserMappings,
170
525
  ServerKitRouter,
526
+ TextParser,
527
+ authenticationMiddleware,
171
528
  bodyParserMiddleware,
172
529
  corsMiddleware,
173
530
  errorMiddleware,
174
531
  rateLimiterMiddleware,
175
- serverKitContextMiddleware
532
+ serverKitContextMiddleware,
533
+ setupParsers
176
534
  };
177
535
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/serverkit.router.ts","../src/middleware/server/cors.middleware.ts","../src/middleware/server/error.middleware.ts","../src/middleware/server/rate.limiter.middleware.ts","../src/middleware/server/serverkit.context.middleware.ts","../src/middleware/router/body.parser.middleware.ts"],"sourcesContent":["import { DefaultState } from 'koa';\nimport Router from '@koa/router';\nimport { ServerKitContext } from './serverkit.context.js';\n\n/**\n * Creates a new Koa router typed for ServerKit state and context.\n * Use with {@link ServerKitContext} for full typing of `ctx` in route handlers.\n *\n * @typeParam StateT - Koa state type (defaults to `DefaultState`).\n * @typeParam ContextT - Context type (defaults to `ServerKitContext`).\n * @returns A new {@link Router} instance.\n */\nexport const ServerKitRouter = <StateT = DefaultState, ContextT = ServerKitContext>() => new Router<StateT, ContextT>();\n","import cors from '@koa/cors';\nimport { ServerKitMiddleware } from '../../serverkit.middleware.js';\nimport { Context } from 'koa';\n\n/**\n * CORS options for {@link corsMiddleware}.\n * Extends `@koa/cors` options with an `origin` that may be a string or array of strings/RegExps.\n */\nexport interface CorsOptions extends Omit<cors.Options, 'origin'> {\n /** Allowed origin(s): `'*'`, a single origin string, or an array of strings/RegExps to match. */\n origin?: string | (string | RegExp)[];\n}\n\n/**\n * Adds CORS headers to responses using `@koa/cors` with ServerKit-compatible origin matching.\n * Supports `'*'`, exact string origins, and RegExp patterns.\n *\n * @param options - Optional {@link CorsOptions}; defaults to `GET,HEAD,PUT,POST,DELETE,PATCH` methods.\n * @returns {@link ServerKitMiddleware} that applies CORS headers.\n */\nexport const corsMiddleware = (options?: CorsOptions): ServerKitMiddleware => {\n // return the request origin as its own matcher to support RegExp\n const originMatcher = (ctx: Context): string => {\n const origin = ctx.get('origin');\n const matchers = options?.origin ?? ['*'];\n for (const matcher of matchers) {\n if (matcher === '*') {\n return origin;\n }\n\n if (typeof matcher === 'string') {\n if (matcher === origin) {\n return origin;\n }\n continue;\n }\n\n if (matcher.test(origin)) {\n return origin;\n }\n }\n\n // return the zero value to prevent matches\n return '';\n };\n\n return cors({\n ...options,\n origin: originMatcher,\n allowMethods: options?.allowMethods ?? 'GET,HEAD,PUT,POST,DELETE,PATCH',\n secureContext: options?.secureContext ?? false,\n keepHeadersOnError: options?.keepHeadersOnError ?? false,\n privateNetworkAccess: options?.privateNetworkAccess ?? false,\n });\n};\n","import { ServerKitMiddleware } from '../../serverkit.middleware.js';\nimport { IsHttpError } from '@maroonedsoftware/errors';\n\n/**\n * Central error handler: catches thrown errors, sets status/body from HTTP errors,\n * returns 404 for unmatched routes, and 500 for unknown errors.\n * Emits `error` or `warn` on the app for logging.\n *\n * @returns {@link ServerKitMiddleware} that wraps the stack in try/catch and normalizes responses.\n */\nexport const errorMiddleware = (): ServerKitMiddleware => {\n return async (ctx, next) => {\n try {\n await next();\n if (ctx.status === 404 && !ctx.body) {\n const body = {\n statusCode: 404,\n message: 'Not Found',\n details: { url: ctx.URL.toString() },\n };\n ctx.status = 404;\n ctx.body = body;\n ctx.app.emit('warn', body, ctx);\n }\n } catch (error) {\n if (IsHttpError(error)) {\n ctx.status = error.statusCode;\n ctx.body = {\n statusCode: error.statusCode,\n message: error.message,\n details: error.details,\n };\n if (error.headers) {\n for (const entry of Object.entries(error.headers)) {\n ctx.set(entry[0], entry[1]);\n }\n }\n } else {\n ctx.status = 500;\n ctx.body = {\n statusCode: 500,\n message: 'Internal Server Error',\n };\n }\n\n ctx.app.emit('error', error, ctx);\n }\n };\n};\n","import { RateLimiterAbstract } from 'rate-limiter-flexible';\nimport { ServerKitMiddleware } from '../../serverkit.middleware.js';\nimport { httpError } from '@maroonedsoftware/errors';\n\n/**\n * Enforces rate limiting per client IP using a `rate-limiter-flexible` instance.\n * Consumes one token per request; throws HTTP 429 when the limit is exceeded.\n *\n * @param rateLimiter - A {@link RateLimiterAbstract} instance (e.g. `RateLimiterMemory`, `RateLimiterRedis`).\n * @returns {@link ServerKitMiddleware} that consumes a token and continues or throws 429.\n */\nexport const rateLimiterMiddleware = (rateLimiter: RateLimiterAbstract): ServerKitMiddleware => {\n return async (ctx, next) => {\n try {\n await rateLimiter.consume(ctx.ip);\n } catch (error) {\n throw httpError(429).withCause(error as Error);\n }\n\n await next();\n };\n};\n","import crypto from 'crypto';\nimport { Container } from 'injectkit';\nimport { Logger } from '@maroonedsoftware/logger';\nimport { ServerKitMiddleware } from '../../serverkit.middleware.js';\n\n/**\n * Populates {@link ServerKitContext} for each request: scoped container, logger,\n * logger name, user-agent, correlation ID, and request ID.\n * Reads or generates `X-Correlation-Id` and `X-Request-Id` and sets response headers.\n * Should be applied early so downstream middleware and routes can use `ctx.container` and `ctx.logger`.\n *\n * @param container - Root injectkit {@link Container} used to create a scoped container and resolve {@link Logger}.\n * @returns {@link ServerKitMiddleware} that attaches ServerKit context to `ctx`.\n */\nexport const serverKitContextMiddleware = (container: Container): ServerKitMiddleware => {\n return async (ctx, next) => {\n ctx.container = container.createScopedContainer();\n ctx.logger = container.get(Logger);\n ctx.loggerName = ctx.path;\n\n ctx.userAgent = ctx.get('user-agent') ?? '';\n ctx.correlationId = ctx.get('x-correlation-id') ?? crypto.randomUUID();\n ctx.requestId = ctx.get('x-request-id') ?? crypto.randomUUID();\n\n ctx.headers['x-correlation-id'] = ctx.correlationId;\n ctx.set('x-correlation-id', ctx.correlationId);\n\n ctx.headers['x-request-id'] = ctx.requestId;\n ctx.set('x-request-id', ctx.requestId);\n\n await next();\n };\n};\n","import coBody from 'co-body';\nimport { httpError, IsHttpError } from '@maroonedsoftware/errors';\nimport { MultipartBody } from '@maroonedsoftware/multipart';\nimport rawBody from 'raw-body';\nimport { ServerKitMiddleware } from '../../serverkit.middleware.js';\n\n/**\n * Parses the request body based on `Content-Type` and assigns it to `ctx.body`.\n * Rejects requests with unexpected or unsupported content types.\n *\n * Supported types: JSON, URL-encoded form, text, multipart, PDF (raw buffer).\n * Requires a body when `contentTypes` is non-empty; otherwise rejects bodies.\n *\n * @param contentTypes - Allowed MIME types (e.g. `['application/json', 'application/x-www-form-urlencoded']`).\n * Use an empty array to disallow any request body.\n * @returns {@link ServerKitMiddleware} that parses the body and sets `ctx.body`.\n * @throws HTTP 400 if body is present when no content types are allowed.\n * @throws HTTP 411 if body is required but missing.\n * @throws HTTP 415 if `Content-Type` is not in `contentTypes`.\n * @throws HTTP 422 if body is invalid or media type is unsupported.\n */\nexport const bodyParserMiddleware = (contentTypes: string[]): ServerKitMiddleware => {\n return async (ctx, next) => {\n if (contentTypes.length === 0) {\n if (ctx.request.length > 0) {\n throw httpError(400).withDetails({ body: 'Unexpected body' });\n }\n } else {\n if (ctx.request.length > 0) {\n if (!ctx.request.is(contentTypes)) {\n throw httpError(415).withDetails({\n 'content-type': `must be ${contentTypes.length > 1 ? 'one of ' : ''}${contentTypes.join(', ')}`,\n value: ctx.request.type,\n });\n }\n\n try {\n if (ctx.request.is('json', 'application/*+json')) {\n ctx.body = await coBody.json(ctx);\n } else if (ctx.request.is('urlencoded')) {\n ctx.body = await coBody.form(ctx);\n } else if (ctx.request.is('text/*')) {\n ctx.body = await coBody.text(ctx);\n } else if (ctx.request.is('multipart')) {\n ctx.body = new MultipartBody(ctx.req);\n } else if (ctx.request.is('pdf')) {\n ctx.body = await rawBody(ctx.req);\n } else {\n throw httpError(422).withDetails({ body: 'Unsupported media type' });\n }\n } catch (error) {\n if (IsHttpError(error)) {\n throw error;\n }\n throw httpError(422)\n .withCause(error as Error)\n .withDetails({ body: 'Invalid request body format' });\n }\n } else {\n throw httpError(411);\n }\n }\n await next();\n };\n};\n"],"mappings":"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","names":["Router","ServerKitRouter","Router","cors","corsMiddleware","options","originMatcher","ctx","origin","get","matchers","matcher","test","cors","allowMethods","secureContext","keepHeadersOnError","privateNetworkAccess","IsHttpError","errorMiddleware","ctx","next","status","body","statusCode","message","details","url","URL","toString","app","emit","error","IsHttpError","headers","entry","Object","entries","set","httpError","rateLimiterMiddleware","rateLimiter","ctx","next","consume","ip","error","httpError","withCause","crypto","Logger","serverKitContextMiddleware","container","ctx","next","createScopedContainer","logger","get","Logger","loggerName","path","userAgent","correlationId","crypto","randomUUID","requestId","headers","set","coBody","httpError","IsHttpError","MultipartBody","rawBody","bodyParserMiddleware","contentTypes","ctx","next","length","request","httpError","withDetails","body","is","join","value","type","coBody","json","form","text","MultipartBody","req","rawBody","error","IsHttpError","withCause"]}
1
+ {"version":3,"sources":["../src/serverkit.router.ts","../src/middleware/server/cors.middleware.ts","../src/middleware/server/error.middleware.ts","../src/middleware/server/rate.limiter.middleware.ts","../src/middleware/server/serverkit.context.middleware.ts","../src/middleware/server/authentication.middleware.ts","../src/middleware/router/body.parser.middleware.ts","../src/serverkit.bodyparser.ts","../src/parsers/serverkit.parser.ts","../src/parsers/json.parser.ts","../src/parsers/text.parser.ts","../src/parsers/form.parser.ts","../src/parsers/multipart.parser.ts","../src/parsers/binary.parser.ts","../src/parsers.setup.ts"],"sourcesContent":["import { DefaultState } from 'koa';\nimport Router from '@koa/router';\nimport { ServerKitContext } from './serverkit.context.js';\n\n/**\n * Creates a new Koa router typed for ServerKit state and context.\n * Use with {@link ServerKitContext} for full typing of `ctx` in route handlers.\n *\n * @typeParam StateT - Koa state type (defaults to `DefaultState`).\n * @typeParam ContextT - Context type (defaults to `ServerKitContext`).\n * @returns A new {@link Router} instance.\n */\nexport const ServerKitRouter = <StateT = DefaultState, ContextT = ServerKitContext>() => new Router<StateT, ContextT>();\n","import cors from '@koa/cors';\nimport { ServerKitMiddleware } from '../../serverkit.middleware.js';\nimport { Context } from 'koa';\n\n/**\n * CORS options for {@link corsMiddleware}.\n * Extends `@koa/cors` options with an `origin` that may be a string or array of strings/RegExps.\n */\nexport interface CorsOptions extends Omit<cors.Options, 'origin'> {\n /** Allowed origin(s): `'*'`, a single origin string, or an array of strings/RegExps to match. */\n origin?: string | (string | RegExp)[];\n}\n\n/**\n * Adds CORS headers to responses using `@koa/cors` with ServerKit-compatible origin matching.\n * Supports `'*'`, exact string origins, and RegExp patterns.\n *\n * @param options - Optional {@link CorsOptions}; defaults to `GET,HEAD,PUT,POST,DELETE,PATCH` methods.\n * @returns {@link ServerKitMiddleware} that applies CORS headers.\n */\nexport const corsMiddleware = (options?: CorsOptions): ServerKitMiddleware => {\n // return the request origin as its own matcher to support RegExp\n const originMatcher = (ctx: Context): string => {\n const origin = ctx.get('origin');\n const matchers = options?.origin ?? ['*'];\n for (const matcher of matchers) {\n if (matcher === '*') {\n return origin;\n }\n\n if (typeof matcher === 'string') {\n if (matcher === origin) {\n return origin;\n }\n continue;\n }\n\n if (matcher.test(origin)) {\n return origin;\n }\n }\n\n // return the zero value to prevent matches\n return '';\n };\n\n return cors({\n ...options,\n origin: originMatcher,\n allowMethods: options?.allowMethods ?? 'GET,HEAD,PUT,POST,DELETE,PATCH',\n secureContext: options?.secureContext ?? false,\n keepHeadersOnError: options?.keepHeadersOnError ?? false,\n privateNetworkAccess: options?.privateNetworkAccess ?? false,\n });\n};\n","import { ServerKitMiddleware } from '../../serverkit.middleware.js';\nimport { IsHttpError } from '@maroonedsoftware/errors';\n\n/**\n * Central error handler: catches thrown errors, sets status/body from HTTP errors,\n * returns 404 for unmatched routes, and 500 for unknown errors.\n * Emits `error` or `warn` on the app for logging.\n *\n * @returns {@link ServerKitMiddleware} that wraps the stack in try/catch and normalizes responses.\n */\nexport const errorMiddleware = (): ServerKitMiddleware => {\n return async (ctx, next) => {\n try {\n await next();\n if (ctx.status === 404 && !ctx.body) {\n const body = {\n statusCode: 404,\n message: 'Not Found',\n details: { url: ctx.URL.toString() },\n };\n ctx.status = 404;\n ctx.body = body;\n ctx.app.emit('warn', body, ctx);\n }\n } catch (error) {\n if (IsHttpError(error)) {\n ctx.status = error.statusCode;\n ctx.body = {\n statusCode: error.statusCode,\n message: error.message,\n details: error.details,\n };\n if (error.headers) {\n for (const entry of Object.entries(error.headers)) {\n ctx.set(entry[0], entry[1]);\n }\n }\n } else {\n ctx.status = 500;\n ctx.body = {\n statusCode: 500,\n message: 'Internal Server Error',\n };\n }\n\n ctx.app.emit('error', error, ctx);\n }\n };\n};\n","import { RateLimiterAbstract } from 'rate-limiter-flexible';\nimport { ServerKitMiddleware } from '../../serverkit.middleware.js';\nimport { httpError } from '@maroonedsoftware/errors';\n\n/**\n * Enforces rate limiting per client IP using a `rate-limiter-flexible` instance.\n * Consumes one token per request; throws HTTP 429 when the limit is exceeded.\n *\n * @param rateLimiter - A {@link RateLimiterAbstract} instance (e.g. `RateLimiterMemory`, `RateLimiterRedis`).\n * @returns {@link ServerKitMiddleware} that consumes a token and continues or throws 429.\n */\nexport const rateLimiterMiddleware = (rateLimiter: RateLimiterAbstract): ServerKitMiddleware => {\n return async (ctx, next) => {\n try {\n await rateLimiter.consume(ctx.ip);\n } catch (error) {\n throw httpError(429).withCause(error as Error);\n }\n\n await next();\n };\n};\n","import crypto from 'crypto';\nimport { Container } from 'injectkit';\nimport { Logger } from '@maroonedsoftware/logger';\nimport { ServerKitMiddleware } from '../../serverkit.middleware.js';\n\n/**\n * Populates {@link ServerKitContext} for each request: scoped container, logger,\n * logger name, user-agent, correlation ID, and request ID.\n * Reads or generates `X-Correlation-Id` and `X-Request-Id` and sets response headers.\n * Should be applied early so downstream middleware and routes can use `ctx.container` and `ctx.logger`.\n *\n * @param container - Root injectkit {@link Container} used to create a scoped container and resolve {@link Logger}.\n * @returns {@link ServerKitMiddleware} that attaches ServerKit context to `ctx`.\n */\nexport const serverKitContextMiddleware = (container: Container): ServerKitMiddleware => {\n return async (ctx, next) => {\n ctx.container = container.createScopedContainer();\n ctx.logger = container.get(Logger);\n ctx.loggerName = ctx.path;\n\n ctx.userAgent = ctx.get('user-agent') ?? '';\n ctx.correlationId = ctx.get('x-correlation-id') ?? crypto.randomUUID();\n ctx.requestId = ctx.get('x-request-id') ?? crypto.randomUUID();\n\n ctx.headers['x-correlation-id'] = ctx.correlationId;\n ctx.set('x-correlation-id', ctx.correlationId);\n\n ctx.headers['x-request-id'] = ctx.requestId;\n ctx.set('x-request-id', ctx.requestId);\n\n await next();\n };\n};\n","import { ServerKitMiddleware } from '../../serverkit.middleware.js';\nimport { AuthenticationSchemeHandler, invalidAuthenticationContext } from '@maroonedsoftware/authentication';\n\n/**\n * Resolves the `Authorization` request header into an {@link AuthenticationContext}\n * and attaches it to `ctx.authenticationContext`.\n *\n * The header is immediately removed from `ctx.req.headers` after being read so it\n * cannot be accidentally captured by downstream logging or serialization.\n *\n * Resolution is delegated to the {@link AuthenticationSchemeHandler} registered in\n * the DI container. `ctx.authenticationContext` is initialised to\n * {@link invalidAuthenticationContext} before delegation, ensuring that any error\n * thrown by the scheme handler leaves the context in a safe, unauthenticated state.\n *\n * @returns A {@link ServerKitMiddleware} that populates `ctx.authenticationContext`.\n *\n * @example\n * ```typescript\n * app.use(authenticationMiddleware());\n * ```\n */\nexport const authenticationMiddleware = (): ServerKitMiddleware => {\n return async (ctx, next) => {\n ctx.authenticationContext = invalidAuthenticationContext; // bad initial state so it will fail verification\n\n // NOTE: we delete the auth headers on the request here to ensure we don't accidentally log it\n const authorizationHeader = ctx.req.headers.authorization;\n delete ctx.req.headers.authorization;\n\n const schemeHandler = ctx.serviceLocator.get(AuthenticationSchemeHandler);\n\n ctx.authenticationContext = await schemeHandler.handle(authorizationHeader);\n\n await next();\n };\n};\n","import { httpError, IsHttpError } from '@maroonedsoftware/errors';\nimport { ServerKitMiddleware } from '../../serverkit.middleware.js';\nimport { ServerKitBodyParser } from '../../serverkit.bodyparser.js';\n\n/**\n * Parses the request body based on `Content-Type` and assigns it to `ctx.body`.\n * Rejects requests with unexpected or unsupported content types.\n *\n * Supported types: JSON, URL-encoded form, text, multipart, PDF (raw buffer).\n * Requires a body when `contentTypes` is non-empty; otherwise rejects bodies.\n *\n * @param contentTypes - Allowed MIME types (e.g. `['application/json', 'application/x-www-form-urlencoded']`).\n * Use an empty array to disallow any request body.\n * @returns {@link ServerKitMiddleware} that parses the body and sets `ctx.body`.\n * @throws HTTP 400 if body is present when no content types are allowed.\n * @throws HTTP 411 if body is required but missing.\n * @throws HTTP 415 if `Content-Type` is not in `contentTypes`.\n * @throws HTTP 422 if body is invalid or media type is unsupported.\n */\nexport const bodyParserMiddleware = (contentTypes: string[]): ServerKitMiddleware => {\n return async (ctx, next) => {\n if (contentTypes.length === 0) {\n if (ctx.request.length > 0) {\n throw httpError(400).withDetails({ body: 'Unexpected body' });\n }\n } else {\n if (ctx.request.length > 0) {\n if (!ctx.request.is(contentTypes)) {\n throw httpError(415).withDetails({\n 'content-type': `must be ${contentTypes.length > 1 ? 'one of ' : ''}${contentTypes.join(', ')}`,\n value: ctx.request.type,\n });\n }\n\n try {\n const parser = ctx.container.get(ServerKitBodyParser);\n const result = await parser.parse(ctx);\n ctx.body = result.parsed;\n ctx.rawBody = result.raw;\n } catch (error) {\n if (IsHttpError(error)) {\n throw error;\n }\n throw httpError(422)\n .withCause(error as Error)\n .withDetails({ body: 'Invalid request body format' });\n }\n } else {\n throw httpError(411);\n }\n }\n await next();\n };\n};\n","import { Injectable } from 'injectkit';\nimport { ServerKitParser, ServerKitParserResult } from './parsers/serverkit.parser.js';\nimport { ServerKitContext } from './serverkit.context.js';\nimport { unique } from '@maroonedsoftware/utilities';\nimport { httpError } from '@maroonedsoftware/errors';\n\n@Injectable()\nexport class ServerKitParserMappings extends Map<string, ServerKitParser> {}\n\n@Injectable()\nexport class ServerKitBodyParser {\n private readonly mimeTypes: string[];\n constructor(private readonly parsers: ServerKitParserMappings) {\n this.mimeTypes = unique(Array.from(this.parsers.keys()));\n }\n\n async parse(ctx: ServerKitContext): Promise<ServerKitParserResult> {\n const mimeType = ctx.request.is(this.mimeTypes);\n if (!mimeType) {\n throw httpError(415).withDetails({ body: 'Unsupported media type' });\n }\n const parser = this.parsers.get(mimeType);\n if (!parser) {\n throw httpError(415).withDetails({ body: 'Unsupported media type' });\n }\n return parser.parse(ctx.req);\n }\n}\n","import { IncomingMessage } from 'http';\nimport { Injectable } from 'injectkit';\n\nexport type ServerKitParserResult = {\n parsed: unknown;\n raw: unknown;\n};\n\n@Injectable()\nexport abstract class ServerKitParser {\n abstract parse(req: IncomingMessage): Promise<ServerKitParserResult>;\n}\n","import { parse, Reviver } from '@hapi/bourne';\nimport { IncomingMessage } from 'http';\nimport raw from 'raw-body';\nimport inflate from 'inflation';\nimport { httpError } from '@maroonedsoftware/errors';\nimport { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';\nimport { Injectable } from 'injectkit';\n\nexport type JsonParserOptions = raw.Options & {\n strict?: boolean;\n protoAction?: 'error' | 'remove' | 'ignore';\n reviver?: Reviver;\n};\n\n// Allowed whitespace is defined in RFC 7159\n// http://www.rfc-editor.org/rfc/rfc7159.txt\n/* eslint-disable-next-line no-control-regex */\nconst strictJSONReg = /^[\\x20\\x09\\x0a\\x0d]*(\\[|\\{)/;\n\n@Injectable()\nexport class JsonParser extends ServerKitParser {\n constructor(private readonly options: JsonParserOptions = {}) {\n super();\n }\n\n async parse(req: IncomingMessage): Promise<ServerKitParserResult> {\n const len = req.headers['content-length'];\n const contentEncoding = req.headers['content-encoding'] || 'identity';\n const length: number | undefined = len && contentEncoding === 'identity' ? ~~len : undefined;\n const encoding = this.options.encoding ?? 'utf8';\n const limit = this.options.limit ?? '1mb';\n\n const strict = this.options.strict ?? true;\n const protoAction = this.options.protoAction ?? 'error';\n\n const str = await raw(inflate(req), { encoding, limit, length });\n\n const doParse = (str: string) => {\n try {\n if (this.options.reviver) {\n return parse(str, this.options.reviver, { protoAction });\n }\n return parse(str, { protoAction });\n } catch (err) {\n throw httpError(400).withCause(err as Error);\n }\n };\n\n if (!strict) {\n return str ? { parsed: doParse(str), raw: str } : { parsed: undefined, raw: str };\n } else if (!str) {\n return { parsed: undefined, raw: str };\n } else if (!strictJSONReg.test(str)) {\n throw httpError(400).withDetails({ body: 'Invalid JSON, only supports object and array' });\n }\n return { parsed: doParse(str), raw: str };\n }\n}\n","import { Injectable } from 'injectkit';\nimport { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';\nimport { IncomingMessage } from 'http';\nimport raw from 'raw-body';\nimport inflate from 'inflation';\n\nexport type TextParserOptions = raw.Options;\n\n@Injectable()\nexport class TextParser extends ServerKitParser {\n constructor(private readonly options: TextParserOptions = {}) {\n super();\n }\n\n async parse(req: IncomingMessage): Promise<ServerKitParserResult> {\n const len = req.headers['content-length'];\n const contentEncoding = req.headers['content-encoding'] || 'identity';\n const length: number | undefined = len && contentEncoding === 'identity' ? ~~len : undefined;\n const encoding = this.options.encoding ?? 'utf8';\n const limit = this.options.limit ?? '1mb';\n\n const str = await raw(inflate(req), { encoding, limit, length });\n\n return { parsed: str, raw: str };\n }\n}\n","import { httpError } from '@maroonedsoftware/errors';\nimport { Injectable } from 'injectkit';\nimport { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';\nimport { IncomingMessage } from 'http';\nimport { parse, IParseOptions } from 'qs';\nimport raw from 'raw-body';\nimport inflate from 'inflation';\n\nexport type FormParserOptions = raw.Options & IParseOptions;\n\n@Injectable()\nexport class FormParser extends ServerKitParser {\n constructor(private readonly options: FormParserOptions = {}) {\n super();\n }\n\n async parse(req: IncomingMessage): Promise<ServerKitParserResult> {\n const len = req.headers['content-length'];\n const contentEncoding = req.headers['content-encoding'] || 'identity';\n const length: number | undefined = len && contentEncoding === 'identity' ? ~~len : undefined;\n const encoding = this.options.encoding ?? 'utf8';\n const limit = this.options.limit ?? '56kb';\n\n const str = await raw(inflate(req), { encoding, limit, length });\n\n try {\n return { parsed: parse(str, this.options), raw: str };\n } catch (err) {\n throw httpError(400).withCause(err as Error);\n }\n }\n}\n","import { Injectable } from 'injectkit';\nimport { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';\nimport { IncomingMessage } from 'http';\nimport { MultipartBody } from '@maroonedsoftware/multipart';\n\n@Injectable()\nexport class MultipartParser extends ServerKitParser {\n async parse(req: IncomingMessage): Promise<ServerKitParserResult> {\n return { parsed: new MultipartBody(req), raw: undefined };\n }\n}\n","import { Injectable } from 'injectkit';\nimport { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';\nimport { IncomingMessage } from 'http';\nimport raw from 'raw-body';\nimport inflate from 'inflation';\n\n@Injectable()\nexport class BinaryParser extends ServerKitParser {\n async parse(req: IncomingMessage): Promise<ServerKitParserResult> {\n return { parsed: await raw(inflate(req)), raw: undefined };\n }\n}\n","import { Constructor, Registry } from 'injectkit';\nimport { ServerKitBodyParser, ServerKitParserMappings } from './serverkit.bodyparser.js';\nimport { ServerKitParser } from './parsers/serverkit.parser.js';\nimport { JsonParser } from './parsers/json.parser.js';\nimport { TextParser } from './parsers/text.parser.js';\nimport { FormParser } from './parsers/form.parser.js';\nimport { MultipartParser } from './parsers/multipart.parser.js';\nimport { BinaryParser } from './parsers/binary.parser.js';\n\nexport type ParserMappingOverrides = Record<string, Constructor<ServerKitParser>>;\n\nconst defaultParserMappings: ParserMappingOverrides = {\n 'json': JsonParser,\n 'application/*+json': JsonParser,\n 'urlencoded': FormParser,\n 'text': TextParser,\n 'multipart': MultipartParser,\n};\n\nconst defaultParserClasses: Constructor<ServerKitParser>[] = [\n JsonParser,\n FormParser,\n TextParser,\n MultipartParser,\n BinaryParser,\n];\n\nexport const setupParsers = (registry: Registry, overrides: ParserMappingOverrides = {}) => {\n const merged = { ...defaultParserMappings, ...overrides };\n\n const mapRegistration = registry\n .register(ServerKitParserMappings)\n .useMap(ServerKitParserMappings);\n\n for (const [key, parser] of Object.entries(merged)) {\n mapRegistration.set(key, parser);\n }\n\n const parserClasses = new Set<Constructor<ServerKitParser>>([\n ...defaultParserClasses,\n ...Object.values(overrides),\n ]);\n\n for (const parserClass of parserClasses) {\n registry.register(parserClass).useClass(parserClass).asSingleton();\n }\n\n registry.register(ServerKitBodyParser).useClass(ServerKitBodyParser).asSingleton();\n};\n"],"mappings":"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","names":["Router","ServerKitRouter","Router","cors","corsMiddleware","options","originMatcher","ctx","origin","get","matchers","matcher","test","cors","allowMethods","secureContext","keepHeadersOnError","privateNetworkAccess","IsHttpError","errorMiddleware","ctx","next","status","body","statusCode","message","details","url","URL","toString","app","emit","error","IsHttpError","headers","entry","Object","entries","set","httpError","rateLimiterMiddleware","rateLimiter","ctx","next","consume","ip","error","httpError","withCause","crypto","Logger","serverKitContextMiddleware","container","ctx","next","createScopedContainer","logger","get","Logger","loggerName","path","userAgent","correlationId","crypto","randomUUID","requestId","headers","set","AuthenticationSchemeHandler","invalidAuthenticationContext","authenticationMiddleware","ctx","next","authenticationContext","invalidAuthenticationContext","authorizationHeader","req","headers","authorization","schemeHandler","serviceLocator","get","AuthenticationSchemeHandler","handle","httpError","IsHttpError","Injectable","unique","httpError","ServerKitParserMappings","Map","ServerKitBodyParser","mimeTypes","parsers","unique","Array","from","keys","parse","ctx","mimeType","request","is","httpError","withDetails","body","parser","get","req","bodyParserMiddleware","contentTypes","ctx","next","length","request","httpError","withDetails","body","is","join","value","type","parser","container","get","ServerKitBodyParser","result","parse","parsed","rawBody","raw","error","IsHttpError","withCause","Injectable","ServerKitParser","parse","raw","inflate","httpError","Injectable","strictJSONReg","JsonParser","ServerKitParser","options","parse","req","len","headers","contentEncoding","length","undefined","encoding","limit","strict","protoAction","str","raw","inflate","doParse","reviver","err","httpError","withCause","parsed","test","withDetails","body","Injectable","raw","inflate","TextParser","ServerKitParser","options","parse","req","len","headers","contentEncoding","length","undefined","encoding","limit","str","raw","inflate","parsed","httpError","Injectable","parse","raw","inflate","FormParser","ServerKitParser","options","parse","req","len","headers","contentEncoding","length","undefined","encoding","limit","str","raw","inflate","parsed","err","httpError","withCause","Injectable","MultipartBody","MultipartParser","ServerKitParser","parse","req","parsed","MultipartBody","raw","undefined","Injectable","raw","inflate","BinaryParser","ServerKitParser","parse","req","parsed","raw","inflate","undefined","defaultParserMappings","JsonParser","FormParser","TextParser","MultipartParser","defaultParserClasses","BinaryParser","setupParsers","registry","overrides","merged","mapRegistration","register","ServerKitParserMappings","useMap","key","parser","Object","entries","set","parserClasses","Set","values","parserClass","useClass","asSingleton","ServerKitBodyParser"]}
@@ -1 +1 @@
1
- {"version":3,"file":"body.parser.middleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/router/body.parser.middleware.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAAI,cAAc,MAAM,EAAE,KAAG,mBA2C7D,CAAC"}
1
+ {"version":3,"file":"body.parser.middleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/router/body.parser.middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAGpE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAAI,cAAc,MAAM,EAAE,KAAG,mBAkC7D,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { ServerKitMiddleware } from '../../serverkit.middleware.js';
2
+ /**
3
+ * Resolves the `Authorization` request header into an {@link AuthenticationContext}
4
+ * and attaches it to `ctx.authenticationContext`.
5
+ *
6
+ * The header is immediately removed from `ctx.req.headers` after being read so it
7
+ * cannot be accidentally captured by downstream logging or serialization.
8
+ *
9
+ * Resolution is delegated to the {@link AuthenticationSchemeHandler} registered in
10
+ * the DI container. `ctx.authenticationContext` is initialised to
11
+ * {@link invalidAuthenticationContext} before delegation, ensuring that any error
12
+ * thrown by the scheme handler leaves the context in a safe, unauthenticated state.
13
+ *
14
+ * @returns A {@link ServerKitMiddleware} that populates `ctx.authenticationContext`.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * app.use(authenticationMiddleware());
19
+ * ```
20
+ */
21
+ export declare const authenticationMiddleware: () => ServerKitMiddleware;
22
+ //# sourceMappingURL=authentication.middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authentication.middleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/server/authentication.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAGpE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,wBAAwB,QAAO,mBAc3C,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';
2
+ import { IncomingMessage } from 'http';
3
+ export declare class BinaryParser extends ServerKitParser {
4
+ parse(req: IncomingMessage): Promise<ServerKitParserResult>;
5
+ }
6
+ //# sourceMappingURL=binary.parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary.parser.d.ts","sourceRoot":"","sources":["../../src/parsers/binary.parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAIvC,qBACa,YAAa,SAAQ,eAAe;IACzC,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAGlE"}
@@ -0,0 +1,11 @@
1
+ import { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';
2
+ import { IncomingMessage } from 'http';
3
+ import { IParseOptions } from 'qs';
4
+ import raw from 'raw-body';
5
+ export type FormParserOptions = raw.Options & IParseOptions;
6
+ export declare class FormParser extends ServerKitParser {
7
+ private readonly options;
8
+ constructor(options?: FormParserOptions);
9
+ parse(req: IncomingMessage): Promise<ServerKitParserResult>;
10
+ }
11
+ //# sourceMappingURL=form.parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.parser.d.ts","sourceRoot":"","sources":["../../src/parsers/form.parser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,EAAS,aAAa,EAAE,MAAM,IAAI,CAAC;AAC1C,OAAO,GAAG,MAAM,UAAU,CAAC;AAG3B,MAAM,MAAM,iBAAiB,GAAG,GAAG,CAAC,OAAO,GAAG,aAAa,CAAC;AAE5D,qBACa,UAAW,SAAQ,eAAe;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,iBAAsB;IAItD,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAelE"}
@@ -0,0 +1,15 @@
1
+ import { Reviver } from '@hapi/bourne';
2
+ import { IncomingMessage } from 'http';
3
+ import raw from 'raw-body';
4
+ import { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';
5
+ export type JsonParserOptions = raw.Options & {
6
+ strict?: boolean;
7
+ protoAction?: 'error' | 'remove' | 'ignore';
8
+ reviver?: Reviver;
9
+ };
10
+ export declare class JsonParser extends ServerKitParser {
11
+ private readonly options;
12
+ constructor(options?: JsonParserOptions);
13
+ parse(req: IncomingMessage): Promise<ServerKitParserResult>;
14
+ }
15
+ //# sourceMappingURL=json.parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.parser.d.ts","sourceRoot":"","sources":["../../src/parsers/json.parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,GAAG,MAAM,UAAU,CAAC;AAG3B,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG/E,MAAM,MAAM,iBAAiB,GAAG,GAAG,CAAC,OAAO,GAAG;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAOF,qBACa,UAAW,SAAQ,eAAe;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,iBAAsB;IAItD,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAgClE"}
@@ -0,0 +1,6 @@
1
+ import { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';
2
+ import { IncomingMessage } from 'http';
3
+ export declare class MultipartParser extends ServerKitParser {
4
+ parse(req: IncomingMessage): Promise<ServerKitParserResult>;
5
+ }
6
+ //# sourceMappingURL=multipart.parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipart.parser.d.ts","sourceRoot":"","sources":["../../src/parsers/multipart.parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAGvC,qBACa,eAAgB,SAAQ,eAAe;IAC5C,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAGlE"}
@@ -0,0 +1,9 @@
1
+ import { IncomingMessage } from 'http';
2
+ export type ServerKitParserResult = {
3
+ parsed: unknown;
4
+ raw: unknown;
5
+ };
6
+ export declare abstract class ServerKitParser {
7
+ abstract parse(req: IncomingMessage): Promise<ServerKitParserResult>;
8
+ }
9
+ //# sourceMappingURL=serverkit.parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverkit.parser.d.ts","sourceRoot":"","sources":["../../src/parsers/serverkit.parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAGvC,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,8BACsB,eAAe;IACnC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,qBAAqB,CAAC;CACrE"}
@@ -0,0 +1,10 @@
1
+ import { ServerKitParser, ServerKitParserResult } from './serverkit.parser.js';
2
+ import { IncomingMessage } from 'http';
3
+ import raw from 'raw-body';
4
+ export type TextParserOptions = raw.Options;
5
+ export declare class TextParser extends ServerKitParser {
6
+ private readonly options;
7
+ constructor(options?: TextParserOptions);
8
+ parse(req: IncomingMessage): Promise<ServerKitParserResult>;
9
+ }
10
+ //# sourceMappingURL=text.parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.parser.d.ts","sourceRoot":"","sources":["../../src/parsers/text.parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,GAAG,MAAM,UAAU,CAAC;AAG3B,MAAM,MAAM,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAAC;AAE5C,qBACa,UAAW,SAAQ,eAAe;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,iBAAsB;IAItD,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAWlE"}
@@ -0,0 +1,5 @@
1
+ import { Constructor, Registry } from 'injectkit';
2
+ import { ServerKitParser } from './parsers/serverkit.parser.js';
3
+ export type ParserMappingOverrides = Record<string, Constructor<ServerKitParser>>;
4
+ export declare const setupParsers: (registry: Registry, overrides?: ParserMappingOverrides) => void;
5
+ //# sourceMappingURL=parsers.setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.setup.d.ts","sourceRoot":"","sources":["../src/parsers.setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAOhE,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC,CAAC;AAkBlF,eAAO,MAAM,YAAY,GAAI,UAAU,QAAQ,EAAE,YAAW,sBAA2B,SAqBtF,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { ServerKitParser, ServerKitParserResult } from './parsers/serverkit.parser.js';
2
+ import { ServerKitContext } from './serverkit.context.js';
3
+ export declare class ServerKitParserMappings extends Map<string, ServerKitParser> {
4
+ }
5
+ export declare class ServerKitBodyParser {
6
+ private readonly parsers;
7
+ private readonly mimeTypes;
8
+ constructor(parsers: ServerKitParserMappings);
9
+ parse(ctx: ServerKitContext): Promise<ServerKitParserResult>;
10
+ }
11
+ //# sourceMappingURL=serverkit.bodyparser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverkit.bodyparser.d.ts","sourceRoot":"","sources":["../src/serverkit.bodyparser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI1D,qBACa,uBAAwB,SAAQ,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;CAAG;AAE5E,qBACa,mBAAmB;IAElB,OAAO,CAAC,QAAQ,CAAC,OAAO;IADpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;gBACR,OAAO,EAAE,uBAAuB;IAIvD,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAWnE"}
@@ -1,6 +1,7 @@
1
1
  import { Context } from 'koa';
2
2
  import { Container } from 'injectkit';
3
3
  import { Logger } from '@maroonedsoftware/logger';
4
+ import { AuthenticationContext } from '@maroonedsoftware/authentication';
4
5
  /**
5
6
  * Koa context extended with ServerKit request-scoped services and metadata.
6
7
  * Populated by {@link serverKitContextMiddleware}.
@@ -22,5 +23,9 @@ export interface ServerKitContext extends Context {
22
23
  correlationId: string;
23
24
  /** Request ID; from `X-Request-Id` header or generated. */
24
25
  requestId: string;
26
+ /** Raw body for this request. */
27
+ rawBody: unknown;
28
+ /** Authentication context. */
29
+ authenticationContext: AuthenticationContext;
25
30
  }
26
31
  //# sourceMappingURL=serverkit.context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"serverkit.context.d.ts","sourceRoot":"","sources":["../src/serverkit.context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAiB,SAAQ,OAAO;IAC/C,8EAA8E;IAC9E,SAAS,EAAE,SAAS,CAAC;IACrB,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"serverkit.context.d.ts","sourceRoot":"","sources":["../src/serverkit.context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAEzE;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAiB,SAAQ,OAAO;IAC/C,8EAA8E;IAC9E,SAAS,EAAE,SAAS,CAAC;IACrB,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,qBAAqB,EAAE,qBAAqB,CAAC;CAC9C"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maroonedsoftware/koa",
3
- "version": "1.1.1",
4
- "description": "",
3
+ "version": "1.2.1",
4
+ "description": "Koa middleware, body parsing, and utilities for ServerKit",
5
5
  "author": {
6
6
  "name": "Marooned Software",
7
7
  "url": "https://github.com/MaroonedSoftware/serverkit"
@@ -30,12 +30,17 @@
30
30
  "dist/**"
31
31
  ],
32
32
  "dependencies": {
33
+ "@hapi/bourne": "^3.0.0",
33
34
  "co-body": "^6.2.0",
34
- "injectkit": "^1.0.3",
35
- "rate-limiter-flexible": "^9.0.1",
35
+ "inflation": "^2.1.0",
36
+ "injectkit": "^1.1.3",
37
+ "qs": "^6.15.0",
38
+ "rate-limiter-flexible": "^9.1.1",
36
39
  "raw-body": "^3.0.2",
37
40
  "@maroonedsoftware/errors": "1.2.0",
38
41
  "@maroonedsoftware/multipart": "1.0.2",
42
+ "@maroonedsoftware/utilities": "1.1.0",
43
+ "@maroonedsoftware/authentication": "0.0.1",
39
44
  "@maroonedsoftware/logger": "1.0.0"
40
45
  },
41
46
  "peerDependencies": {
@@ -45,13 +50,15 @@
45
50
  },
46
51
  "devDependencies": {
47
52
  "@koa/cors": "^5.0.0",
48
- "@koa/router": "^15.2.0",
53
+ "@koa/router": "^15.3.1",
49
54
  "@types/co-body": "^6.1.3",
55
+ "@types/inflation": "^2.0.4",
50
56
  "@types/koa": "^3.0.1",
51
57
  "@types/koa__cors": "^5.0.1",
52
- "koa": "^3.1.1",
53
- "@repo/config-eslint": "0.0.0",
54
- "@repo/config-typescript": "0.0.0"
58
+ "@types/qs": "^6.15.0",
59
+ "koa": "^3.1.2",
60
+ "@repo/config-typescript": "0.0.0",
61
+ "@repo/config-eslint": "0.1.0"
55
62
  },
56
63
  "scripts": {
57
64
  "build": "tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly --declaration",