@aeriajs/http 0.0.193 → 0.0.194

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/cors.js CHANGED
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.cors = void 0;
4
- const cors = async (req, res, config) => {
1
+ export const cors = async (req, res, config) => {
5
2
  const { allowOrigin = [], allowMethods = [], allowHeaders = [], maxAge, } = config;
6
3
  const headers = {
7
4
  'Access-Control-Allow-Origin': allowOrigin.join(','),
@@ -18,4 +15,3 @@ const cors = async (req, res, config) => {
18
15
  res.setHeader(key, value);
19
16
  });
20
17
  };
21
- exports.cors = cors;
package/dist/index.js CHANGED
@@ -1,20 +1,4 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./cors.js"), exports);
18
- __exportStar(require("./log.js"), exports);
19
- __exportStar(require("./routing.js"), exports);
20
- __exportStar(require("./payload.js"), exports);
1
+ export * from './cors.js';
2
+ export * from './log.js';
3
+ export * from './routing.js';
4
+ export * from './payload.js';
package/dist/log.js CHANGED
@@ -1,9 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.logResponse = void 0;
4
- const types_1 = require("@aeriajs/types");
5
- const node_util_1 = require("node:util");
6
- const logResponse = (response) => {
1
+ import { METHOD_COLORS } from '@aeriajs/types';
2
+ import { styleText } from 'node:util';
3
+ export const logResponse = (response) => {
7
4
  const { statusCode, req: { method, url } } = response;
8
5
  if (!method) {
9
6
  return;
@@ -11,17 +8,16 @@ const logResponse = (response) => {
11
8
  const statusColor = statusCode >= 400 && statusCode <= 599
12
9
  ? 'red'
13
10
  : 'white';
14
- const methodColor = method in types_1.METHOD_COLORS
15
- ? types_1.METHOD_COLORS[method]
11
+ const methodColor = method in METHOD_COLORS
12
+ ? METHOD_COLORS[method]
16
13
  : 'white';
17
14
  const now = new Date();
18
- let line = `[${(0, node_util_1.styleText)(statusColor, statusCode.toString())}] `;
15
+ let line = `[${styleText(statusColor, statusCode.toString())}] `;
19
16
  line += `[${now.toLocaleString()}] `;
20
- line += (0, node_util_1.styleText)([
17
+ line += styleText([
21
18
  'bold',
22
19
  methodColor,
23
20
  ], method) + ' ';
24
21
  line += url;
25
22
  console.log(line);
26
23
  };
27
- exports.logResponse = logResponse;
package/dist/payload.js CHANGED
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.safeJson = void 0;
4
- const safeJson = (candidate) => {
1
+ export const safeJson = (candidate) => {
5
2
  if (!candidate || typeof candidate !== 'string') {
6
3
  return candidate;
7
4
  }
@@ -12,4 +9,3 @@ const safeJson = (candidate) => {
12
9
  }
13
10
  return json;
14
11
  };
15
- exports.safeJson = safeJson;
package/dist/routing.js CHANGED
@@ -1,43 +1,40 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createRouter = exports.wrapRouteExecution = exports.registerRoute = exports.matches = void 0;
4
- const node_stream_1 = require("node:stream");
5
- const mongodb_1 = require("mongodb");
6
- const types_1 = require("@aeriajs/types");
7
- const common_1 = require("@aeriajs/common");
8
- const validation_1 = require("@aeriajs/validation");
9
- const entrypoint_1 = require("@aeriajs/entrypoint");
10
- const payload_js_1 = require("./payload.js");
1
+ import { Stream } from 'node:stream';
2
+ import { ObjectId } from 'mongodb';
3
+ import { Result, ACError, HTTPStatus, REQUEST_METHODS, STREAMED_RESPONSE } from '@aeriajs/types';
4
+ import { pipe, isGranted, deepMerge, endpointError } from '@aeriajs/common';
5
+ import { validateWithRefs } from '@aeriajs/validation';
6
+ import { getConfig } from '@aeriajs/entrypoint';
7
+ import { safeJson } from './payload.js';
11
8
  const checkUnprocessable = async (what, schema, context, validateOptions = {}) => {
12
9
  let result;
13
10
  if (Array.isArray(schema)) {
14
11
  for (const property of schema) {
15
- result = await (0, validation_1.validateWithRefs)(what, property, validateOptions);
12
+ result = await validateWithRefs(what, property, validateOptions);
16
13
  if (!result.error) {
17
14
  break;
18
15
  }
19
16
  }
20
17
  }
21
18
  else {
22
- result = await (0, validation_1.validateWithRefs)(what, schema, validateOptions);
19
+ result = await validateWithRefs(what, schema, validateOptions);
23
20
  }
24
21
  const { error, result: validated } = result;
25
22
  if (error) {
26
23
  if ('code' in error) {
27
- return context.error(types_1.HTTPStatus.UnprocessableContent, {
24
+ return context.error(HTTPStatus.UnprocessableContent, {
28
25
  code: error.code,
29
26
  details: error.details,
30
27
  });
31
28
  }
32
- return context.error(types_1.HTTPStatus.UnprocessableContent, {
33
- code: types_1.ACError.MalformedInput,
29
+ return context.error(HTTPStatus.UnprocessableContent, {
30
+ code: ACError.MalformedInput,
34
31
  message: 'the provided payload is unprocessable',
35
32
  details: error,
36
33
  });
37
34
  }
38
- return types_1.Result.result(validated);
35
+ return Result.result(validated);
39
36
  };
40
- const matches = (req, method, exp, options = {}, config) => {
37
+ export const matches = (req, method, exp, options = {}, config) => {
41
38
  const base = config?.baseUrl && config.baseUrl !== '/'
42
39
  ? options.base
43
40
  ? `${config.baseUrl}${options.base}`
@@ -62,20 +59,19 @@ const matches = (req, method, exp, options = {}, config) => {
62
59
  };
63
60
  }
64
61
  };
65
- exports.matches = matches;
66
- const registerRoute = async (context, method, exp, cb, contract, options = {}) => {
67
- const config = await (0, entrypoint_1.getConfig)();
68
- const match = (0, exports.matches)(context.request, method, exp, options, config);
62
+ export const registerRoute = async (context, method, exp, cb, contract, options = {}) => {
63
+ const config = await getConfig();
64
+ const match = matches(context.request, method, exp, options, config);
69
65
  if (match) {
70
66
  if (context.request.headers['content-type'] === 'application/json') {
71
67
  try {
72
- context.request.payload = (0, common_1.deepMerge)((0, payload_js_1.safeJson)(context.request.body), context.request.payload, {
68
+ context.request.payload = deepMerge(safeJson(context.request.body), context.request.payload, {
73
69
  arrays: false,
74
70
  });
75
71
  }
76
72
  catch (err) {
77
- return context.error(types_1.HTTPStatus.UnprocessableContent, {
78
- code: types_1.ACError.MalformedInput,
73
+ return context.error(HTTPStatus.UnprocessableContent, {
74
+ code: ACError.MalformedInput,
79
75
  message: 'Invalid JSON',
80
76
  });
81
77
  }
@@ -83,13 +79,13 @@ const registerRoute = async (context, method, exp, cb, contract, options = {}) =
83
79
  Object.assign(context.request, match);
84
80
  if (contract) {
85
81
  if (contract.streamed) {
86
- context.response[types_1.STREAMED_RESPONSE] = true;
82
+ context.response[STREAMED_RESPONSE] = true;
87
83
  }
88
84
  if (contract.roles) {
89
- const granted = (0, common_1.isGranted)(contract.roles, context.token);
85
+ const granted = isGranted(contract.roles, context.token);
90
86
  if (!granted) {
91
- return context.error(types_1.HTTPStatus.Unauthorized, {
92
- code: types_1.ACError.AuthorizationError,
87
+ return context.error(HTTPStatus.Unauthorized, {
88
+ code: ACError.AuthorizationError,
93
89
  message: 'your roles dont grant access to this route',
94
90
  });
95
91
  }
@@ -99,10 +95,10 @@ const registerRoute = async (context, method, exp, cb, contract, options = {}) =
99
95
  checkObjectIds: true,
100
96
  coerceObjectIds: true,
101
97
  context,
102
- objectIdConstructor: mongodb_1.ObjectId,
98
+ objectIdConstructor: ObjectId,
103
99
  });
104
100
  if (error) {
105
- return types_1.Result.error(error);
101
+ return Result.error(error);
106
102
  }
107
103
  }
108
104
  if ('query' in contract && contract.query) {
@@ -110,10 +106,10 @@ const registerRoute = async (context, method, exp, cb, contract, options = {}) =
110
106
  checkObjectIds: true,
111
107
  coerce: true,
112
108
  context,
113
- objectIdConstructor: mongodb_1.ObjectId,
109
+ objectIdConstructor: ObjectId,
114
110
  });
115
111
  if (error) {
116
- return types_1.Result.error(error);
112
+ return Result.error(error);
117
113
  }
118
114
  context.request.query = validated;
119
115
  }
@@ -124,14 +120,13 @@ const registerRoute = async (context, method, exp, cb, contract, options = {}) =
124
120
  : result;
125
121
  }
126
122
  };
127
- exports.registerRoute = registerRoute;
128
- const wrapRouteExecution = async (response, cb) => {
123
+ export const wrapRouteExecution = async (response, cb) => {
129
124
  try {
130
125
  const result = await cb();
131
- if (response[types_1.STREAMED_RESPONSE] && !result) {
126
+ if (response[STREAMED_RESPONSE] && !result) {
132
127
  return;
133
128
  }
134
- if (result instanceof node_stream_1.Stream) {
129
+ if (result instanceof Stream) {
135
130
  try {
136
131
  result.pipe(response);
137
132
  }
@@ -141,7 +136,7 @@ const wrapRouteExecution = async (response, cb) => {
141
136
  }
142
137
  if (result === null) {
143
138
  if (!response.headersSent) {
144
- response.writeHead(types_1.HTTPStatus.NoContent);
139
+ response.writeHead(HTTPStatus.NoContent);
145
140
  }
146
141
  response.end(result);
147
142
  return;
@@ -154,19 +149,18 @@ const wrapRouteExecution = async (response, cb) => {
154
149
  catch (e) {
155
150
  console.trace(e);
156
151
  if (!response.headersSent) {
157
- response.writeHead(types_1.HTTPStatus.InternalServerError);
152
+ response.writeHead(HTTPStatus.InternalServerError);
158
153
  }
159
154
  if (!response.writableEnded) {
160
- return (0, common_1.endpointError)({
161
- httpStatus: types_1.HTTPStatus.InternalServerError,
162
- code: types_1.ACError.UnknownError,
155
+ return endpointError({
156
+ httpStatus: HTTPStatus.InternalServerError,
157
+ code: ACError.UnknownError,
163
158
  message: 'Internal server error',
164
159
  });
165
160
  }
166
161
  }
167
162
  };
168
- exports.wrapRouteExecution = wrapRouteExecution;
169
- const createRouter = (options = {}) => {
163
+ export const createRouter = (options = {}) => {
170
164
  const { exhaust } = options;
171
165
  const routes = [];
172
166
  const routesMeta = {};
@@ -176,7 +170,7 @@ const createRouter = (options = {}) => {
176
170
  ? method[0]
177
171
  : method] = contract || null;
178
172
  routes.push((_, context, groupOptions) => {
179
- return (0, exports.registerRoute)(context, method, exp, cb, contract, groupOptions || options);
173
+ return registerRoute(context, method, exp, cb, contract, groupOptions || options);
180
174
  });
181
175
  };
182
176
  const group = (exp, router, middleware) => {
@@ -185,14 +179,14 @@ const createRouter = (options = {}) => {
185
179
  routesMeta[`${exp}${route}`] = router.routesMeta[route];
186
180
  }
187
181
  routes.push(async (_, context, groupOptions) => {
188
- const config = await (0, entrypoint_1.getConfig)();
182
+ const config = await getConfig();
189
183
  const base = groupOptions
190
184
  ? groupOptions.base
191
185
  : options.base;
192
186
  newOptions.base = base && base !== '/'
193
187
  ? `${base}${exp}`
194
188
  : exp;
195
- const match = (0, exports.matches)(context.request, null, config.baseUrl === '/'
189
+ const match = matches(context.request, null, config.baseUrl === '/'
196
190
  ? new RegExp(`^${newOptions.base}/`)
197
191
  : new RegExp(`^${config.baseUrl}${newOptions.base}/`), newOptions);
198
192
  if (match) {
@@ -206,7 +200,7 @@ const createRouter = (options = {}) => {
206
200
  }
207
201
  });
208
202
  };
209
- const routerPipe = (0, common_1.pipe)(routes, {
203
+ const routerPipe = pipe(routes, {
210
204
  returnFirst: (value) => {
211
205
  if (value !== undefined) {
212
206
  return value;
@@ -223,8 +217,8 @@ const createRouter = (options = {}) => {
223
217
  context.response = response;
224
218
  const result = await routerPipe(undefined, context, options);
225
219
  if (exhaust && result === undefined) {
226
- return context.error(types_1.HTTPStatus.NotFound, {
227
- code: types_1.ACError.ResourceNotFound,
220
+ return context.error(HTTPStatus.NotFound, {
221
+ code: ACError.ResourceNotFound,
228
222
  message: 'Not found',
229
223
  });
230
224
  }
@@ -233,11 +227,10 @@ const createRouter = (options = {}) => {
233
227
  };
234
228
  return new Proxy(router, {
235
229
  get: (target, key) => {
236
- if (types_1.REQUEST_METHODS.includes(key)) {
230
+ if (REQUEST_METHODS.includes(key)) {
237
231
  return (...args) => target.route(key, ...args);
238
232
  }
239
233
  return target[key];
240
234
  },
241
235
  });
242
236
  };
243
- exports.createRouter = createRouter;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@aeriajs/http",
3
- "version": "0.0.193",
3
+ "type": "module",
4
+ "version": "0.0.194",
4
5
  "description": "## Installation",
5
6
  "main": "dist/index.js",
6
7
  "aeriaMain": "tests/fixtures/aeriaMain.js",
7
- "module": "dist/index.mjs",
8
8
  "types": "dist/index.d.ts",
9
9
  "publishConfig": {
10
10
  "access": "public"
@@ -15,8 +15,7 @@
15
15
  "exports": {
16
16
  ".": {
17
17
  "types": "./dist/index.d.ts",
18
- "import": "./dist/index.mjs",
19
- "require": "./dist/index.js"
18
+ "default": "./dist/index.js"
20
19
  }
21
20
  },
22
21
  "files": [
@@ -30,19 +29,16 @@
30
29
  "mongodb": "^6.17.0"
31
30
  },
32
31
  "peerDependencies": {
33
- "@aeriajs/common": "^0.0.157",
34
- "@aeriajs/entrypoint": "^0.0.163",
35
- "@aeriajs/types": "^0.0.135",
36
- "@aeriajs/validation": "^0.0.178",
32
+ "@aeriajs/common": "^0.0.158",
33
+ "@aeriajs/entrypoint": "^0.0.164",
34
+ "@aeriajs/types": "^0.0.136",
35
+ "@aeriajs/validation": "^0.0.179",
37
36
  "mongodb": "^6.17.0"
38
37
  },
39
38
  "scripts": {
40
39
  "test": "vitest run",
41
40
  "lint": "eslint .",
42
41
  "lint:fix": "eslint . --fix",
43
- "build": "pnpm build:cjs && pnpm build:esm",
44
- "build:cjs": "tsc",
45
- "build:esm": "esbuild './src/**/*.ts' --outdir=dist --out-extension:.js=.mjs && pnpm build:esm-transform",
46
- "build:esm-transform": "pnpm -w esm-transform $PWD/dist"
42
+ "build": "tsc"
47
43
  }
48
44
  }
package/dist/cors.mjs DELETED
@@ -1,23 +0,0 @@
1
- "use strict";
2
- export const cors = async (req, res, config) => {
3
- const {
4
- allowOrigin = [],
5
- allowMethods = [],
6
- allowHeaders = [],
7
- maxAge
8
- } = config;
9
- const headers = {
10
- "Access-Control-Allow-Origin": allowOrigin.join(","),
11
- "Access-Control-Allow-Methods": allowMethods.join(","),
12
- "Access-Control-Allow-Headers": allowHeaders.join(","),
13
- "Access-Control-Max-Age": maxAge
14
- };
15
- if (req.method === "OPTIONS") {
16
- res.writeHead(204, headers);
17
- res.end();
18
- return null;
19
- }
20
- Object.entries(headers).forEach(([key, value]) => {
21
- res.setHeader(key, value);
22
- });
23
- };
package/dist/index.mjs DELETED
@@ -1,5 +0,0 @@
1
- "use strict";
2
- export * from "./cors.mjs";
3
- export * from "./log.mjs";
4
- export * from "./routing.mjs";
5
- export * from "./payload.mjs";
package/dist/log.mjs DELETED
@@ -1,20 +0,0 @@
1
- "use strict";
2
- import { METHOD_COLORS } from "@aeriajs/types";
3
- import { styleText } from "node:util";
4
- export const logResponse = (response) => {
5
- const { statusCode, req: { method, url } } = response;
6
- if (!method) {
7
- return;
8
- }
9
- const statusColor = statusCode >= 400 && statusCode <= 599 ? "red" : "white";
10
- const methodColor = method in METHOD_COLORS ? METHOD_COLORS[method] : "white";
11
- const now = /* @__PURE__ */ new Date();
12
- let line = `[${styleText(statusColor, statusCode.toString())}] `;
13
- line += `[${now.toLocaleString()}] `;
14
- line += styleText([
15
- "bold",
16
- methodColor
17
- ], method) + " ";
18
- line += url;
19
- console.log(line);
20
- };
package/dist/payload.mjs DELETED
@@ -1,12 +0,0 @@
1
- "use strict";
2
- export const safeJson = (candidate) => {
3
- if (!candidate || typeof candidate !== "string") {
4
- return candidate;
5
- }
6
- const json = JSON.parse(candidate);
7
- if (json && typeof json === "object") {
8
- delete json.constructor;
9
- delete json.__proto__;
10
- }
11
- return json;
12
- };
package/dist/routing.mjs DELETED
@@ -1,233 +0,0 @@
1
- "use strict";
2
- import { Stream } from "node:stream";
3
- import { ObjectId } from "mongodb";
4
- import { Result, ACError, HTTPStatus, REQUEST_METHODS, STREAMED_RESPONSE } from "@aeriajs/types";
5
- import { pipe, isGranted, deepMerge, endpointError } from "@aeriajs/common";
6
- import { validateWithRefs } from "@aeriajs/validation";
7
- import { getConfig } from "@aeriajs/entrypoint";
8
- import { safeJson } from "./payload.mjs";
9
- const checkUnprocessable = async (what, schema, context, validateOptions = {}) => {
10
- let result;
11
- if (Array.isArray(schema)) {
12
- for (const property of schema) {
13
- result = await validateWithRefs(what, property, validateOptions);
14
- if (!result.error) {
15
- break;
16
- }
17
- }
18
- } else {
19
- result = await validateWithRefs(what, schema, validateOptions);
20
- }
21
- const { error, result: validated } = result;
22
- if (error) {
23
- if ("code" in error) {
24
- return context.error(HTTPStatus.UnprocessableContent, {
25
- code: error.code,
26
- details: error.details
27
- });
28
- }
29
- return context.error(HTTPStatus.UnprocessableContent, {
30
- code: ACError.MalformedInput,
31
- message: "the provided payload is unprocessable",
32
- details: error
33
- });
34
- }
35
- return Result.result(validated);
36
- };
37
- export const matches = (req, method, exp, options = {}, config) => {
38
- const base = config?.baseUrl && config.baseUrl !== "/" ? options.base ? `${config.baseUrl}${options.base}` : config.baseUrl : options.base ? options.base : "";
39
- if (method && method !== req.method) {
40
- if (!Array.isArray(method) || !method.includes(req.method)) {
41
- return;
42
- }
43
- }
44
- const regexp = exp instanceof RegExp ? exp : new RegExp(`^${base}${exp}$`);
45
- const url = new URL(`http://0.com${req.url}`).pathname;
46
- const expMatches = url.match(regexp);
47
- if (expMatches) {
48
- const fragments = expMatches.splice(1);
49
- return {
50
- fragments
51
- };
52
- }
53
- };
54
- export const registerRoute = async (context, method, exp, cb, contract, options = {}) => {
55
- const config = await getConfig();
56
- const match = matches(
57
- context.request,
58
- method,
59
- exp,
60
- options,
61
- config
62
- );
63
- if (match) {
64
- if (context.request.headers["content-type"] === "application/json") {
65
- try {
66
- context.request.payload = deepMerge(safeJson(context.request.body), context.request.payload, {
67
- arrays: false
68
- });
69
- } catch (err) {
70
- return context.error(HTTPStatus.UnprocessableContent, {
71
- code: ACError.MalformedInput,
72
- message: "Invalid JSON"
73
- });
74
- }
75
- }
76
- Object.assign(context.request, match);
77
- if (contract) {
78
- if (contract.streamed) {
79
- context.response[STREAMED_RESPONSE] = true;
80
- }
81
- if (contract.roles) {
82
- const granted = isGranted(contract.roles, context.token);
83
- if (!granted) {
84
- return context.error(HTTPStatus.Unauthorized, {
85
- code: ACError.AuthorizationError,
86
- message: "your roles dont grant access to this route"
87
- });
88
- }
89
- }
90
- if ("payload" in contract && contract.payload) {
91
- const { error } = await checkUnprocessable(context.request.payload, contract.payload, context, {
92
- checkObjectIds: true,
93
- coerceObjectIds: true,
94
- context,
95
- objectIdConstructor: ObjectId
96
- });
97
- if (error) {
98
- return Result.error(error);
99
- }
100
- }
101
- if ("query" in contract && contract.query) {
102
- const { error, result: validated } = await checkUnprocessable(context.request.query, contract.query, context, {
103
- checkObjectIds: true,
104
- coerce: true,
105
- context,
106
- objectIdConstructor: ObjectId
107
- });
108
- if (error) {
109
- return Result.error(error);
110
- }
111
- context.request.query = validated;
112
- }
113
- }
114
- const result = await cb(context);
115
- return result === void 0 ? null : result;
116
- }
117
- };
118
- export const wrapRouteExecution = async (response, cb) => {
119
- try {
120
- const result = await cb();
121
- if (response[STREAMED_RESPONSE] && !result) {
122
- return;
123
- }
124
- if (result instanceof Stream) {
125
- try {
126
- result.pipe(response);
127
- } catch (err) {
128
- }
129
- return;
130
- }
131
- if (result === null) {
132
- if (!response.headersSent) {
133
- response.writeHead(HTTPStatus.NoContent);
134
- }
135
- response.end(result);
136
- return;
137
- }
138
- if (!response.writableEnded) {
139
- response.end(result);
140
- }
141
- return result;
142
- } catch (e) {
143
- console.trace(e);
144
- if (!response.headersSent) {
145
- response.writeHead(HTTPStatus.InternalServerError);
146
- }
147
- if (!response.writableEnded) {
148
- return endpointError({
149
- httpStatus: HTTPStatus.InternalServerError,
150
- code: ACError.UnknownError,
151
- message: "Internal server error"
152
- });
153
- }
154
- }
155
- };
156
- export const createRouter = (options = {}) => {
157
- const { exhaust } = options;
158
- const routes = [];
159
- const routesMeta = {};
160
- const route = (method, exp, cb, contract) => {
161
- routesMeta[exp] ??= {};
162
- routesMeta[exp][Array.isArray(method) ? method[0] : method] = contract || null;
163
- routes.push((_, context, groupOptions) => {
164
- return registerRoute(
165
- context,
166
- method,
167
- exp,
168
- cb,
169
- contract,
170
- groupOptions || options
171
- );
172
- });
173
- };
174
- const group = (exp, router2, middleware) => {
175
- const newOptions = Object.assign({}, options);
176
- for (const route2 in router2.routesMeta) {
177
- routesMeta[`${exp}${route2}`] = router2.routesMeta[route2];
178
- }
179
- routes.push(async (_, context, groupOptions) => {
180
- const config = await getConfig();
181
- const base = groupOptions ? groupOptions.base : options.base;
182
- newOptions.base = base && base !== "/" ? `${base}${exp}` : exp;
183
- const match = matches(
184
- context.request,
185
- null,
186
- config.baseUrl === "/" ? new RegExp(`^${newOptions.base}/`) : new RegExp(`^${config.baseUrl}${newOptions.base}/`),
187
- newOptions
188
- );
189
- if (match) {
190
- if (middleware) {
191
- const result = await middleware(context);
192
- if (result) {
193
- return result;
194
- }
195
- }
196
- return router2.handle(context.request, context.response, context, newOptions);
197
- }
198
- });
199
- };
200
- const routerPipe = pipe(routes, {
201
- returnFirst: (value) => {
202
- if (value !== void 0) {
203
- return value;
204
- }
205
- }
206
- });
207
- const router = {
208
- route,
209
- routes,
210
- routesMeta,
211
- group,
212
- handle: async (request, response, context, options2) => {
213
- context.request = request;
214
- context.response = response;
215
- const result = await routerPipe(void 0, context, options2);
216
- if (exhaust && result === void 0) {
217
- return context.error(HTTPStatus.NotFound, {
218
- code: ACError.ResourceNotFound,
219
- message: "Not found"
220
- });
221
- }
222
- return result;
223
- }
224
- };
225
- return new Proxy(router, {
226
- get: (target, key) => {
227
- if (REQUEST_METHODS.includes(key)) {
228
- return (...args) => target.route(key, ...args);
229
- }
230
- return target[key];
231
- }
232
- });
233
- };