@bedrock/validation 7.0.0 → 7.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.cjs CHANGED
@@ -1,12 +1,15 @@
1
1
  module.exports = {
2
2
  root: true,
3
- parserOptions: {
4
- // this is required for dynamic import()
5
- ecmaVersion: 2020
6
- },
7
3
  env: {
8
4
  node: true
9
5
  },
10
- extends: ['digitalbazaar', 'digitalbazaar/jsdoc'],
11
- ignorePatterns: ['node_modules/']
6
+ extends: [
7
+ 'digitalbazaar',
8
+ 'digitalbazaar/jsdoc',
9
+ 'digitalbazaar/module'
10
+ ],
11
+ ignorePatterns: ['node_modules/'],
12
+ rules: {
13
+ 'unicorn/prefer-node-protocol': 'error'
14
+ }
12
15
  };
@@ -8,11 +8,11 @@ jobs:
8
8
  timeout-minutes: 10
9
9
  strategy:
10
10
  matrix:
11
- node-version: [18.x]
11
+ node-version: [22.x]
12
12
  steps:
13
- - uses: actions/checkout@v2
13
+ - uses: actions/checkout@v4
14
14
  - name: Use Node.js ${{ matrix.node-version }}
15
- uses: actions/setup-node@v1
15
+ uses: actions/setup-node@v4
16
16
  with:
17
17
  node-version: ${{ matrix.node-version }}
18
18
  - run: npm install
@@ -24,11 +24,11 @@ jobs:
24
24
  timeout-minutes: 10
25
25
  strategy:
26
26
  matrix:
27
- node-version: [14.x, 16.x, 18.x]
27
+ node-version: [18.x, 20.x, 22.x]
28
28
  steps:
29
- - uses: actions/checkout@v2
29
+ - uses: actions/checkout@v4
30
30
  - name: Use Node.js ${{ matrix.node-version }}
31
- uses: actions/setup-node@v1
31
+ uses: actions/setup-node@v4
32
32
  with:
33
33
  node-version: ${{ matrix.node-version }}
34
34
  - run: |
@@ -45,11 +45,11 @@ jobs:
45
45
  timeout-minutes: 10
46
46
  strategy:
47
47
  matrix:
48
- node-version: [18.x]
48
+ node-version: [22.x]
49
49
  steps:
50
- - uses: actions/checkout@v2
50
+ - uses: actions/checkout@v4
51
51
  - name: Use Node.js ${{ matrix.node-version }}
52
- uses: actions/setup-node@v1
52
+ uses: actions/setup-node@v4
53
53
  with:
54
54
  node-version: ${{ matrix.node-version }}
55
55
  - run: |
@@ -61,7 +61,8 @@ jobs:
61
61
  cd test
62
62
  npm run coverage-ci
63
63
  - name: Upload coverage to Codecov
64
- uses: codecov/codecov-action@v2
64
+ uses: codecov/codecov-action@v4
65
65
  with:
66
66
  file: ./test/coverage/lcov.info
67
67
  fail_ci_if_error: true
68
+ token: ${{ secrets.CODECOV_TOKEN }}
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # bedrock-validation ChangeLog
2
2
 
3
+ ## 7.1.1 - 2024-11-14
4
+
5
+ ### Changed
6
+ - Test and support Node.js 18, 20, 22.
7
+ - Update dependencies:
8
+ - `ajv@6.12.6`
9
+ - `klona@2.0.6`
10
+ - Update dev dependencies.
11
+ - Fix lint issues.
12
+
13
+ ### Fixed
14
+ - Errors now use the spelling `occurred` vs the typo `occured`.
15
+ - **NOTE**: This typo is known to be present in many tests of error message
16
+ and will require similar typo fixes.
17
+
18
+ ## 7.1.0 - 2022-10-16
19
+
20
+ ### Added
21
+ - Added a validator for `VerifiablePresentation`
22
+ - Added a validator for `VerifiableCredential`.
23
+
24
+ ### Changed
25
+ - The `credential` and `presentation` schemas are now deprecated and
26
+ will be removed in a future major release.
27
+
3
28
  ## 7.0.0 - 2022-04-28
4
29
 
5
30
  ### Changed
package/README.md CHANGED
@@ -18,7 +18,8 @@ npm install @bedrock/validation
18
18
 
