yedra 0.9.2 → 0.9.4
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/README.md +16 -50
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -5
- package/dist/lib.d.ts +27 -27
- package/dist/lib.js +29 -67
- package/dist/routing/app.d.ts +2 -2
- package/dist/routing/app.js +33 -50
- package/dist/routing/endpoint.d.ts +5 -5
- package/dist/routing/endpoint.js +50 -65
- package/dist/routing/env.d.ts +2 -2
- package/dist/routing/env.js +3 -7
- package/dist/routing/errors.js +7 -17
- package/dist/routing/http.d.ts +1 -1
- package/dist/routing/http.js +34 -53
- package/dist/routing/listen.d.ts +1 -1
- package/dist/routing/listen.js +20 -36
- package/dist/routing/log.js +1 -5
- package/dist/routing/path.js +1 -5
- package/dist/routing/route.d.ts +8 -7
- package/dist/routing/route.js +58 -70
- package/dist/routing/test.d.ts +2 -2
- package/dist/routing/test.js +52 -64
- package/dist/validation/array.d.ts +3 -3
- package/dist/validation/array.js +12 -16
- package/dist/validation/body.js +1 -5
- package/dist/validation/boolean.d.ts +1 -1
- package/dist/validation/boolean.js +6 -10
- package/dist/validation/date.d.ts +1 -1
- package/dist/validation/date.js +8 -12
- package/dist/validation/doc.d.ts +1 -1
- package/dist/validation/doc.js +7 -7
- package/dist/validation/either.d.ts +1 -1
- package/dist/validation/either.js +7 -11
- package/dist/validation/enum.d.ts +1 -1
- package/dist/validation/enum.js +6 -10
- package/dist/validation/error.js +4 -9
- package/dist/validation/intersection.d.ts +2 -2
- package/dist/validation/intersection.js +8 -13
- package/dist/validation/modifiable.d.ts +2 -2
- package/dist/validation/modifiable.js +6 -10
- package/dist/validation/none.d.ts +1 -1
- package/dist/validation/none.js +3 -8
- package/dist/validation/number.d.ts +1 -1
- package/dist/validation/number.js +12 -16
- package/dist/validation/object.d.ts +3 -3
- package/dist/validation/object.js +14 -19
- package/dist/validation/raw.d.ts +1 -1
- package/dist/validation/raw.js +4 -8
- package/dist/validation/record.d.ts +3 -3
- package/dist/validation/record.js +8 -12
- package/dist/validation/schema.d.ts +1 -1
- package/dist/validation/schema.js +5 -9
- package/dist/validation/string.d.ts +1 -1
- package/dist/validation/string.js +11 -15
- package/dist/validation/undefined.d.ts +1 -1
- package/dist/validation/undefined.js +6 -11
- package/dist/validation/union.d.ts +2 -2
- package/dist/validation/union.js +6 -10
- package/dist/validation/unknown.d.ts +1 -1
- package/dist/validation/unknown.js +3 -7
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# yedra
|
|
2
2
|
|
|
3
3
|
## Table Of Contents
|
|
4
4
|
|
|
@@ -14,61 +14,22 @@
|
|
|
14
14
|
|
|
15
15
|
## Introduction
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
similar to Zod, and a simple route system similar to express.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Instead, it makes it easy to build well-documented software: y supports
|
|
23
|
-
automatic generation of OpenAPI documentation for all endpoints. This includes
|
|
24
|
-
generating JSON schemas for all request and response bodies that are specified
|
|
25
|
-
using y schemas.
|
|
17
|
+
yedra is a web framework for TypeScript. It includes a validation library
|
|
18
|
+
similar to Zod, and a simple route system similar to express. yedra's primary
|
|
19
|
+
goal is to make it easy to build well-documented software: it supports automatic
|
|
20
|
+
generation of OpenAPI documentation for all endpoints, and generating JSON
|
|
21
|
+
schemas for all request and response bodies that are specified using schemas.
|
|
26
22
|
|
|
27
23
|
## Getting Started
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
To create a yedra project, run:
|
|
30
26
|
|
|
31
27
|
```bash
|
|
32
|
-
|
|
33
|
-
yarn
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Then, create your first endpoint in `src/routes/up.ts`:
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
import { y } from "@wemakefuture/y";
|
|
41
|
-
|
|
42
|
-
export default y.endpoint("/up", {
|
|
43
|
-
summary: "Get server status.",
|
|
44
|
-
method: "GET",
|
|
45
|
-
query: y.object({}),
|
|
46
|
-
headers: y.object({}),
|
|
47
|
-
req: y.object({}),
|
|
48
|
-
res: y.object({ message: y.string() }),
|
|
49
|
-
do(req) {
|
|
50
|
-
return {
|
|
51
|
-
body: {
|
|
52
|
-
message: "Healthy.",
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
},
|
|
56
|
-
});
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
And add this to `src/index.ts`:
|
|
60
|
-
|
|
61
|
-
```ts
|
|
62
|
-
import { y } from "@wemakefuture/y";
|
|
63
|
-
|
|
64
|
-
y.app(`${__dirname}/routes`).then((app) => {
|
|
65
|
-
app.listen(3000);
|
|
66
|
-
});
|
|
28
|
+
bun create yedra@latest my-project
|
|
29
|
+
yarn create yedra@latest my-project
|
|
30
|
+
npm create yedra@latest my-project
|
|
67
31
|
```
|
|
68
32
|
|
|
69
|
-
This starts a server with all endpoints in `src/routes` and listens on
|
|
70
|
-
port 3000.
|
|
71
|
-
|
|
72
33
|
## Endpoints
|
|
73
34
|
|
|
74
35
|
The core construct of y is the `endpoint`. Endpoints are created like this:
|
|
@@ -292,7 +253,8 @@ y generally tries to follow a semantic versioning model. Right now, y is
|
|
|
292
253
|
pre-1.0, so breaking changes can occur on every minor release.
|
|
293
254
|
|
|
294
255
|
- 0.8.0 - Removed `identity` encoding, changed error field to `errorMessage`
|
|
295
|
-
- 0.7.3 - Changed `accept-encoding` for `y.Http` to `identity` to prevent memory
|
|
256
|
+
- 0.7.3 - Changed `accept-encoding` for `y.Http` to `identity` to prevent memory
|
|
257
|
+
leak
|
|
296
258
|
- 0.7.2 - Added time and connection count to connection log
|
|
297
259
|
- 0.7.1 - Made headers on test service methods optional
|
|
298
260
|
- 0.7.0 - Added test service and env parser
|
|
@@ -324,3 +286,7 @@ pre-1.0, so breaking changes can occur on every minor release.
|
|
|
324
286
|
- 0.1.2 - Fixed y.number() minimum and maximum checks
|
|
325
287
|
- 0.1.1 - Added test cases, documentation and license
|
|
326
288
|
- 0.1.0 - Initial release
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import * as y from './lib';
|
|
1
|
+
import * as y from './lib.js';
|
|
2
2
|
export { y };
|
package/dist/index.js
CHANGED
package/dist/lib.d.ts
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
export { type EndpointOptions, type EndpointRequest, type EndpointResponse, endpoint, } from './routing/endpoint';
|
|
2
|
-
export { HttpError, BadRequestError, UnauthorizedError, PaymentRequiredError, ForbiddenError, NotFoundError, ConflictError, } from './routing/errors';
|
|
3
|
-
export { type Context } from './routing/listen';
|
|
4
|
-
export { Log } from './routing/log';
|
|
5
|
-
export { type Endpoint, app } from './routing/app';
|
|
1
|
+
export { type EndpointOptions, type EndpointRequest, type EndpointResponse, endpoint, } from './routing/endpoint.js';
|
|
2
|
+
export { HttpError, BadRequestError, UnauthorizedError, PaymentRequiredError, ForbiddenError, NotFoundError, ConflictError, } from './routing/errors.js';
|
|
3
|
+
export { type Context } from './routing/listen.js';
|
|
4
|
+
export { Log } from './routing/log.js';
|
|
5
|
+
export { type Endpoint, app } from './routing/app.js';
|
|
6
6
|
export declare const validatePath: (path: string) => void;
|
|
7
|
-
export { TestService } from './routing/test';
|
|
8
|
-
export { parseEnv } from './routing/env';
|
|
9
|
-
export { route } from './routing/route';
|
|
10
|
-
export { array } from './validation/array';
|
|
11
|
-
export { boolean } from './validation/boolean';
|
|
12
|
-
export { date } from './validation/date';
|
|
13
|
-
export { _enum as enum } from './validation/enum';
|
|
14
|
-
export { ValidationError } from './validation/error';
|
|
15
|
-
export { intersection } from './validation/intersection';
|
|
16
|
-
export { number } from './validation/number';
|
|
17
|
-
export { object } from './validation/object';
|
|
18
|
-
export { record } from './validation/record';
|
|
19
|
-
export { Schema } from './validation/schema';
|
|
20
|
-
export { BodyType, type Typeof } from './validation/body';
|
|
21
|
-
export { raw } from './validation/raw';
|
|
22
|
-
export { none } from './validation/none';
|
|
23
|
-
export { either } from './validation/either';
|
|
24
|
-
export { HttpResponse, HttpRequestError, Http } from './routing/http';
|
|
25
|
-
export { string } from './validation/string';
|
|
26
|
-
export { _undefined as undefined } from './validation/undefined';
|
|
27
|
-
export { union } from './validation/union';
|
|
28
|
-
export { unknown } from './validation/unknown';
|
|
7
|
+
export { TestService } from './routing/test.js';
|
|
8
|
+
export { parseEnv } from './routing/env.js';
|
|
9
|
+
export { route } from './routing/route.js';
|
|
10
|
+
export { array } from './validation/array.js';
|
|
11
|
+
export { boolean } from './validation/boolean.js';
|
|
12
|
+
export { date } from './validation/date.js';
|
|
13
|
+
export { _enum as enum } from './validation/enum.js';
|
|
14
|
+
export { ValidationError } from './validation/error.js';
|
|
15
|
+
export { intersection } from './validation/intersection.js';
|
|
16
|
+
export { number } from './validation/number.js';
|
|
17
|
+
export { object } from './validation/object.js';
|
|
18
|
+
export { record } from './validation/record.js';
|
|
19
|
+
export { Schema } from './validation/schema.js';
|
|
20
|
+
export { BodyType, type Typeof } from './validation/body.js';
|
|
21
|
+
export { raw } from './validation/raw.js';
|
|
22
|
+
export { none } from './validation/none.js';
|
|
23
|
+
export { either } from './validation/either.js';
|
|
24
|
+
export { HttpResponse, HttpRequestError, Http } from './routing/http.js';
|
|
25
|
+
export { string } from './validation/string.js';
|
|
26
|
+
export { _undefined as undefined } from './validation/undefined.js';
|
|
27
|
+
export { union } from './validation/union.js';
|
|
28
|
+
export { unknown } from './validation/unknown.js';
|
package/dist/lib.js
CHANGED
|
@@ -1,70 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.unknown = exports.union = exports.undefined = exports.string = exports.Http = exports.HttpRequestError = exports.HttpResponse = exports.either = exports.none = exports.raw = exports.BodyType = exports.Schema = exports.record = exports.object = exports.number = exports.intersection = exports.ValidationError = exports.enum = exports.date = exports.boolean = exports.array = exports.route = exports.parseEnv = exports.TestService = exports.validatePath = exports.app = exports.Log = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.PaymentRequiredError = exports.UnauthorizedError = exports.BadRequestError = exports.HttpError = exports.endpoint = void 0;
|
|
4
|
-
const path_1 = require("./routing/path");
|
|
1
|
+
import { Path } from './routing/path.js';
|
|
5
2
|
// routing
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Object.defineProperty(exports, "PaymentRequiredError", { enumerable: true, get: function () { return errors_1.PaymentRequiredError; } });
|
|
13
|
-
Object.defineProperty(exports, "ForbiddenError", { enumerable: true, get: function () { return errors_1.ForbiddenError; } });
|
|
14
|
-
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return errors_1.NotFoundError; } });
|
|
15
|
-
Object.defineProperty(exports, "ConflictError", { enumerable: true, get: function () { return errors_1.ConflictError; } });
|
|
16
|
-
var log_1 = require("./routing/log");
|
|
17
|
-
Object.defineProperty(exports, "Log", { enumerable: true, get: function () { return log_1.Log; } });
|
|
18
|
-
var app_1 = require("./routing/app");
|
|
19
|
-
Object.defineProperty(exports, "app", { enumerable: true, get: function () { return app_1.app; } });
|
|
20
|
-
const validatePath = (path) => {
|
|
21
|
-
new path_1.Path(path);
|
|
3
|
+
export { endpoint, } from './routing/endpoint.js';
|
|
4
|
+
export { HttpError, BadRequestError, UnauthorizedError, PaymentRequiredError, ForbiddenError, NotFoundError, ConflictError, } from './routing/errors.js';
|
|
5
|
+
export { Log } from './routing/log.js';
|
|
6
|
+
export { app } from './routing/app.js';
|
|
7
|
+
export const validatePath = (path) => {
|
|
8
|
+
new Path(path);
|
|
22
9
|
};
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
var env_1 = require("./routing/env");
|
|
27
|
-
Object.defineProperty(exports, "parseEnv", { enumerable: true, get: function () { return env_1.parseEnv; } });
|
|
28
|
-
var route_1 = require("./routing/route");
|
|
29
|
-
Object.defineProperty(exports, "route", { enumerable: true, get: function () { return route_1.route; } });
|
|
10
|
+
export { TestService } from './routing/test.js';
|
|
11
|
+
export { parseEnv } from './routing/env.js';
|
|
12
|
+
export { route } from './routing/route.js';
|
|
30
13
|
// validation
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
Object.defineProperty(exports, "Schema", { enumerable: true, get: function () { return schema_1.Schema; } });
|
|
51
|
-
var body_1 = require("./validation/body");
|
|
52
|
-
Object.defineProperty(exports, "BodyType", { enumerable: true, get: function () { return body_1.BodyType; } });
|
|
53
|
-
var raw_1 = require("./validation/raw");
|
|
54
|
-
Object.defineProperty(exports, "raw", { enumerable: true, get: function () { return raw_1.raw; } });
|
|
55
|
-
var none_1 = require("./validation/none");
|
|
56
|
-
Object.defineProperty(exports, "none", { enumerable: true, get: function () { return none_1.none; } });
|
|
57
|
-
var either_1 = require("./validation/either");
|
|
58
|
-
Object.defineProperty(exports, "either", { enumerable: true, get: function () { return either_1.either; } });
|
|
59
|
-
var http_1 = require("./routing/http");
|
|
60
|
-
Object.defineProperty(exports, "HttpResponse", { enumerable: true, get: function () { return http_1.HttpResponse; } });
|
|
61
|
-
Object.defineProperty(exports, "HttpRequestError", { enumerable: true, get: function () { return http_1.HttpRequestError; } });
|
|
62
|
-
Object.defineProperty(exports, "Http", { enumerable: true, get: function () { return http_1.Http; } });
|
|
63
|
-
var string_1 = require("./validation/string");
|
|
64
|
-
Object.defineProperty(exports, "string", { enumerable: true, get: function () { return string_1.string; } });
|
|
65
|
-
var undefined_1 = require("./validation/undefined");
|
|
66
|
-
Object.defineProperty(exports, "undefined", { enumerable: true, get: function () { return undefined_1._undefined; } });
|
|
67
|
-
var union_1 = require("./validation/union");
|
|
68
|
-
Object.defineProperty(exports, "union", { enumerable: true, get: function () { return union_1.union; } });
|
|
69
|
-
var unknown_1 = require("./validation/unknown");
|
|
70
|
-
Object.defineProperty(exports, "unknown", { enumerable: true, get: function () { return unknown_1.unknown; } });
|
|
14
|
+
export { array } from './validation/array.js';
|
|
15
|
+
export { boolean } from './validation/boolean.js';
|
|
16
|
+
export { date } from './validation/date.js';
|
|
17
|
+
export { _enum as enum } from './validation/enum.js';
|
|
18
|
+
export { ValidationError } from './validation/error.js';
|
|
19
|
+
export { intersection } from './validation/intersection.js';
|
|
20
|
+
export { number } from './validation/number.js';
|
|
21
|
+
export { object } from './validation/object.js';
|
|
22
|
+
export { record } from './validation/record.js';
|
|
23
|
+
export { Schema } from './validation/schema.js';
|
|
24
|
+
export { BodyType } from './validation/body.js';
|
|
25
|
+
export { raw } from './validation/raw.js';
|
|
26
|
+
export { none } from './validation/none.js';
|
|
27
|
+
export { either } from './validation/either.js';
|
|
28
|
+
export { HttpResponse, HttpRequestError, Http } from './routing/http.js';
|
|
29
|
+
export { string } from './validation/string.js';
|
|
30
|
+
export { _undefined as undefined } from './validation/undefined.js';
|
|
31
|
+
export { union } from './validation/union.js';
|
|
32
|
+
export { unknown } from './validation/unknown.js';
|
package/dist/routing/app.d.ts
CHANGED
package/dist/routing/app.js
CHANGED
|
@@ -1,19 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.app = exports.App = void 0;
|
|
13
|
-
const glob_1 = require("glob");
|
|
14
|
-
const errors_1 = require("./errors");
|
|
15
|
-
const listen_1 = require("./listen");
|
|
16
|
-
class App {
|
|
1
|
+
import { glob } from 'glob';
|
|
2
|
+
import { HttpError } from './errors.js';
|
|
3
|
+
import { listen } from './listen.js';
|
|
4
|
+
export class App {
|
|
17
5
|
constructor(endpoints) {
|
|
18
6
|
this.endpoints = endpoints;
|
|
19
7
|
}
|
|
@@ -22,42 +10,39 @@ class App {
|
|
|
22
10
|
* @param req - The HTTP request.
|
|
23
11
|
* @returns The HTTP response.
|
|
24
12
|
*/
|
|
25
|
-
handle(req) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
return App.errorResponse(405, `Method '${req.method}' not allowed for path '${req.url}'.`);
|
|
37
|
-
}
|
|
38
|
-
return App.errorResponse(404, `Path '${req.url}' not found.`);
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
return yield match.result.endpoint.handle(req, match.result.params);
|
|
13
|
+
async handle(req) {
|
|
14
|
+
if (req.method !== 'GET' &&
|
|
15
|
+
req.method !== 'POST' &&
|
|
16
|
+
req.method !== 'PUT' &&
|
|
17
|
+
req.method !== 'DELETE') {
|
|
18
|
+
return App.errorResponse(405, `Method '${req.method}' not allowed.`);
|
|
19
|
+
}
|
|
20
|
+
const match = this.matchEndpoint(req.url, req.method);
|
|
21
|
+
if (!match.result) {
|
|
22
|
+
if (match.invalidMethod) {
|
|
23
|
+
return App.errorResponse(405, `Method '${req.method}' not allowed for path '${req.url}'.`);
|
|
42
24
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
25
|
+
return App.errorResponse(404, `Path '${req.url}' not found.`);
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return await match.result.endpoint.handle(req, match.result.params);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error instanceof HttpError) {
|
|
32
|
+
return App.errorResponse(error.status, error.message);
|
|
49
33
|
}
|
|
50
|
-
|
|
34
|
+
console.error(error);
|
|
35
|
+
return App.errorResponse(500, 'Internal Server Error.');
|
|
36
|
+
}
|
|
51
37
|
}
|
|
52
38
|
/**
|
|
53
39
|
* Generate OpenAPI documentation for the app.
|
|
54
40
|
*/
|
|
55
41
|
docs(options) {
|
|
56
|
-
var _a;
|
|
57
42
|
const paths = {};
|
|
58
43
|
for (const endpoint of this.endpoints) {
|
|
59
44
|
const path = endpoint.path.toString();
|
|
60
|
-
const methods =
|
|
45
|
+
const methods = paths[path] ?? {};
|
|
61
46
|
methods[endpoint.method.toLowerCase()] = endpoint.documentation();
|
|
62
47
|
paths[path] = methods;
|
|
63
48
|
}
|
|
@@ -69,7 +54,7 @@ class App {
|
|
|
69
54
|
};
|
|
70
55
|
}
|
|
71
56
|
listen(port) {
|
|
72
|
-
return
|
|
57
|
+
return listen(this, port);
|
|
73
58
|
}
|
|
74
59
|
static errorResponse(status, errorMessage) {
|
|
75
60
|
return {
|
|
@@ -96,7 +81,7 @@ class App {
|
|
|
96
81
|
continue;
|
|
97
82
|
}
|
|
98
83
|
const score = Object.keys(params).length;
|
|
99
|
-
const previous = result
|
|
84
|
+
const previous = result?.score;
|
|
100
85
|
if (previous === undefined || score < previous) {
|
|
101
86
|
// if there was no previous match or this one is better, use it
|
|
102
87
|
result = { endpoint, params, score };
|
|
@@ -105,7 +90,6 @@ class App {
|
|
|
105
90
|
return { invalidMethod, result };
|
|
106
91
|
}
|
|
107
92
|
}
|
|
108
|
-
exports.App = App;
|
|
109
93
|
const shouldIgnore = (path) => {
|
|
110
94
|
const extensions = [
|
|
111
95
|
'.test.ts',
|
|
@@ -123,18 +107,17 @@ const shouldIgnore = (path) => {
|
|
|
123
107
|
}
|
|
124
108
|
return false;
|
|
125
109
|
};
|
|
126
|
-
const app = (routes) =>
|
|
110
|
+
export const app = async (routes) => {
|
|
127
111
|
const endpoints = [];
|
|
128
|
-
const files =
|
|
112
|
+
const files = await glob([`${routes}/**/*.ts`, `${routes}/**/*.js`], {
|
|
129
113
|
absolute: true,
|
|
130
114
|
});
|
|
131
115
|
for (const file of files) {
|
|
132
116
|
if (shouldIgnore(file)) {
|
|
133
117
|
continue;
|
|
134
118
|
}
|
|
135
|
-
const endpoint =
|
|
119
|
+
const endpoint = await import(file);
|
|
136
120
|
endpoints.push(endpoint.default);
|
|
137
121
|
}
|
|
138
122
|
return new App(endpoints);
|
|
139
|
-
}
|
|
140
|
-
exports.app = app;
|
|
123
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { BodyType, Typeof } from '../validation/body';
|
|
2
|
-
import type { Schema } from '../validation/schema';
|
|
3
|
-
import type { Endpoint } from './app';
|
|
4
|
-
import { Http } from './http';
|
|
5
|
-
import { Log } from './log';
|
|
1
|
+
import type { BodyType, Typeof } from '../validation/body.js';
|
|
2
|
+
import type { Schema } from '../validation/schema.js';
|
|
3
|
+
import type { Endpoint } from './app.js';
|
|
4
|
+
import { Http } from './http.js';
|
|
5
|
+
import { Log } from './log.js';
|
|
6
6
|
export type EndpointRequest<Query, Headers, Req> = {
|
|
7
7
|
log: Log;
|
|
8
8
|
http: Http;
|
package/dist/routing/endpoint.js
CHANGED
|
@@ -1,78 +1,65 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.endpoint = void 0;
|
|
13
|
-
const types_1 = require("node:util/types");
|
|
14
|
-
const error_1 = require("../validation/error");
|
|
15
|
-
const errors_1 = require("./errors");
|
|
16
|
-
const http_1 = require("./http");
|
|
17
|
-
const log_1 = require("./log");
|
|
18
|
-
const path_1 = require("./path");
|
|
19
|
-
const endpoint = (path, options) => {
|
|
1
|
+
import { isUint8Array } from 'node:util/types';
|
|
2
|
+
import { ValidationError } from '../validation/error.js';
|
|
3
|
+
import { BadRequestError } from './errors.js';
|
|
4
|
+
import { Http } from './http.js';
|
|
5
|
+
import { Log } from './log.js';
|
|
6
|
+
import { Path } from './path.js';
|
|
7
|
+
export const endpoint = (path, options) => {
|
|
20
8
|
return {
|
|
21
9
|
method: options.method,
|
|
22
|
-
path: new
|
|
23
|
-
handle(req, params) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (error instanceof SyntaxError) {
|
|
36
|
-
throw new errors_1.BadRequestError(error.message);
|
|
37
|
-
}
|
|
38
|
-
if (error instanceof error_1.ValidationError) {
|
|
39
|
-
throw new errors_1.BadRequestError(error.format());
|
|
40
|
-
}
|
|
41
|
-
throw error;
|
|
10
|
+
path: new Path(path),
|
|
11
|
+
async handle(req, params) {
|
|
12
|
+
let body;
|
|
13
|
+
let query;
|
|
14
|
+
let headers;
|
|
15
|
+
try {
|
|
16
|
+
body = options.req.deserialize(req.body, req.headers['content-type'] ?? 'application/octet-stream');
|
|
17
|
+
query = options.query.parse(req.query);
|
|
18
|
+
headers = options.headers.parse(req.headers);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (error instanceof SyntaxError) {
|
|
22
|
+
throw new BadRequestError(error.message);
|
|
42
23
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const response = yield options.do({
|
|
46
|
-
log,
|
|
47
|
-
http,
|
|
48
|
-
url: req.url,
|
|
49
|
-
params,
|
|
50
|
-
query,
|
|
51
|
-
headers,
|
|
52
|
-
body,
|
|
53
|
-
});
|
|
54
|
-
if ((0, types_1.isUint8Array)(response.body)) {
|
|
55
|
-
return {
|
|
56
|
-
status: (_b = response.status) !== null && _b !== void 0 ? _b : 200,
|
|
57
|
-
body: response.body,
|
|
58
|
-
headers: (_c = response.headers) !== null && _c !== void 0 ? _c : {},
|
|
59
|
-
};
|
|
24
|
+
if (error instanceof ValidationError) {
|
|
25
|
+
throw new BadRequestError(error.format());
|
|
60
26
|
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
const log = new Log();
|
|
30
|
+
const http = new Http(log);
|
|
31
|
+
const response = await options.do({
|
|
32
|
+
log,
|
|
33
|
+
http,
|
|
34
|
+
url: req.url,
|
|
35
|
+
params,
|
|
36
|
+
query,
|
|
37
|
+
headers,
|
|
38
|
+
body,
|
|
39
|
+
});
|
|
40
|
+
if (isUint8Array(response.body)) {
|
|
61
41
|
return {
|
|
62
|
-
status:
|
|
63
|
-
body:
|
|
64
|
-
headers:
|
|
42
|
+
status: response.status ?? 200,
|
|
43
|
+
body: response.body,
|
|
44
|
+
headers: response.headers ?? {},
|
|
65
45
|
};
|
|
66
|
-
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
status: response.status ?? 200,
|
|
49
|
+
body: Buffer.from(JSON.stringify(response.body)),
|
|
50
|
+
headers: {
|
|
51
|
+
'content-type': 'application/json',
|
|
52
|
+
...response.headers,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
67
55
|
},
|
|
68
56
|
documentation() {
|
|
69
|
-
var _a;
|
|
70
57
|
const parameters = [
|
|
71
58
|
...paramDocs(options.query, 'query'),
|
|
72
59
|
...paramDocs(options.headers, 'header'),
|
|
73
60
|
];
|
|
74
61
|
return {
|
|
75
|
-
tags: [
|
|
62
|
+
tags: [options.category ?? path.split('/')[1]],
|
|
76
63
|
summary: options.summary,
|
|
77
64
|
description: options.description,
|
|
78
65
|
parameters,
|
|
@@ -108,9 +95,7 @@ const endpoint = (path, options) => {
|
|
|
108
95
|
},
|
|
109
96
|
};
|
|
110
97
|
};
|
|
111
|
-
exports.endpoint = endpoint;
|
|
112
98
|
const paramDocs = (params, position) => {
|
|
113
|
-
var _a;
|
|
114
99
|
const result = [];
|
|
115
100
|
const docs = params.documentation();
|
|
116
101
|
if (!('properties' in docs) || !Array.isArray(docs.properties)) {
|
|
@@ -123,7 +108,7 @@ const paramDocs = (params, position) => {
|
|
|
123
108
|
name: name,
|
|
124
109
|
in: position,
|
|
125
110
|
description: 'description' in property ? property.description : undefined,
|
|
126
|
-
required:
|
|
111
|
+
required: required.includes(name) ?? false,
|
|
127
112
|
schema: property,
|
|
128
113
|
});
|
|
129
114
|
}
|
package/dist/routing/env.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { Typeof } from '../validation/body';
|
|
2
|
-
import type { Schema } from '../validation/schema';
|
|
1
|
+
import type { Typeof } from '../validation/body.js';
|
|
2
|
+
import type { Schema } from '../validation/schema.js';
|
|
3
3
|
export declare const parseEnv: <T extends Schema<unknown>>(schema: T) => Typeof<T>;
|
package/dist/routing/env.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.parseEnv = void 0;
|
|
4
|
-
const error_1 = require("../validation/error");
|
|
5
|
-
const parseEnv = (schema) => {
|
|
1
|
+
import { ValidationError } from '../validation/error.js';
|
|
2
|
+
export const parseEnv = (schema) => {
|
|
6
3
|
try {
|
|
7
4
|
return schema.parse(process.env);
|
|
8
5
|
}
|
|
9
6
|
catch (error) {
|
|
10
|
-
if (error instanceof
|
|
7
|
+
if (error instanceof ValidationError) {
|
|
11
8
|
console.error(`error: env validation failed: ${error.format()}`);
|
|
12
9
|
}
|
|
13
10
|
process.exit(1);
|
|
14
11
|
}
|
|
15
12
|
};
|
|
16
|
-
exports.parseEnv = parseEnv;
|