@openaddresses/batch-schema 7.6.0 → 8.0.0
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 +8 -0
- package/README.md +2 -6
- package/lib/middleware.js +1 -0
- package/lib/openapi.js +96 -0
- package/lib/schema.js +2 -2
- package/package.json +7 -7
- package/routes/schema.js +18 -18
- package/test/schema.srv.test.js +5 -0
- package/test/schema.test.js +1 -1
- package/lib/docs.js +0 -36
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -4,12 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
```sh
|
|
8
|
-
yarn add @openaddresses/batch-schema
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
or
|
|
12
|
-
|
|
13
7
|
```sh
|
|
14
8
|
npm i @openaddresses/batch-schema
|
|
15
9
|
```
|
|
@@ -75,6 +69,8 @@ Adds a route called `GET /schema` which allows the caller to get a list of endpo
|
|
|
75
69
|
as well as full schema details for every route. If your API is public we recommend enabling this feature, however
|
|
76
70
|
if you do not wish for API routes to be published, this feature is disabled unless called.
|
|
77
71
|
|
|
72
|
+
Adds a route called `GET /openapi` which returns an OpenAPI / Swagger JSON Object
|
|
73
|
+
|
|
78
74
|
### schema.not_found
|
|
79
75
|
|
|
80
76
|
Adds a middlware which will catch all routes that have not been defined and return
|
package/lib/middleware.js
CHANGED
package/lib/openapi.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @class
|
|
3
|
+
*/
|
|
4
|
+
export default class Docs {
|
|
5
|
+
constructor(info) {
|
|
6
|
+
this.base = {
|
|
7
|
+
openapi: '3.0.3',
|
|
8
|
+
info: info || {
|
|
9
|
+
title: 'OpenAPI Schema',
|
|
10
|
+
version: '1.0.0'
|
|
11
|
+
},
|
|
12
|
+
paths: {}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
push(parsed, schemas) {
|
|
17
|
+
let path = [];
|
|
18
|
+
const method = parsed[0].toLowerCase();
|
|
19
|
+
|
|
20
|
+
for (let sec of parsed[1].split('/')) {
|
|
21
|
+
for (const lit of ['.', '-']) { // These chars are used literally and can't be part of a param name
|
|
22
|
+
const mini = [];
|
|
23
|
+
for (const s of sec.split(lit)) {
|
|
24
|
+
if (s[0] === ':') mini.push(`{${s}}`);
|
|
25
|
+
else mini.push(s);
|
|
26
|
+
}
|
|
27
|
+
sec = mini.join(lit);
|
|
28
|
+
}
|
|
29
|
+
path.push(sec);
|
|
30
|
+
}
|
|
31
|
+
path = path.join('/');
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if (!this.base.paths[path]) this.base.paths[path] = {};
|
|
35
|
+
|
|
36
|
+
if (this.base.paths[path][method]) throw new Error(`Duplicate Path: ${parsed.join(' ')}`);
|
|
37
|
+
|
|
38
|
+
const document = {
|
|
39
|
+
summary: schemas.description || 'No Description',
|
|
40
|
+
tags: [schemas.group || 'Default'],
|
|
41
|
+
parameters: [],
|
|
42
|
+
responses: {
|
|
43
|
+
200: {
|
|
44
|
+
description: 'Successful Response'
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
for (const key in schemas) {
|
|
50
|
+
if (key[0] === ':') {
|
|
51
|
+
document.parameters.push({
|
|
52
|
+
in: 'path',
|
|
53
|
+
name: key,
|
|
54
|
+
schema: {
|
|
55
|
+
type: schemas[key]
|
|
56
|
+
},
|
|
57
|
+
required: true
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (schemas.query && schemas.query.type === 'object') {
|
|
63
|
+
for (const name in (schemas.query.properties || {})) {
|
|
64
|
+
const query = schemas.query.properties[name];
|
|
65
|
+
document.parameters.push({
|
|
66
|
+
in: 'query',
|
|
67
|
+
name,
|
|
68
|
+
schema: query,
|
|
69
|
+
required: query.required || (schemas.query.required || []).includes(name),
|
|
70
|
+
description: query.description || 'No Description'
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (schemas.res) {
|
|
76
|
+
document.responses['200'].content = {
|
|
77
|
+
'application/json': {
|
|
78
|
+
schema: schemas.res
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (schemas.body) {
|
|
84
|
+
document.requestBody = {
|
|
85
|
+
required: true,
|
|
86
|
+
content: {
|
|
87
|
+
'application/json': {
|
|
88
|
+
schema: schemas.body
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.base.paths[path][method] = document;
|
|
95
|
+
}
|
|
96
|
+
}
|
package/lib/schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Validator } from 'express-json-validator-middleware';
|
|
2
|
-
import $RefParser from 'json-schema-ref-parser';
|
|
2
|
+
import $RefParser from '@apidevtools/json-schema-ref-parser';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import morgan from 'morgan';
|
|
@@ -7,7 +7,7 @@ import bodyparser from 'body-parser';
|
|
|
7
7
|
|
|
8
8
|
import SchemaRoute from '../routes/schema.js';
|
|
9
9
|
import Param from './param.js';
|
|
10
|
-
import Docs from './
|
|
10
|
+
import Docs from './openapi.js';
|
|
11
11
|
import Middleware from './middleware.js';
|
|
12
12
|
|
|
13
13
|
/**
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"type": "module",
|
|
4
4
|
"root": true,
|
|
5
5
|
"main": "index.js",
|
|
6
|
-
"version": "
|
|
6
|
+
"version": "8.0.0",
|
|
7
7
|
"description": "Strongly Validated JSON Schema support for address",
|
|
8
8
|
"repository": "git@github.com:openaddresses/batch-schema",
|
|
9
9
|
"author": "ingalls <nick@ingalls.ca>",
|
|
@@ -18,23 +18,23 @@
|
|
|
18
18
|
"doc": "documentation build index.js -f html -o docs && documentation lint index.js"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
+
"@apidevtools/json-schema-ref-parser": "^10.0.0",
|
|
21
22
|
"@openaddresses/batch-error": "^2.1.2",
|
|
22
23
|
"ajv": "^8.6.3",
|
|
23
24
|
"ajv-formats": "^2.1.1",
|
|
24
25
|
"body-parser": "^1.20.0",
|
|
25
26
|
"express": "^4.17.1",
|
|
26
27
|
"express-json-validator-middleware": "^3.0.0",
|
|
27
|
-
"glob": "^
|
|
28
|
-
"
|
|
29
|
-
"morgan": "^1.10.0",
|
|
30
|
-
"tape": "^5.3.1"
|
|
28
|
+
"glob": "^9.0.0",
|
|
29
|
+
"morgan": "^1.10.0"
|
|
31
30
|
},
|
|
32
31
|
"peerDependencies": {
|
|
33
32
|
"@openaddresses/batch-generic": "x.x.x"
|
|
34
33
|
},
|
|
35
34
|
"devDependencies": {
|
|
36
|
-
"documentation": "^
|
|
35
|
+
"documentation": "^14.0.1",
|
|
37
36
|
"eslint": "^8.0.1",
|
|
38
|
-
"eslint-plugin-node": "^11.0.0"
|
|
37
|
+
"eslint-plugin-node": "^11.0.0",
|
|
38
|
+
"tape": "^5.3.1"
|
|
39
39
|
}
|
|
40
40
|
}
|
package/routes/schema.js
CHANGED
|
@@ -1,26 +1,16 @@
|
|
|
1
1
|
import Err from '@openaddresses/batch-error';
|
|
2
2
|
|
|
3
3
|
export default async function router(schema) {
|
|
4
|
-
/**
|
|
5
|
-
* @api {get} /api/schema List Schemas
|
|
6
|
-
* @apiVersion 1.0.0
|
|
7
|
-
* @apiName ListSchemas
|
|
8
|
-
* @apiGroup Schemas
|
|
9
|
-
* @apiPermission public
|
|
10
|
-
*
|
|
11
|
-
* @apiDescription
|
|
12
|
-
* List all JSON Schemas in use
|
|
13
|
-
* With no parameters this API will return a list of all the endpoints that have a form of schema validation
|
|
14
|
-
* If the url/method params are used, the schemas themselves are returned
|
|
15
|
-
*
|
|
16
|
-
* Note: If url or method params are used, they must be used together
|
|
17
|
-
*
|
|
18
|
-
* @apiSchema (Query) {jsonschema=../schema/req.query.ListSchema.json} apiParam
|
|
19
|
-
* @apiSchema {jsonschema=../schema/res.ListSchema.json} apiSuccess
|
|
20
|
-
*/
|
|
21
4
|
await schema.get('/schema', {
|
|
22
5
|
query: 'req.query.ListSchema.json',
|
|
23
|
-
res: 'res.ListSchema.json'
|
|
6
|
+
res: 'res.ListSchema.json',
|
|
7
|
+
description: `
|
|
8
|
+
List all JSON Schemas in use
|
|
9
|
+
With no parameters this API will return a list of all the endpoints that have a form of schema validation
|
|
10
|
+
If the url/method params are used, the schemas themselves are returned
|
|
11
|
+
|
|
12
|
+
Note: If url or method params are used, they must be used together
|
|
13
|
+
`
|
|
24
14
|
}, async (req, res) => {
|
|
25
15
|
try {
|
|
26
16
|
if (req.query.url && req.query.method) {
|
|
@@ -34,4 +24,14 @@ export default async function router(schema) {
|
|
|
34
24
|
return Err.respond(err, res);
|
|
35
25
|
}
|
|
36
26
|
});
|
|
27
|
+
|
|
28
|
+
await schema.get('/openapi', {
|
|
29
|
+
description: 'Return a OpenAPI Schema for the API'
|
|
30
|
+
}, async (req, res) => {
|
|
31
|
+
try {
|
|
32
|
+
return res.json(schema.docs.base);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
return Err.respond(err, res);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
37
|
}
|
package/test/schema.srv.test.js
CHANGED
package/test/schema.test.js
CHANGED
package/lib/docs.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @class Docs
|
|
3
|
-
*/
|
|
4
|
-
export default class Docs extends Array {
|
|
5
|
-
push(parsed, schemas) {
|
|
6
|
-
const apiParams = [];
|
|
7
|
-
for (const key in schemas) {
|
|
8
|
-
if (key[0] === ':') {
|
|
9
|
-
apiParams.push(`* @apiParam {${schemas[key]}} ${key.slice(1)} param`);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
super.push(
|
|
14
|
-
`
|
|
15
|
-
/**
|
|
16
|
-
* @api {${parsed[0].toLowerCase()}} ${parsed[1]} ${schemas.name || parsed.join(' ')}
|
|
17
|
-
* @apiVersion ${schemas.version || '1.0.0'}
|
|
18
|
-
* @apiName ${parsed.join('-')}
|
|
19
|
-
* @apiGroup ${schemas.group || 'Default'}
|
|
20
|
-
* @apiPermission ${schemas.auth || 'Unknown'}
|
|
21
|
-
*
|
|
22
|
-
* @apidescription
|
|
23
|
-
* ${schemas.description || 'No Description'}
|
|
24
|
-
*
|
|
25
|
-
${apiParams.join('\n')}
|
|
26
|
-
*
|
|
27
|
-
* ${schemas.query_url ? `@apiSchema (Query) {jsonschema=${schemas.query_url}} apiParam` : ''}
|
|
28
|
-
* ${schemas.body_url ? `@apiSchema (Body) {jsonschema=${schemas.body_url}} apiParam` : ''}
|
|
29
|
-
* ${schemas.res_url ? `@apiSchema {jsonschema=${schemas.res_url}} apiSuccess` : ''}
|
|
30
|
-
*/
|
|
31
|
-
`.split('\n')
|
|
32
|
-
.map((l) => l.trim())
|
|
33
|
-
.join('\n')
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
}
|