19
19
  ```js
20
20
  import * as bedrock from '@bedrock/core';
21
- import {validate} from '@bedrock/validation';
21
+ import {postBarValidator, postBarQueryValidator} from '../schemas/my-schemas.js';
22
+ import {createValidateMiddleware as validate} from '@bedrock/validation';
22
23
 
23
24
  // load schemas from '/foo'
24
25
  bedrock.config.validation.schema.paths.push('/foo');
@@ -28,7 +29,7 @@ bedrock.events.on('bedrock-express.configure.routes', function(app) {
28
29
  app.post('/bar',
29
30
  // validate the query using the 'postBarQueryValidator'
30
31
  // validate the response body using the 'postBarValidator'
31
- validate({query: 'postBarQueryValidator', body: 'postBarValidator'}),
32
+ validate({querySchema: postBarQueryValidator, bodySchema: postBarValidator}),
32
33
  function(req, res) {
33
34
  // do something
34
35
  });
@@ -50,23 +51,12 @@ For more documentation on configuration, see [config.js](./lib/config.js).
50
51
 
51
52
  ## API
52
53
 
53
- ### validate(name, [data])
54
+ ### createValidateMiddleware({querySchema: schema, bodySchema: schema})
54
55
 
55
- This method may be called with either one or two parameters.
56
+ This method may be called with either `query` or `body` defined.
56
57
 
57
- If only one parameter is given:
58
-
59
- * The method returns express middleware that will be used to validate a request
60
- using the schema associated with the given name.
61
- * If a string is provided for the first parameter, then it will be used as the
62
- schema name for validating the request body.
63
- * If an object is provided for the first parameter, then the object can contain
64
- `body` and `query` schema names as properties of the object.
65
-
66
- If two parameters are given:
67
-
68
- * The first parameter must be a string and the second parameter must be the
69
- data to validate. The return value will contain the result of the validation.
58
+ The method returns express middleware that will be used to validate a request
59
+ using the schema associated with either `query` or `body`.
70
60
 
71
61
  ### getSchema(name)
72
62
 
package/lib/index.js CHANGED
@@ -241,8 +241,8 @@ function _createError({schema, instance}) {
241
241
  }
242
242
 
243
243
  const msg = schema.title ?
244
- 'A validation error occured in the \'' + schema.title + '\' validator.' :
245
- 'A validation error occured in an unnamed validator.';
244
+ 'A validation error occurred in the \'' + schema.title + '\' validator.' :
245
+ 'A validation error occurred in an unnamed validator.';
246
246
  const error = new BedrockError(
247
247
  msg, 'ValidationError', {public: true, errors, httpStatusCode: 400});
248
248
 
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@bedrock/validation",
3
- "version": "7.0.0",
3
+ "version": "7.1.1",
4
4
  "type": "module",
5
5
  "description": "Bedrock validation",
6
6
  "main": "./lib/index.js",
7
7
  "scripts": {
8
- "lint": "eslint ."
8
+ "lint": "eslint --ext .cjs,.js ."
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
@@ -24,19 +24,19 @@
24
24
  },
25
25
  "homepage": "https://github.com/digitalbazaar/bedrock-validation",
26
26
  "dependencies": {
27
- "ajv": "^6.12.0",
28
- "klona": "^2.0.5"
27
+ "ajv": "^6.12.6",
28
+ "klona": "^2.0.6"
29
29
  },
30
30
  "peerDependencies": {
31
- "@bedrock/core": "^6.0.0"
31
+ "@bedrock/core": "^6.2.0"
32
32
  },
33
33
  "directories": {
34
34
  "lib": "./lib"
35
35
  },
36
36
  "devDependencies": {
37
- "eslint": "^7.32.0",
38
- "eslint-config-digitalbazaar": "^2.8.0",
39
- "eslint-plugin-jsdoc": "^37.9.7",
40
- "jsdoc-to-markdown": "^7.1.1"
37
+ "eslint": "^8.57.1",
38
+ "eslint-config-digitalbazaar": "^5.2.0",
39
+ "eslint-plugin-jsdoc": "^50.5.0",
40
+ "eslint-plugin-unicorn": "^56.0.0"
41
41
  }
42
42
  }
@@ -0,0 +1,26 @@
1
+ /*!
2
+ * Copyright (c) 2012-2022 Digital Bazaar, Inc. All rights reserved.
3
+ */
4
+ import {extend as _extend} from '../../lib/helpers.js';
5
+ import identifier from '../identifier.js';
6
+ import {klona} from 'klona';
7
+
8
+ const schema = {
9
+ title: 'identifier or an object with an id',
10
+ anyOf: [
11
+ identifier(),
12
+ {
13
+ type: 'object',
14
+ additionalProperties: true,
15
+ properties: {id: identifier()},
16
+ required: ['id']
17
+ }
18
+ ]
19
+ };
20
+
21
+ export default function(extend) {
22
+ if(extend) {
23
+ return _extend(true, klona(schema), extend);
24
+ }
25
+ return schema;
26
+ }
@@ -0,0 +1,21 @@
1
+ /*!
2
+ * Copyright (c) 2012-2022 Digital Bazaar, Inc. All rights reserved.
3
+ */
4
+ import {extend as _extend} from '../lib/helpers.js';
5
+ import {klona} from 'klona';
6
+
7
+ // schema for a proof on a VerifiableCredential or Presentation
8
+ const schema = {
9
+ title: 'Proof',
10
+ anyOf: [
11
+ {type: 'object'},
12
+ {type: 'array', minItems: 1, items: {type: 'object'}}
13
+ ]
14
+ };
15
+
16
+ export default function(extend) {
17
+ if(extend) {
18
+ return _extend(true, klona(schema), extend);
19
+ }
20
+ return schema;
21
+ }
@@ -0,0 +1,67 @@
1
+ /*!
2
+ * Copyright (c) 2012-2022 Digital Bazaar, Inc. All rights reserved.
3
+ */
4
+ import {extend as _extend} from '../lib/helpers.js';
5
+ import idOrObjectWithId from './helpers/idOrObjectWithId.js';
6
+ import {klona} from 'klona';
7
+ import proof from './proof.js';
8
+ import w3cDateTime from './w3cDateTime.js';
9
+
10
+ // https://www.w3.org/TR/vc-data-model/
11
+ // Based off of the VC Data Model 1.1
12
+ const schema = {
13
+ type: 'object',
14
+ title: 'Verifiable Credential',
15
+ additionalProperties: true,
16
+ properties: {
17
+ '@context': {
18
+ type: 'array',
19
+ minItems: 1,
20
+ // the first context must be the VC context
21
+ items: [{
22
+ type: 'string',
23
+ const: 'https://www.w3.org/2018/credentials/v1'
24
+ }],
25
+ // additional contexts maybe strings or objects
26
+ additionalItems: {
27
+ anyOf: [{type: 'string'}, {type: 'object'}]
28
+ }
29
+ },
30
+ credentialSubject: {
31
+ anyOf: [
32
+ {type: 'object'},
33
+ {type: 'array', minItems: 1, items: {type: 'object'}}
34
+ ]
35
+ },
36
+ id: idOrObjectWithId(),
37
+ issuer: idOrObjectWithId(),
38
+ issuanceDate: w3cDateTime(),
39
+ proof: proof(),
40
+ type: {
41
+ type: 'array',
42
+ minItems: 1,
43
+ // this first type must be VerifiableCredential
44
+ items: [
45
+ {type: 'string', const: 'VerifiableCredential'},
46
+ ],
47
+ // additional types must be strings
48
+ additionalItems: {
49
+ type: 'string'
50
+ }
51
+ }
52
+ },
53
+ required: [
54
+ '@context',
55
+ 'credentialSubject',
56
+ 'issuer',
57
+ 'issuanceDate',
58
+ 'type'
59
+ ]
60
+ };
61
+
62
+ export default function(extend) {
63
+ if(extend) {
64
+ return _extend(true, klona(schema), extend);
65
+ }
66
+ return schema;
67
+ }
@@ -0,0 +1,58 @@
1
+ /*!
2
+ * Copyright (c) 2012-2022 Digital Bazaar, Inc. All rights reserved.
3
+ */
4
+ import {extend as _extend} from '../lib/helpers.js';
5
+ import idOrObjectWithId from './helpers/idOrObjectWithId.js';
6
+ import {klona} from 'klona';
7
+ import proof from './proof.js';
8
+ import verifiableCredential from './verifiableCredential.js';
9
+
10
+ const schema = {
11
+ title: 'Verifiable Presentation',
12
+ type: 'object',
13
+ additionalProperties: true,
14
+ properties: {
15
+ '@context': {
16
+ type: 'array',
17
+ minItems: 1,
18
+ // the first context must be the VC context
19
+ items: [{
20
+ type: 'string',
21
+ const: 'https://www.w3.org/2018/credentials/v1'
22
+ }],
23
+ // additional contexts maybe strings or objects
24
+ additionalItems: {
25
+ anyOf: [{type: 'string'}, {type: 'object'}]
26
+ }
27
+ },
28
+ id: idOrObjectWithId(),
29
+ type: {
30
+ type: 'array',
31
+ minItems: 1,
32
+ // this first type must be VerifiablePresentation
33
+ items: [
34
+ {type: 'string', const: 'VerifiablePresentation'},
35
+ ],
36
+ // additional types must be strings
37
+ additionalItems: {
38
+ type: 'string'
39
+ }
40
+ },
41
+ verifiableCredential: {
42
+ anyOf: [
43
+ verifiableCredential(),
44
+ {type: 'array', minItems: 1, items: verifiableCredential()}
45
+ ]
46
+ },
47
+ holder: idOrObjectWithId(),
48
+ proof: proof()
49
+ },
50
+ required: ['@context', 'type']
51
+ };
52
+
53
+ export default function(extend) {
54
+ if(extend) {
55
+ return _extend(true, klona(schema), extend);
56
+ }
57
+ return schema;
58
+ }
@@ -986,36 +986,49 @@ describe('bedrock-validation', function() {
986
986
  });
987
987
  });
988
988
 
989
- describe('credential', function() {
990
- const schema = validation.getSchema({name: 'credential'});
989
+ describe('verifiableCredential', function() {
990
+ const schema = validation.getSchema({name: 'verifiableCredential'});
991
991
  it('should be an Object', function() {
992
992
  schema.should.be.an.instanceof(Object);
993
993
  });
994
994
  it('should validate a credential', function() {
995
- const credential = {
996
- issuer: 'test',
997
- issued: '1997-07-16T19:20:30',
998
- claim: {
999
- id: '1234'
1000
- }
1001
- };
995
+ const credential = {...mock.credentials.valid};
1002
996
  const result = validateInstance({instance: credential, schema});
1003
997
  result.valid.should.be.true;
1004
998
  });
1005
999
  it('should validate a credential with an extend', function() {
1006
- const credential = {
1007
- issuer: 'test',
1008
- issued: '2016-01-01T01:00:00Z',
1009
- claim: {
1010
- id: '1234'
1011
- }
1012
- };
1000
+ const credential = {...mock.credentials.valid};
1013
1001
  const extend = {name: 'test'};
1014
- const schema = validation.schemas.credential(extend);
1002
+ const schema = validation.schemas.verifiableCredential(extend);
1015
1003
  const result = validateInstance({instance: credential, schema});
1016
1004
  schema.name.should.equal('test');
1017
1005
  result.valid.should.be.true;
1018
1006
  });
1007
+ it('should not validate a credential with an invalid @context', function() {
1008
+ const credential = {...mock.credentials.invalid.invalidContext};
1009
+ const result = validateInstance({instance: credential, schema});
1010
+ result.valid.should.be.false;
1011
+ });
1012
+ });
1013
+
1014
+ describe('verifiablePresentation', function() {
1015
+ const schema = validation.getSchema({name: 'verifiablePresentation'});
1016
+ it('should be an Object', function() {
1017
+ schema.should.be.an.instanceof(Object);
1018
+ });
1019
+ it('should validate a presentation', function() {
1020
+ const presentation = {...mock.presentations.valid};
1021
+ const result = validateInstance({instance: presentation, schema});
1022
+ result.valid.should.be.true;
1023
+ });
1024
+ it('should validate a presentation with an extend', function() {
1025
+ const presentation = {...mock.presentations.valid};
1026
+ const extend = {name: 'test'};
1027
+ const schema = validation.schemas.verifiablePresentation(extend);
1028
+ const result = validateInstance({instance: presentation, schema});
1029
+ schema.name.should.equal('test');
1030
+ result.valid.should.be.true;
1031
+ });
1019
1032
  });
1020
1033
 
1021
1034
  describe('jsonPatch', function() {
@@ -43,3 +43,33 @@ keys.alpha = {
43
43
  '42EADs/ajTEckTxULdirbEk2rINRwQC5kWMde3fcwAnn6xt3wvOyuwg=\n' +
44
44
  '-----END RSA PRIVATE KEY-----'
45
45
  };
46
+
47
+ const credentialsContext = 'https://www.w3.org/2018/credentials/v1';
48
+ const credentials = mock.credentials = {};
49
+
50
+ credentials.valid = {
51
+ '@context': [credentialsContext, 'https://www.schema.org'],
52
+ id: 'urn:uuid:test-vc',
53
+ issuer: 'test',
54
+ issuanceDate: '1997-07-16T19:20:30',
55
+ type: ['VerifiableCredential', 'TestCredential'],
56
+ credentialSubject: {
57
+ id: '1234'
58
+ }
59
+ };
60
+
61
+ credentials.invalid = {
62
+ invalidContext: {
63
+ ...credentials.valid,
64
+ '@context': ['https://www.schema.org']
65
+ }
66
+ };
67
+
68
+ const presentations = mock.presentations = {};
69
+
70
+ presentations.valid = {
71
+ '@context': [credentialsContext],
72
+ type: ['VerifiablePresentation'],
73
+ id: 'urn:uuid:test-vc',
74
+ verifiableCredential: [{...credentials.valid}]
75
+ };