@decohere/http 0.0.1-dev.129 → 0.0.1-dev.130
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/commonjs/src/auth/casl-authorization.service.js +2 -2
- package/commonjs/src/auth/token-service.js +5 -5
- package/commonjs/src/const.js +1 -2
- package/commonjs/src/health/health.controller.js +2 -2
- package/commonjs/src/openapi/request-schema.js +2 -2
- package/commonjs/src/openapi/request-validator.js +3 -3
- package/commonjs/src/providers/fastify.provider.js +2 -2
- package/commonjs/src/routing/decorators/argument.decorator.js +3 -3
- package/commonjs/src/routing/decorators/route.decorator.js +2 -2
- package/commonjs/src/routing/filters/exception-filter-host.js +3 -3
- package/commonjs/src/routing/index.js +1 -1
- package/commonjs/src/routing/middleware/http-access-log.middleware.js +2 -2
- package/commonjs/src/routing/pipes/pipes.js +8 -8
- package/commonjs/src/routing/services/route-registry.js +4 -4
- package/commonjs/src/routing/services/router.js +4 -4
- package/es6/src/auth/casl-authorization.service.js +1 -1
- package/es6/src/auth/token-service.js +1 -1
- package/es6/src/const.js +1 -2
- package/es6/src/health/health.controller.js +1 -1
- package/es6/src/openapi/request-schema.js +1 -1
- package/es6/src/openapi/request-validator.js +1 -1
- package/es6/src/providers/fastify.provider.js +1 -1
- package/es6/src/routing/decorators/argument.decorator.js +1 -1
- package/es6/src/routing/decorators/route.decorator.js +1 -1
- package/es6/src/routing/filters/exception-filter-host.js +1 -1
- package/es6/src/routing/index.js +1 -1
- package/es6/src/routing/middleware/http-access-log.middleware.js +1 -1
- package/es6/src/routing/pipes/pipes.js +1 -1
- package/es6/src/routing/services/route-registry.js +1 -1
- package/es6/src/routing/services/router.js +1 -1
- package/package.json +4 -4
- package/types/src/app/app.d.ts +1 -1
- package/types/src/auth/auth.types.d.ts +2 -2
- package/types/src/auth/casl-authorization.service.d.ts +1 -1
- package/types/src/auth/token-service.d.ts +1 -1
- package/types/src/http/http.extensions.d.ts +1 -1
- package/types/src/http/http.options.d.ts +1 -1
- package/types/src/openapi/index.d.ts +1 -1
- package/types/src/openapi/request-schema.d.ts +1 -1
- package/types/src/openapi/request-validator.d.ts +2 -2
- package/types/src/providers/fastify.provider.d.ts +1 -1
- package/types/src/routing/decorators/argument.decorator.d.ts +1 -1
- package/types/src/routing/decorators/controller.decorator.d.ts +1 -1
- package/types/src/routing/decorators/field.decorator.d.ts +1 -1
- package/types/src/routing/decorators/request.decorator.d.ts +1 -1
- package/types/src/routing/filters/exception-filter.d.ts +1 -1
- package/types/src/routing/index.d.ts +1 -1
- package/types/src/routing/middleware/middleware.d.ts +1 -1
- package/types/src/routing/services/route-argument-resolver.d.ts +1 -1
- package/types/src/routing/services/route-registry.d.ts +1 -1
- package/types/src/routing/services/router.d.ts +1 -1
- package/types/src/testing/boot-module.d.ts +1 -1
- /package/commonjs/src/routing/{anvil.types.js → http.types.js} +0 -0
- /package/es6/src/routing/{anvil.types.js → http.types.js} +0 -0
- /package/types/src/routing/{anvil.types.d.ts → http.types.d.ts} +0 -0
|
@@ -8,7 +8,7 @@ Object.defineProperty(exports, "CaslAuthorizationService", {
|
|
|
8
8
|
return CaslAuthorizationService;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
const
|
|
11
|
+
const _httptypes = require("../routing/http.types.js");
|
|
12
12
|
class CaslAuthorizationService {
|
|
13
13
|
factory;
|
|
14
14
|
tokenService;
|
|
@@ -30,7 +30,7 @@ class CaslAuthorizationService {
|
|
|
30
30
|
async authorize(principal, action, subject) {
|
|
31
31
|
const ability = this.factory(principal);
|
|
32
32
|
if (ability.cannot(action, subject)) {
|
|
33
|
-
throw new
|
|
33
|
+
throw new _httptypes.ForbiddenError(`Cannot perform "${action}" on "${subject}"`);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "TokenService", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _jose = require("jose");
|
|
12
|
-
const
|
|
12
|
+
const _httptypes = require("../routing/http.types.js");
|
|
13
13
|
const _ability = require("./ability.js");
|
|
14
14
|
const _authtypes = require("./auth.types.js");
|
|
15
15
|
const _safeoutboundurl = require("./safe-outbound-url.js");
|
|
@@ -31,15 +31,15 @@ class TokenService {
|
|
|
31
31
|
async verifyRequest(request) {
|
|
32
32
|
const authHeader = request.headers.authorization;
|
|
33
33
|
if (!authHeader) {
|
|
34
|
-
throw new
|
|
34
|
+
throw new _httptypes.UnauthorizedError("Missing Authorization header");
|
|
35
35
|
}
|
|
36
36
|
const spaceIdx = authHeader.indexOf(" ");
|
|
37
37
|
if (spaceIdx === -1) {
|
|
38
|
-
throw new
|
|
38
|
+
throw new _httptypes.UnauthorizedError("Malformed Authorization header");
|
|
39
39
|
}
|
|
40
40
|
const scheme = authHeader.slice(0, spaceIdx);
|
|
41
41
|
if (scheme !== "Bearer") {
|
|
42
|
-
throw new
|
|
42
|
+
throw new _httptypes.UnauthorizedError(`Unsupported authorization scheme: ${scheme}`);
|
|
43
43
|
}
|
|
44
44
|
const credentials = authHeader.slice(spaceIdx + 1);
|
|
45
45
|
return this.verify(credentials);
|
|
@@ -57,7 +57,7 @@ class TokenService {
|
|
|
57
57
|
});
|
|
58
58
|
return this.mapPrincipal(payload);
|
|
59
59
|
} catch (err) {
|
|
60
|
-
throw new
|
|
60
|
+
throw new _httptypes.UnauthorizedError(err instanceof Error ? err.message : "Token verification failed");
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
/**
|
package/commonjs/src/const.js
CHANGED
|
@@ -52,8 +52,7 @@ _export(exports, {
|
|
|
52
52
|
return TokenServiceToken;
|
|
53
53
|
}
|
|
54
54
|
});
|
|
55
|
-
const
|
|
56
|
-
const RoutingKey = `${Anvil}:Routing`;
|
|
55
|
+
const RoutingKey = "http:Routing";
|
|
57
56
|
const RouteRegistryToken = Symbol("RouteRegistryToken");
|
|
58
57
|
const HttpProviderToken = Symbol("HttpProviderToken");
|
|
59
58
|
const RouterToken = Symbol("RouterToken");
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "HealthController", {
|
|
|
10
10
|
});
|
|
11
11
|
const _decorators = require("@decohere/crucible/decorators");
|
|
12
12
|
const _const = require("../const.js");
|
|
13
|
-
const
|
|
13
|
+
const _httptypes = require("../routing/http.types.js");
|
|
14
14
|
const _index = require("../routing/index.js");
|
|
15
15
|
const _readinessservice = require("./readiness.service.js");
|
|
16
16
|
function _ts_decorate(decorators, target, key, desc) {
|
|
@@ -40,7 +40,7 @@ class HealthController {
|
|
|
40
40
|
async ready() {
|
|
41
41
|
const result = await this.readiness.checkAll();
|
|
42
42
|
if (!result.ok) {
|
|
43
|
-
throw new
|
|
43
|
+
throw new _httptypes.HttpError("Not ready", 503);
|
|
44
44
|
}
|
|
45
45
|
return {
|
|
46
46
|
status: "ok"
|
|
@@ -26,13 +26,13 @@ _export(exports, {
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
const _reflection = require("@decohere/core/reflection");
|
|
29
|
-
const
|
|
29
|
+
const _httptypes = require("../routing/http.types.js");
|
|
30
30
|
function buildRouteRequestSchemas(route) {
|
|
31
31
|
const queryParams = [];
|
|
32
32
|
const pathParams = [];
|
|
33
33
|
let bodySchema;
|
|
34
34
|
for (const routeArg of route.routeArgs ?? []){
|
|
35
|
-
if (routeArg.argumentLocation != null &&
|
|
35
|
+
if (routeArg.argumentLocation != null && _httptypes.InjectedParts.includes(routeArg.argumentLocation)) {
|
|
36
36
|
continue;
|
|
37
37
|
}
|
|
38
38
|
if ((0, _reflection.isPrimitiveOrDateType)(routeArg.argumentType)) {
|
|
@@ -10,14 +10,14 @@ function _export(target, all) {
|
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
12
|
get ValidationError () {
|
|
13
|
-
return
|
|
13
|
+
return _httptypes.ValidationError;
|
|
14
14
|
},
|
|
15
15
|
get validateRequest () {
|
|
16
16
|
return validateRequest;
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
19
|
const _ajv = require("ajv");
|
|
20
|
-
const
|
|
20
|
+
const _httptypes = require("../routing/http.types.js");
|
|
21
21
|
const _requestschema = require("./request-schema.js");
|
|
22
22
|
function validateRequest(route, request) {
|
|
23
23
|
const { params, body } = getValidators(route);
|
|
@@ -29,7 +29,7 @@ function validateRequest(route, request) {
|
|
|
29
29
|
collectIssues(body, request.body, "/body", issues);
|
|
30
30
|
}
|
|
31
31
|
if (issues.length > 0) {
|
|
32
|
-
throw new
|
|
32
|
+
throw new _httptypes.ValidationError("Validation failed", issues);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
const ajv = new _ajv.Ajv({
|
|
@@ -25,7 +25,7 @@ const _httpsecurity = require("../http/http.security.js");
|
|
|
25
25
|
const _httpcompression = require("../http/http.compression.js");
|
|
26
26
|
const _httpstatic = require("../http/http.static.js");
|
|
27
27
|
const _openapigenerator = require("../openapi/openapi.generator.js");
|
|
28
|
-
const
|
|
28
|
+
const _httptypes = require("../routing/http.types.js");
|
|
29
29
|
const _exceptionfilterhost = require("../routing/filters/exception-filter-host.js");
|
|
30
30
|
const _requestid = require("../routing/middleware/request-id.js");
|
|
31
31
|
const _pathutil = require("../routing/path.util.js");
|
|
@@ -365,7 +365,7 @@ class FastifyProvider {
|
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
367
|
const requestId = (0, _requestid.resolveRequestId)(headers, String(fastifyRequest.id ?? ""));
|
|
368
|
-
return new
|
|
368
|
+
return new _httptypes.HttpRequest({
|
|
369
369
|
requestId,
|
|
370
370
|
url,
|
|
371
371
|
method,
|
|
@@ -21,17 +21,17 @@ _export(exports, {
|
|
|
21
21
|
});
|
|
22
22
|
const _reflection = require("@decohere/core/reflection");
|
|
23
23
|
const _const = require("../../const.js");
|
|
24
|
-
const
|
|
24
|
+
const _httptypes = require("../http.types.js");
|
|
25
25
|
function Query(key) {
|
|
26
26
|
return Argument({
|
|
27
27
|
mappingKey: key,
|
|
28
|
-
argumentLocation:
|
|
28
|
+
argumentLocation: _httptypes.RequestParts.query
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
function Param(key) {
|
|
32
32
|
return Argument({
|
|
33
33
|
mappingKey: key,
|
|
34
|
-
argumentLocation:
|
|
34
|
+
argumentLocation: _httptypes.RequestParts.params
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
function Argument(options) {
|
|
@@ -30,7 +30,7 @@ _export(exports, {
|
|
|
30
30
|
});
|
|
31
31
|
const _reflection = require("@decohere/core/reflection");
|
|
32
32
|
const _const = require("../../const.js");
|
|
33
|
-
const
|
|
33
|
+
const _httptypes = require("../http.types.js");
|
|
34
34
|
function Get(path) {
|
|
35
35
|
return routeDecorator(_const.HTTPMethods.GET, path);
|
|
36
36
|
}
|
|
@@ -55,7 +55,7 @@ function Route(method, path) {
|
|
|
55
55
|
*/ function routeDecorator(method, path = "") {
|
|
56
56
|
return (targetClass, functionName, descriptor)=>{
|
|
57
57
|
if (path !== "" && !path.startsWith("/")) {
|
|
58
|
-
throw new
|
|
58
|
+
throw new _httptypes.RouteConfigurationError(`Error configuring routes. Path defined in controller ${targetClass.constructor.name}.${functionName}() should start '/'`);
|
|
59
59
|
}
|
|
60
60
|
const { value: handler } = descriptor;
|
|
61
61
|
const routeConfig = {
|
|
@@ -20,7 +20,7 @@ const _crucible = require("@decohere/crucible");
|
|
|
20
20
|
const _decorators = require("@decohere/crucible/decorators");
|
|
21
21
|
const _scribe = require("@decohere/scribe");
|
|
22
22
|
const _const = require("../../const.js");
|
|
23
|
-
const
|
|
23
|
+
const _httptypes = require("../http.types.js");
|
|
24
24
|
const _exceptionfilter = require("./exception-filter.js");
|
|
25
25
|
function _ts_decorate(decorators, target, key, desc) {
|
|
26
26
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -39,7 +39,7 @@ function _ts_param(paramIndex, decorator) {
|
|
|
39
39
|
class DefaultHttpExceptionFilter {
|
|
40
40
|
logger = _scribe.scribe.logger(DefaultHttpExceptionFilter.name);
|
|
41
41
|
catch(error, _ctx) {
|
|
42
|
-
if (error instanceof
|
|
42
|
+
if (error instanceof _httptypes.ValidationError) {
|
|
43
43
|
return {
|
|
44
44
|
status: 400,
|
|
45
45
|
body: {
|
|
@@ -50,7 +50,7 @@ class DefaultHttpExceptionFilter {
|
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
if (error instanceof
|
|
53
|
+
if (error instanceof _httptypes.HttpError) {
|
|
54
54
|
// Never expose internal auth failure details (header shape, issuer, etc.) to clients.
|
|
55
55
|
if (error.status === 401) {
|
|
56
56
|
this.logger.warn(error.message);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
_export_star(require("./
|
|
5
|
+
_export_star(require("./http.types.js"), exports);
|
|
6
6
|
_export_star(require("./decorators/index.js"), exports);
|
|
7
7
|
_export_star(require("./filters/exception-filter.js"), exports);
|
|
8
8
|
_export_star(require("./filters/exception-filter-host.js"), exports);
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "HttpAccessLogMiddleware", {
|
|
|
10
10
|
});
|
|
11
11
|
const _decorators = require("@decohere/crucible/decorators");
|
|
12
12
|
const _scribe = require("@decohere/scribe");
|
|
13
|
-
const
|
|
13
|
+
const _httptypes = require("../http.types.js");
|
|
14
14
|
const _requestid = require("./request-id.js");
|
|
15
15
|
function _ts_decorate(decorators, target, key, desc) {
|
|
16
16
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -27,7 +27,7 @@ class HttpAccessLogMiddleware {
|
|
|
27
27
|
try {
|
|
28
28
|
return await next();
|
|
29
29
|
} catch (error) {
|
|
30
|
-
status = error instanceof
|
|
30
|
+
status = error instanceof _httptypes.HttpError ? error.status : 500;
|
|
31
31
|
throw error;
|
|
32
32
|
} finally{
|
|
33
33
|
const durationMs = Math.round(performance.now() - start);
|
|
@@ -26,7 +26,7 @@ _export(exports, {
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
const _reflection = require("@decohere/core/reflection");
|
|
29
|
-
const
|
|
29
|
+
const _httptypes = require("../http.types.js");
|
|
30
30
|
const invalidBooleanIssue = {
|
|
31
31
|
path: "/value",
|
|
32
32
|
message: "Invalid boolean",
|
|
@@ -60,7 +60,7 @@ class BooleanPipe extends Pipe {
|
|
|
60
60
|
case 0:
|
|
61
61
|
return false;
|
|
62
62
|
default:
|
|
63
|
-
throw new
|
|
63
|
+
throw new _httptypes.ValidationError("Validation failed", [
|
|
64
64
|
invalidBooleanIssue
|
|
65
65
|
]);
|
|
66
66
|
}
|
|
@@ -70,7 +70,7 @@ class DatePipe extends Pipe {
|
|
|
70
70
|
transform(value, _context) {
|
|
71
71
|
if (value instanceof Date) {
|
|
72
72
|
if (Number.isNaN(value.getTime())) {
|
|
73
|
-
throw new
|
|
73
|
+
throw new _httptypes.ValidationError("Validation failed", [
|
|
74
74
|
invalidDateIssue
|
|
75
75
|
]);
|
|
76
76
|
}
|
|
@@ -79,7 +79,7 @@ class DatePipe extends Pipe {
|
|
|
79
79
|
if (typeof value === "string") {
|
|
80
80
|
const trimmed = value.trim();
|
|
81
81
|
if (trimmed === "") {
|
|
82
|
-
throw new
|
|
82
|
+
throw new _httptypes.ValidationError("Validation failed", [
|
|
83
83
|
invalidDateIssue
|
|
84
84
|
]);
|
|
85
85
|
}
|
|
@@ -88,7 +88,7 @@ class DatePipe extends Pipe {
|
|
|
88
88
|
}
|
|
89
89
|
const parsed = new Date(trimmed);
|
|
90
90
|
if (Number.isNaN(parsed.getTime())) {
|
|
91
|
-
throw new
|
|
91
|
+
throw new _httptypes.ValidationError("Validation failed", [
|
|
92
92
|
invalidDateIssue
|
|
93
93
|
]);
|
|
94
94
|
}
|
|
@@ -97,7 +97,7 @@ class DatePipe extends Pipe {
|
|
|
97
97
|
if (typeof value === "number" && !Number.isNaN(value)) {
|
|
98
98
|
return new Date(value);
|
|
99
99
|
}
|
|
100
|
-
throw new
|
|
100
|
+
throw new _httptypes.ValidationError("Validation failed", [
|
|
101
101
|
invalidDateIssue
|
|
102
102
|
]);
|
|
103
103
|
}
|
|
@@ -111,7 +111,7 @@ class JsonPipe extends Pipe {
|
|
|
111
111
|
});
|
|
112
112
|
return obj;
|
|
113
113
|
} catch (err) {
|
|
114
|
-
throw new
|
|
114
|
+
throw new _httptypes.TransformError(`Error parsing json ${err}`);
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
reviver(fieldTypes, fieldKey, value) {
|
|
@@ -136,7 +136,7 @@ class NumberPipe extends Pipe {
|
|
|
136
136
|
const text = typeof value === "number" ? null : String(value).trim();
|
|
137
137
|
const number = text == null ? value : text === "" ? Number.NaN : Number(text);
|
|
138
138
|
if (!Number.isFinite(number)) {
|
|
139
|
-
throw new
|
|
139
|
+
throw new _httptypes.ValidationError("Validation failed", [
|
|
140
140
|
invalidNumberIssue
|
|
141
141
|
]);
|
|
142
142
|
}
|
|
@@ -11,7 +11,7 @@ Object.defineProperty(exports, "RouteRegistry", {
|
|
|
11
11
|
const _decorators = require("@decohere/crucible/decorators");
|
|
12
12
|
const _reflection = require("@decohere/core/reflection");
|
|
13
13
|
const _const = require("../../const.js");
|
|
14
|
-
const
|
|
14
|
+
const _httptypes = require("../http.types.js");
|
|
15
15
|
const _pathutil = require("../path.util.js");
|
|
16
16
|
const _pipes = require("../pipes/pipes.js");
|
|
17
17
|
function _ts_decorate(decorators, target, key, desc) {
|
|
@@ -61,7 +61,7 @@ class RouteRegistry {
|
|
|
61
61
|
const existing = this.routeMap.get(key);
|
|
62
62
|
if (existing != null) {
|
|
63
63
|
// Last one used to win silently, leaving the other handler unreachable.
|
|
64
|
-
throw new
|
|
64
|
+
throw new _httptypes.RouteConfigurationError(`Duplicate route ${method.toUpperCase()} ${path}: ${existing.controller.name}.${existing.handler} and ${controller.name}.${handler}`);
|
|
65
65
|
}
|
|
66
66
|
const routeArgs = this.getRouteArguments(controller, func);
|
|
67
67
|
const httpCode = (0, _reflection.getMeta)(_const.MetadataKeys.httpCode, func);
|
|
@@ -134,7 +134,7 @@ class RouteRegistry {
|
|
|
134
134
|
const fieldKey = field.key;
|
|
135
135
|
const fieldMeta = fieldMap.get(field.key);
|
|
136
136
|
if (fieldMeta && fieldMeta.fieldLocation == null && argMeta?.argumentLocation == null) {
|
|
137
|
-
throw new
|
|
137
|
+
throw new _httptypes.RouteConfigurationError(`field ${fieldMeta.fieldKey} must specify a location because location was not specified for the route argument at idx ${argumentIndex}`);
|
|
138
138
|
}
|
|
139
139
|
const enriched = this.enrichField(field, fieldMeta, argMeta);
|
|
140
140
|
fieldMap.set(fieldKey, enriched);
|
|
@@ -190,5 +190,5 @@ RouteRegistry = _ts_decorate([
|
|
|
190
190
|
])
|
|
191
191
|
], RouteRegistry);
|
|
192
192
|
function isInjectedPart(location) {
|
|
193
|
-
return location != null &&
|
|
193
|
+
return location != null && _httptypes.InjectedParts.includes(location);
|
|
194
194
|
}
|
|
@@ -14,7 +14,7 @@ const _scribe = require("@decohere/scribe");
|
|
|
14
14
|
const _const = require("../../const.js");
|
|
15
15
|
const _requestvalidator = require("../../openapi/request-validator.js");
|
|
16
16
|
const _ssetypes = require("../../sse/sse.types.js");
|
|
17
|
-
const
|
|
17
|
+
const _httptypes = require("../http.types.js");
|
|
18
18
|
const _authdecorator = require("../decorators/auth.decorator.js");
|
|
19
19
|
const _middleware = require("../middleware/middleware.js");
|
|
20
20
|
const _routeargumentresolver = require("./route-argument-resolver.js");
|
|
@@ -58,13 +58,13 @@ class Router {
|
|
|
58
58
|
...this.routeRegistry.routes
|
|
59
59
|
].filter(({ controller, handler })=>(0, _authdecorator.getAuthorizeOptions)(controller.prototype, controller.prototype[handler])).map(({ controller, handler })=>`${controller.name}.${String(handler)}`);
|
|
60
60
|
if (protectedRoutes.length > 0) {
|
|
61
|
-
throw new
|
|
61
|
+
throw new _httptypes.RoutingError(`Routes use @Authorize but auth is not configured, so they would be open to anyone: ${protectedRoutes.join(", ")}. Add .withAuth() to the builder, or remove @Authorize.`);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
async route(routeKey, httpRequest) {
|
|
65
65
|
const routeConfig = this.routeRegistry.getRoute(routeKey);
|
|
66
66
|
if (!routeConfig) {
|
|
67
|
-
throw new
|
|
67
|
+
throw new _httptypes.RoutingError(`Route was not configured for key ${routeKey}`);
|
|
68
68
|
}
|
|
69
69
|
const { controller, handler, routeArgs } = routeConfig;
|
|
70
70
|
// Unnamed: the request id comes from the client, so it is not unique.
|
|
@@ -90,7 +90,7 @@ class Router {
|
|
|
90
90
|
return result;
|
|
91
91
|
}
|
|
92
92
|
if (typeof result?.[Symbol.asyncIterator] !== "function") {
|
|
93
|
-
throw new
|
|
93
|
+
throw new _httptypes.RoutingError(`${controller.name}.${String(handler)} is marked @Sse() so it must return an AsyncIterable (an async generator method works)`);
|
|
94
94
|
}
|
|
95
95
|
scopeHandedOff = true;
|
|
96
96
|
return new _ssetypes.SseResponse(result, ()=>scope[Symbol.asyncDispose]());
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRemoteJWKSet, importJWK, importSPKI, jwtVerify, SignJWT } from "jose";
|
|
2
|
-
import { UnauthorizedError } from "../routing/
|
|
2
|
+
import { UnauthorizedError } from "../routing/http.types.js";
|
|
3
3
|
import { createPrincipalFromPayload } from "./ability.js";
|
|
4
4
|
import { assertDevStaticAllowed, assertNonEmptyAudience, isDevStaticConfig, isDiscoveryConfig, isJwksConfig, isPublicKeyConfig, isSecretConfig } from "./auth.types.js";
|
|
5
5
|
import { assertSafeOutboundUrl } from "./safe-outbound-url.js";
|
package/es6/src/const.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
const RoutingKey = `${Anvil}:Routing`;
|
|
1
|
+
const RoutingKey = "http:Routing";
|
|
3
2
|
export const RouteRegistryToken = Symbol("RouteRegistryToken");
|
|
4
3
|
export const HttpProviderToken = Symbol("HttpProviderToken");
|
|
5
4
|
export const RouterToken = Symbol("RouterToken");
|
|
@@ -14,7 +14,7 @@ function _ts_param(paramIndex, decorator) {
|
|
|
14
14
|
}
|
|
15
15
|
import { inject, injectable } from "@decohere/crucible/decorators";
|
|
16
16
|
import { ReadinessServiceToken } from "../const.js";
|
|
17
|
-
import { HttpError } from "../routing/
|
|
17
|
+
import { HttpError } from "../routing/http.types.js";
|
|
18
18
|
import { AllowAnonymous, Controller, Get } from "../routing/index.js";
|
|
19
19
|
import { ReadinessService } from "./readiness.service.js";
|
|
20
20
|
export class HealthController {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isPrimitiveOrDateType } from "@decohere/core/reflection";
|
|
2
|
-
import { InjectedParts } from "../routing/
|
|
2
|
+
import { InjectedParts } from "../routing/http.types.js";
|
|
3
3
|
export function buildRouteRequestSchemas(route) {
|
|
4
4
|
const queryParams = [];
|
|
5
5
|
const pathParams = [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Ajv } from "ajv";
|
|
2
|
-
import { ValidationError } from "../routing/
|
|
2
|
+
import { ValidationError } from "../routing/http.types.js";
|
|
3
3
|
import { buildRouteRequestSchemas, pathParamsToSchema } from "./request-schema.js";
|
|
4
4
|
export { ValidationError };
|
|
5
5
|
/**
|
|
@@ -29,7 +29,7 @@ import { DEFAULT_HTTP_BODY_LIMIT, DEFAULT_HTTP_RATE_LIMIT } from "../http/http.s
|
|
|
29
29
|
import { DEFAULT_COMPRESSION_ENCODINGS, DEFAULT_COMPRESSION_THRESHOLD } from "../http/http.compression.js";
|
|
30
30
|
import { staticFiles } from "../http/http.static.js";
|
|
31
31
|
import { generateOpenApiDocument, resolveOpenApiPath } from "../openapi/openapi.generator.js";
|
|
32
|
-
import { HttpRequest } from "../routing/
|
|
32
|
+
import { HttpRequest } from "../routing/http.types.js";
|
|
33
33
|
import { DefaultHttpExceptionFilter } from "../routing/filters/exception-filter-host.js";
|
|
34
34
|
import { REQUEST_ID_HEADER, resolveRequestId } from "../routing/middleware/request-id.js";
|
|
35
35
|
import { normalizePrefix } from "../routing/path.util.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineArgumentMeta } from "@decohere/core/reflection";
|
|
2
2
|
import { MetadataKeys } from "../../const.js";
|
|
3
|
-
import { RequestParts } from "../
|
|
3
|
+
import { RequestParts } from "../http.types.js";
|
|
4
4
|
export function Query(key) {
|
|
5
5
|
return Argument({
|
|
6
6
|
mappingKey: key,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineMeta } from "@decohere/core/reflection";
|
|
2
2
|
import { HTTPMethods, MetadataKeys } from "../../const.js";
|
|
3
|
-
import { RouteConfigurationError } from "../
|
|
3
|
+
import { RouteConfigurationError } from "../http.types.js";
|
|
4
4
|
export function Get(path) {
|
|
5
5
|
return routeDecorator(HTTPMethods.GET, path);
|
|
6
6
|
}
|
|
@@ -16,7 +16,7 @@ import { LifetimeScopeToken } from "@decohere/crucible";
|
|
|
16
16
|
import { inject, injectable } from "@decohere/crucible/decorators";
|
|
17
17
|
import { scribe } from "@decohere/scribe";
|
|
18
18
|
import { HttpOptionsToken } from "../../const.js";
|
|
19
|
-
import { HttpError, ValidationError } from "../
|
|
19
|
+
import { HttpError, ValidationError } from "../http.types.js";
|
|
20
20
|
import { getCatchTypes } from "./exception-filter.js";
|
|
21
21
|
export class DefaultHttpExceptionFilter {
|
|
22
22
|
logger = scribe.logger(DefaultHttpExceptionFilter.name);
|
package/es6/src/routing/index.js
CHANGED
|
@@ -6,7 +6,7 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
6
6
|
}
|
|
7
7
|
import { injectable } from "@decohere/crucible/decorators";
|
|
8
8
|
import { scribe } from "@decohere/scribe";
|
|
9
|
-
import { HttpError } from "../
|
|
9
|
+
import { HttpError } from "../http.types.js";
|
|
10
10
|
import { REQUEST_ID_HEADER } from "./request-id.js";
|
|
11
11
|
export class HttpAccessLogMiddleware {
|
|
12
12
|
async use(ctx, next) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isDateType } from "@decohere/core/reflection";
|
|
2
|
-
import { TransformError, ValidationError } from "../
|
|
2
|
+
import { TransformError, ValidationError } from "../http.types.js";
|
|
3
3
|
const invalidBooleanIssue = {
|
|
4
4
|
path: "/value",
|
|
5
5
|
message: "Invalid boolean",
|
|
@@ -15,7 +15,7 @@ function _ts_param(paramIndex, decorator) {
|
|
|
15
15
|
import { inject, injectable } from "@decohere/crucible/decorators";
|
|
16
16
|
import { getArgumentMeta, getFields, getFunctionArgs, getFunctions, getMeta, isConstructable, isPrimitiveOrDateType } from "@decohere/core/reflection";
|
|
17
17
|
import { HttpOptionsToken, MetadataKeys } from "../../const.js";
|
|
18
|
-
import { InjectedParts, RouteConfigurationError } from "../
|
|
18
|
+
import { InjectedParts, RouteConfigurationError } from "../http.types.js";
|
|
19
19
|
import { applyGlobalPrefix, joinRoutePath, normalizePrefix } from "../path.util.js";
|
|
20
20
|
import { BooleanPipe, DatePipe, JsonPipe, NumberPipe } from "../pipes/pipes.js";
|
|
21
21
|
export class RouteRegistry {
|
|
@@ -18,7 +18,7 @@ import { scribe } from "@decohere/scribe";
|
|
|
18
18
|
import { AuthorizationServiceToken, HttpOptionsToken, IPrincipalProviderToken, RouteRegistryToken } from "../../const.js";
|
|
19
19
|
import { validateRequest } from "../../openapi/request-validator.js";
|
|
20
20
|
import { SseResponse } from "../../sse/sse.types.js";
|
|
21
|
-
import { RoutingError } from "../
|
|
21
|
+
import { RoutingError } from "../http.types.js";
|
|
22
22
|
import { getAuthorizeOptions, isAllowAnonymous } from "../decorators/auth.decorator.js";
|
|
23
23
|
import { composeMiddleware } from "../middleware/middleware.js";
|
|
24
24
|
import { RouteArgumentResolve } from "./route-argument-resolver.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decohere/http",
|
|
3
|
-
"version": "0.0.1-dev.
|
|
3
|
+
"version": "0.0.1-dev.130",
|
|
4
4
|
"description": "Web API and microservice platform built on Fastify with decorator-based routing",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@casl/ability": "^6.8.1",
|
|
59
|
-
"@decohere/core": "0.0.1-dev.
|
|
60
|
-
"@decohere/crucible": "0.0.1-dev.
|
|
61
|
-
"@decohere/scribe": "0.0.1-dev.
|
|
59
|
+
"@decohere/core": "0.0.1-dev.130",
|
|
60
|
+
"@decohere/crucible": "0.0.1-dev.130",
|
|
61
|
+
"@decohere/scribe": "0.0.1-dev.130",
|
|
62
62
|
"@fastify/compress": "^9.2.1",
|
|
63
63
|
"@fastify/cors": "^11.3.0",
|
|
64
64
|
"@fastify/helmet": "^13.1.0",
|
package/types/src/app/app.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type LifetimeScope } from "@decohere/crucible";
|
|
2
2
|
import { type IConfigurationService } from "@decohere/core/configuration";
|
|
3
3
|
import type { HostedServiceHost } from "../hosting/hosted-service-host.js";
|
|
4
|
-
import type { HttpProvider, StartResponse } from "../routing/
|
|
4
|
+
import type { HttpProvider, StartResponse } from "../routing/http.types.js";
|
|
5
5
|
export declare class ApiConfiguration {
|
|
6
6
|
port: number;
|
|
7
7
|
}
|
|
@@ -45,12 +45,12 @@ export type DiscoveryConfig = {
|
|
|
45
45
|
* Throw ForbiddenError to deny access.
|
|
46
46
|
*/
|
|
47
47
|
export interface IAuthorizationService {
|
|
48
|
-
authorizeRequest(request: import("../routing/
|
|
48
|
+
authorizeRequest(request: import("../routing/http.types.js").HttpRequest, action: string, subject: string): Promise<Principal>;
|
|
49
49
|
/**
|
|
50
50
|
* Verify the request has a valid principal without checking a CASL ability.
|
|
51
51
|
* Used when auth is enabled but the route has no `@Authorize` metadata.
|
|
52
52
|
*/
|
|
53
|
-
authenticateRequest(request: import("../routing/
|
|
53
|
+
authenticateRequest(request: import("../routing/http.types.js").HttpRequest): Promise<Principal>;
|
|
54
54
|
authorize(principal: Principal, action: string, subject: string): Promise<void>;
|
|
55
55
|
}
|
|
56
56
|
export type TokenServiceConfig = JwksConfig | PublicKeyConfig | SecretConfig | DevStaticConfig | DiscoveryConfig;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AnyAbility } from "@casl/ability";
|
|
2
|
-
import type { HttpRequest } from "../routing/
|
|
2
|
+
import type { HttpRequest } from "../routing/http.types.js";
|
|
3
3
|
import type { IAuthorizationService, Principal } from "./auth.types.js";
|
|
4
4
|
import type { TokenService } from "./token-service.js";
|
|
5
5
|
export type AbilityFactory = (principal: Principal) => AnyAbility;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type JWTPayload } from "jose";
|
|
2
|
-
import type { HttpRequest } from "../routing/
|
|
2
|
+
import type { HttpRequest } from "../routing/http.types.js";
|
|
3
3
|
import type { Principal, PrincipalMapper, TokenServiceConfig } from "./auth.types.js";
|
|
4
4
|
export declare class TokenService {
|
|
5
5
|
private readonly config;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Constructable } from "@decohere/core/reflection";
|
|
2
2
|
import { Builder } from "../builder/builder.js";
|
|
3
3
|
import type { OpenApiOptions } from "../openapi/openapi.types.js";
|
|
4
|
-
import type { CorsOptions, HttpProvider } from "../routing/
|
|
4
|
+
import type { CorsOptions, HttpProvider } from "../routing/http.types.js";
|
|
5
5
|
import type { ExceptionFilter } from "../routing/filters/exception-filter.js";
|
|
6
6
|
import type { Middleware } from "../routing/middleware/middleware.js";
|
|
7
7
|
import type { WithHttpOptions } from "./http.options.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Constructable } from "@decohere/core/reflection";
|
|
2
2
|
import type { OpenApiOptions } from "../openapi/openapi.types.js";
|
|
3
|
-
import type { CorsOptions } from "../routing/
|
|
3
|
+
import type { CorsOptions } from "../routing/http.types.js";
|
|
4
4
|
import type { ExceptionFilter } from "../routing/filters/exception-filter.js";
|
|
5
5
|
import type { Middleware } from "../routing/middleware/middleware.js";
|
|
6
6
|
import type { CompressionOptions } from "./http.compression.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { ValidationIssue } from "../routing/
|
|
1
|
+
export type { ValidationIssue } from "../routing/http.types.js";
|
|
2
2
|
export { generateOpenApiDocument, resolveOpenApiPath, toOpenApiPath, } from "./openapi.generator.js";
|
|
3
3
|
export type { JsonSchema, OpenApiDocument, OpenApiOperation, OpenApiOptions, OpenApiParameter, } from "./openapi.types.js";
|
|
4
4
|
export type { RouteRequestSchemas } from "./request-schema.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type MappedRoute, type RouteArg } from "../routing/
|
|
1
|
+
import { type MappedRoute, type RouteArg } from "../routing/http.types.js";
|
|
2
2
|
import type { JsonSchema, OpenApiParameter } from "./openapi.types.js";
|
|
3
3
|
/**
|
|
4
4
|
* Request shapes derived from route / `@Field` metadata (same source as OpenAPI).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { HttpRequest, MappedRoute, ValidationIssue } from "../routing/
|
|
2
|
-
import { ValidationError } from "../routing/
|
|
1
|
+
import type { HttpRequest, MappedRoute, ValidationIssue } from "../routing/http.types.js";
|
|
2
|
+
import { ValidationError } from "../routing/http.types.js";
|
|
3
3
|
export type { ValidationIssue };
|
|
4
4
|
export { ValidationError };
|
|
5
5
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type FastifyInstance } from "fastify";
|
|
2
2
|
import type { HttpOptions } from "../http/http.options.js";
|
|
3
|
-
import { type HttpProvider, type StartOptions, type StartResponse, type StopResponse } from "../routing/
|
|
3
|
+
import { type HttpProvider, type StartOptions, type StartResponse, type StopResponse } from "../routing/http.types.js";
|
|
4
4
|
import { type ExceptionFilterHost } from "../routing/filters/exception-filter-host.js";
|
|
5
5
|
import type { RouteRegistry } from "../routing/services/route-registry.js";
|
|
6
6
|
import type { Router } from "../routing/services/router.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Constructable } from "@decohere/core/reflection";
|
|
2
|
-
import { type RequestPart } from "../
|
|
2
|
+
import { type RequestPart } from "../http.types.js";
|
|
3
3
|
import type { Pipe } from "../pipes/pipes.js";
|
|
4
4
|
export type ArgumentOptions = {
|
|
5
5
|
mappingKey?: string;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Constructable } from "@decohere/core/reflection";
|
|
2
|
-
import type { ControllerMetadata } from "../
|
|
2
|
+
import type { ControllerMetadata } from "../http.types.js";
|
|
3
3
|
export declare function Controller(options?: ControllerMetadata): (target: Constructable) => void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { RequestPart } from "../
|
|
1
|
+
import type { RequestPart } from "../http.types.js";
|
|
2
2
|
export declare function Field(fieldLocation?: RequestPart, mappingKey?: string): (target: object, fieldName: string) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IPrincipalProvider } from "../../auth/principal-provider.js";
|
|
2
|
-
import type { HttpRequest, RouteArg } from "../
|
|
2
|
+
import type { HttpRequest, RouteArg } from "../http.types.js";
|
|
3
3
|
export declare class RouteArgumentResolve {
|
|
4
4
|
resolveArguments(httpRequest: HttpRequest, routeArgs: RouteArg[], principalProvider?: IPrincipalProvider): any[];
|
|
5
5
|
private getValue;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Constructable } from "@decohere/core/reflection";
|
|
2
2
|
import type { HttpOptions } from "../../http/http.options.js";
|
|
3
|
-
import type { MappedRoute } from "../
|
|
3
|
+
import type { MappedRoute } from "../http.types.js";
|
|
4
4
|
export declare class RouteRegistry {
|
|
5
5
|
private readonly routeMap;
|
|
6
6
|
private readonly httpOptions?;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type LifetimeScope } from "@decohere/crucible";
|
|
2
2
|
import type { IAuthorizationService } from "../../auth/auth.types.js";
|
|
3
3
|
import type { HttpOptions } from "../../http/http.options.js";
|
|
4
|
-
import type { HttpRequest } from "../
|
|
4
|
+
import type { HttpRequest } from "../http.types.js";
|
|
5
5
|
import { RouteRegistry } from "./route-registry.js";
|
|
6
6
|
export declare class Router {
|
|
7
7
|
private readonly argResolver;
|
|
@@ -3,7 +3,7 @@ import type { Constructable } from "@decohere/core/reflection";
|
|
|
3
3
|
import type { App } from "../app/app.js";
|
|
4
4
|
import { Builder } from "../builder/builder.js";
|
|
5
5
|
import "../http/http.extensions.js";
|
|
6
|
-
import type { HttpProvider } from "../routing/
|
|
6
|
+
import type { HttpProvider } from "../routing/http.types.js";
|
|
7
7
|
import { type EventStreamRead, type ReadEventsOptions } from "./sse-reader.js";
|
|
8
8
|
export type BootModuleOptions = {
|
|
9
9
|
controllers: Constructable[];
|
|
File without changes
|
|
File without changes
|
|
File without changes
|