@centralping/ergo 0.1.0-beta.3 → 0.1.0-beta.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/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/http/accepts.js +5 -5
- package/http/body.js +4 -1
- package/http/validate.js +9 -5
- package/lib/validate.js +14 -0
- package/package.json +2 -1
- package/types/http/main.d.ts +3 -1
- package/types/http/validate.d.ts +3 -1
- package/types/lib/validate.d.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.1.0-beta.4] - 2026-05-29
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- JSON Schema `format` keyword support via `ajv-formats`. Standard formats (`email`, `uri`,
|
|
12
|
+
`date-time`, `uuid`, etc.) are validated by default. Opt out with `formats: false` or select
|
|
13
|
+
specific formats with an array (e.g. `formats: ['email', 'uri']`). (#58)
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **BREAKING**: `accepts()` now defaults `throwIfFail` to `true`, enforcing 406 responses for unsatisfied content negotiation per the Fast Fail pipeline contract. Set `throwIfFail: false` to restore the previous informational-only behavior. (#55)
|
|
18
|
+
- `body()` default types now include `application/merge-patch+json` (RFC 7386) and `application/json-patch+json` (RFC 6902), resolving 415 rejections for valid PATCH content types that ergo-router's `strictPatch` allows. (#56)
|
|
19
|
+
- `validate()` params validation now checks `acc.route.params` (ergo-router convention) with fallback to `acc.params` (standalone), fixing silent no-op validation when used with ergo-router. (#57)
|
|
20
|
+
|
|
5
21
|
## [0.1.0-beta.1] - 2026-05-20
|
|
6
22
|
|
|
7
23
|
### Changed
|
package/README.md
CHANGED
package/http/accepts.js
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* `Accept-Charset`, and `Accept-Encoding` request headers and determine the best
|
|
6
6
|
* matching content type, language, charset, and encoding for the response.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* By default, returns `{response: {statusCode: 406, detail}}` for any header
|
|
9
|
+
* that cannot be satisfied, enforcing strict content negotiation in the Fast
|
|
10
|
+
* Fail pipeline. Set `throwIfFail: false` for informational-only negotiation.
|
|
11
11
|
*
|
|
12
12
|
* @module http/accepts
|
|
13
13
|
* @since 0.1.0
|
|
@@ -37,14 +37,14 @@ const headerMap = {
|
|
|
37
37
|
* Creates a content negotiation middleware.
|
|
38
38
|
*
|
|
39
39
|
* @param {object} [options] - Negotiation configuration
|
|
40
|
-
* @param {boolean} [options.throwIfFail=
|
|
40
|
+
* @param {boolean} [options.throwIfFail=true] - Return `{response: {statusCode: 406, detail}}` if any negotiation key is undefined
|
|
41
41
|
* @param {string[]} [options.types] - Acceptable media types
|
|
42
42
|
* @param {string[]} [options.languages] - Acceptable languages
|
|
43
43
|
* @param {string[]} [options.charsets] - Acceptable character sets
|
|
44
44
|
* @param {string[]} [options.encodings] - Acceptable content encodings
|
|
45
45
|
* @returns {function} - Middleware `(req) => {type, language, charset, encoding}` on success, or `{response: {statusCode: 406, detail: string}}` when `throwIfFail` is true and any negotiation value is undefined
|
|
46
46
|
*/
|
|
47
|
-
export default ({throwIfFail =
|
|
47
|
+
export default ({throwIfFail = true, ...options} = {}) => {
|
|
48
48
|
const acceptor = accepts(options);
|
|
49
49
|
|
|
50
50
|
return ({headers = {}} = {}) => {
|
package/http/body.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* @fileoverview HTTP middleware factory for request body parsing.
|
|
3
3
|
*
|
|
4
4
|
* Reads and parses the request body according to the declared `Content-Type`. Supports:
|
|
5
|
-
* - `application/json
|
|
5
|
+
* - `application/json`, `application/vnd.api+json`, `application/merge-patch+json`
|
|
6
|
+
* (RFC 7386), and `application/json-patch+json` (RFC 6902) — parsed via `JSON.parse`
|
|
6
7
|
* - `application/x-www-form-urlencoded` — parsed via the query string parser
|
|
7
8
|
* - `multipart/form-data` — parsed via the RFC 7578 streaming multipart parser
|
|
8
9
|
*
|
|
@@ -128,6 +129,8 @@ export default ({
|
|
|
128
129
|
types = [
|
|
129
130
|
'application/vnd.api+json',
|
|
130
131
|
'application/json',
|
|
132
|
+
'application/merge-patch+json',
|
|
133
|
+
'application/json-patch+json',
|
|
131
134
|
'application/x-www-form-urlencoded',
|
|
132
135
|
'multipart/form-data'
|
|
133
136
|
],
|
package/http/validate.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview HTTP middleware factory for JSON Schema validation.
|
|
3
3
|
*
|
|
4
|
-
* Validates properties from the accumulator (body, url, params) against provided
|
|
5
|
-
* Schemas using AJV. Schemas are compiled once at middleware creation time for
|
|
4
|
+
* Validates properties from the accumulator (body, url, route params) against provided
|
|
5
|
+
* JSON Schemas using AJV. Schemas are compiled once at middleware creation time for
|
|
6
|
+
* performance. Route params are resolved from `acc.route.params` (ergo-router) with
|
|
7
|
+
* fallback to `acc.params` (standalone).
|
|
6
8
|
*
|
|
7
9
|
* Returns `{response: {statusCode: 422, detail: ...}}` with structured error details on validation failure.
|
|
8
10
|
* Must be placed after `body()` and/or `url()` in the pipeline so accumulator values
|
|
@@ -39,8 +41,10 @@ import createValidator from '../lib/validate.js';
|
|
|
39
41
|
* @param {object} [schemas] - Schema map; each key corresponds to an accumulator property
|
|
40
42
|
* @param {object} [schemas.body] - JSON Schema for the parsed request body
|
|
41
43
|
* @param {object} [schemas.query] - JSON Schema for parsed query parameters
|
|
42
|
-
* @param {object} [schemas.params] - JSON Schema for route path parameters
|
|
44
|
+
* @param {object} [schemas.params] - JSON Schema for route path parameters (reads `acc.route.params` or `acc.params`)
|
|
43
45
|
* @param {object} [options] - AJV options forwarded to each compiled validator
|
|
46
|
+
* @param {boolean|Array<string>|object} [options.formats] - Format keyword support via
|
|
47
|
+
* `ajv-formats`; forwarded to `createValidator`. Defaults to all standard formats enabled
|
|
44
48
|
* @returns {function} - Ergo middleware `(req, res, acc) => void` that returns `{response: {statusCode: 422}}`
|
|
45
49
|
* (with `detail` and `details` from AJV) on validation failure
|
|
46
50
|
*/
|
|
@@ -67,8 +71,8 @@ export default (schemas = {}, options = {}) => {
|
|
|
67
71
|
validators.query(acc.url.query);
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
if (validators.params && acc.params) {
|
|
71
|
-
validators.params(acc.params);
|
|
74
|
+
if (validators.params && (acc.route?.params ?? acc.params)) {
|
|
75
|
+
validators.params(acc.route?.params ?? acc.params);
|
|
72
76
|
}
|
|
73
77
|
} catch (err) {
|
|
74
78
|
return {
|
package/lib/validate.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* @module lib/validate
|
|
11
11
|
* @since 0.1.0
|
|
12
12
|
* @requires ajv
|
|
13
|
+
* @requires ajv-formats
|
|
13
14
|
* @requires ../utils/http-errors.js
|
|
14
15
|
*
|
|
15
16
|
* @example
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
* validate({}); // throws 422 with details
|
|
26
27
|
*/
|
|
27
28
|
import Ajv from 'ajv';
|
|
29
|
+
import addFormats from 'ajv-formats';
|
|
28
30
|
import httpErrors from '../utils/http-errors.js';
|
|
29
31
|
|
|
30
32
|
/**
|
|
@@ -34,6 +36,11 @@ import httpErrors from '../utils/http-errors.js';
|
|
|
34
36
|
* @param {object} [options] - Validator options
|
|
35
37
|
* @param {boolean} [options.allErrors=true] - Report all errors instead of stopping at the first
|
|
36
38
|
* @param {boolean} [options.coerceTypes=false] - Coerce input values to match schema types
|
|
39
|
+
* @param {boolean|Array<string>|object} [options.formats] - Format keyword support via
|
|
40
|
+
* `ajv-formats`. `undefined` or `true` enables all standard formats; `false` disables (AJV
|
|
41
|
+
* strict mode rejects unknown formats); an array enables selective formats
|
|
42
|
+
* (e.g. `['email', 'uri']`); an object is passed as the full plugin config
|
|
43
|
+
* (e.g. `{mode: 'fast'}`)
|
|
37
44
|
* @param {object} [options.ajv] - Additional AJV constructor options
|
|
38
45
|
* @returns {function} - `validateData(data)` — returns `data` on success, throws 422 on failure
|
|
39
46
|
* @throws {Error} 422 with `details` array if schema validation fails
|
|
@@ -45,6 +52,13 @@ export default function createValidator(schema, options = {}) {
|
|
|
45
52
|
...options.ajv
|
|
46
53
|
});
|
|
47
54
|
|
|
55
|
+
if (options.formats !== false) {
|
|
56
|
+
addFormats(
|
|
57
|
+
ajv,
|
|
58
|
+
options.formats === true || options.formats === undefined ? undefined : options.formats
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
48
62
|
const validate = ajv.compile(schema);
|
|
49
63
|
|
|
50
64
|
return function validateData(data) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centralping/ergo",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.4",
|
|
4
4
|
"description": "A Fast Fail REST API toolkit for Node.js -- composable middleware with structured Negotiation, Authorization, Validation, and Execution stages.",
|
|
5
5
|
"main": "http/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -116,6 +116,7 @@
|
|
|
116
116
|
},
|
|
117
117
|
"dependencies": {
|
|
118
118
|
"ajv": "^8.20.0",
|
|
119
|
+
"ajv-formats": "^3.0.1",
|
|
119
120
|
"content-type": "^2.0.0",
|
|
120
121
|
"etag": "^1.8.1",
|
|
121
122
|
"negotiator": "^1.0.0"
|
package/types/http/main.d.ts
CHANGED
|
@@ -113,7 +113,9 @@ declare const _default: {
|
|
|
113
113
|
body?: object | undefined;
|
|
114
114
|
query?: object | undefined;
|
|
115
115
|
params?: object | undefined;
|
|
116
|
-
}, options?:
|
|
116
|
+
}, options?: {
|
|
117
|
+
formats?: boolean | object | string[] | undefined;
|
|
118
|
+
}) => Function;
|
|
117
119
|
};
|
|
118
120
|
export default _default;
|
|
119
121
|
import compose from '../utils/compose-with.js';
|
package/types/http/validate.d.ts
CHANGED
|
@@ -2,5 +2,7 @@ declare function _default(schemas?: {
|
|
|
2
2
|
body?: object | undefined;
|
|
3
3
|
query?: object | undefined;
|
|
4
4
|
params?: object | undefined;
|
|
5
|
-
}, options?:
|
|
5
|
+
}, options?: {
|
|
6
|
+
formats?: boolean | object | string[] | undefined;
|
|
7
|
+
}): Function;
|
|
6
8
|
export default _default;
|
package/types/lib/validate.d.ts
CHANGED
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
* @param {object} [options] - Validator options
|
|
6
6
|
* @param {boolean} [options.allErrors=true] - Report all errors instead of stopping at the first
|
|
7
7
|
* @param {boolean} [options.coerceTypes=false] - Coerce input values to match schema types
|
|
8
|
+
* @param {boolean|Array<string>|object} [options.formats] - Format keyword support via
|
|
9
|
+
* `ajv-formats`. `undefined` or `true` enables all standard formats; `false` disables (AJV
|
|
10
|
+
* strict mode rejects unknown formats); an array enables selective formats
|
|
11
|
+
* (e.g. `['email', 'uri']`); an object is passed as the full plugin config
|
|
12
|
+
* (e.g. `{mode: 'fast'}`)
|
|
8
13
|
* @param {object} [options.ajv] - Additional AJV constructor options
|
|
9
14
|
* @returns {function} - `validateData(data)` — returns `data` on success, throws 422 on failure
|
|
10
15
|
* @throws {Error} 422 with `details` array if schema validation fails
|
|
@@ -12,5 +17,6 @@
|
|
|
12
17
|
export default function createValidator(schema: object, options?: {
|
|
13
18
|
allErrors?: boolean | undefined;
|
|
14
19
|
coerceTypes?: boolean | undefined;
|
|
20
|
+
formats?: boolean | object | string[] | undefined;
|
|
15
21
|
ajv?: object | undefined;
|
|
16
22
|
}): Function;
|