@opentermsarchive/engine 3.0.0 → 4.0.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/config/ci.json +1 -3
- package/config/default.json +1 -3
- package/config/test.json +1 -3
- package/package.json +2 -1
- package/scripts/declarations/lint/index.mocha.js +2 -2
- package/scripts/declarations/validate/index.mocha.js +2 -2
- package/src/archivist/services/index.js +3 -3
- package/src/archivist/services/service.js +1 -1
- package/src/collection-api/routes/index.js +12 -2
- package/src/collection-api/routes/metadata.js +151 -0
- package/src/collection-api/routes/metadata.test.js +89 -0
- package/src/collection-api/routes/services.js +97 -99
- package/src/collection-api/server.js +1 -1
package/config/ci.json
CHANGED
package/config/default.json
CHANGED
package/config/test.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentermsarchive/engine",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Tracks and makes visible changes to the terms of online services",
|
|
5
5
|
"homepage": "https://opentermsarchive.org",
|
|
6
6
|
"bugs": {
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
"https-proxy-agent": "^5.0.0",
|
|
83
83
|
"iconv-lite": "^0.6.3",
|
|
84
84
|
"joplin-turndown-plugin-gfm": "^1.0.12",
|
|
85
|
+
"js-yaml": "^4.1.0",
|
|
85
86
|
"jsdom": "^18.1.0",
|
|
86
87
|
"json-source-map": "^0.6.1",
|
|
87
88
|
"lodash": "^4.17.21",
|
|
@@ -16,8 +16,8 @@ const ESLINT_CONFIG_PATH = path.join(ROOT_PATH, '.eslintrc.yaml');
|
|
|
16
16
|
const eslint = new ESLint({ overrideConfigFile: ESLINT_CONFIG_PATH, fix: false });
|
|
17
17
|
const eslintWithFix = new ESLint({ overrideConfigFile: ESLINT_CONFIG_PATH, fix: true });
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
const
|
|
19
|
+
const instancePath = path.resolve(process.cwd(), config.get('@opentermsarchive/engine.collectionPath'));
|
|
20
|
+
const declarationsPath = path.resolve(instancePath, services.DECLARATIONS_PATH);
|
|
21
21
|
|
|
22
22
|
export default async options => {
|
|
23
23
|
let servicesToValidate = options.services || [];
|
|
@@ -19,8 +19,8 @@ const fs = fsApi.promises;
|
|
|
19
19
|
const MIN_DOC_LENGTH = 100;
|
|
20
20
|
const SLOW_DOCUMENT_THRESHOLD = 10 * 1000; // number of milliseconds after which a document fetch is considered slow
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
const
|
|
22
|
+
const instancePath = path.resolve(process.cwd(), config.get('@opentermsarchive/engine.collectionPath'));
|
|
23
|
+
const declarationsPath = path.resolve(instancePath, services.DECLARATIONS_PATH);
|
|
24
24
|
|
|
25
25
|
export default async options => {
|
|
26
26
|
const schemaOnly = options.schemaOnly || false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { pathToFileURL } from 'url';
|
|
4
4
|
|
|
@@ -8,8 +8,8 @@ import Service from './service.js';
|
|
|
8
8
|
import SourceDocument from './sourceDocument.js';
|
|
9
9
|
import Terms from './terms.js';
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
const declarationsPath = path.resolve(process.cwd(), config.get('@opentermsarchive/engine.
|
|
11
|
+
export const DECLARATIONS_PATH = './declarations';
|
|
12
|
+
const declarationsPath = path.resolve(process.cwd(), config.get('@opentermsarchive/engine.collectionPath'), DECLARATIONS_PATH);
|
|
13
13
|
|
|
14
14
|
export async function load(servicesIdsToLoad = []) {
|
|
15
15
|
let servicesIds = await getDeclaredServicesIds();
|
|
@@ -70,6 +70,6 @@ export default class Service {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
static getNumberOfTerms(services, servicesIds, termsTypes) {
|
|
73
|
-
return servicesIds.reduce((acc, serviceId) => acc + services[serviceId].getNumberOfTerms(termsTypes), 0);
|
|
73
|
+
return (servicesIds || Object.keys(services)).reduce((acc, serviceId) => acc + services[serviceId].getNumberOfTerms(termsTypes), 0);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import config from 'config';
|
|
1
4
|
import express from 'express';
|
|
2
5
|
import helmet from 'helmet';
|
|
3
6
|
|
|
7
|
+
import * as Services from '../../archivist/services/index.js';
|
|
8
|
+
|
|
4
9
|
import docsRouter from './docs.js';
|
|
10
|
+
import metadataRouter from './metadata.js';
|
|
5
11
|
import servicesRouter from './services.js';
|
|
6
12
|
import versionsRouter from './versions.js';
|
|
7
13
|
|
|
8
|
-
export default function apiRouter(basePath) {
|
|
14
|
+
export default async function apiRouter(basePath) {
|
|
9
15
|
const router = express.Router();
|
|
10
16
|
|
|
11
17
|
const defaultDirectives = helmet.contentSecurityPolicy.getDefaultDirectives();
|
|
@@ -27,7 +33,11 @@ export default function apiRouter(basePath) {
|
|
|
27
33
|
res.json({ message: 'Welcome to an instance of the Open Terms Archive API. Documentation is available at /docs. Learn more on Open Terms Archive on https://opentermsarchive.org.' });
|
|
28
34
|
});
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
const collectionPath = path.resolve(process.cwd(), config.get('@opentermsarchive/engine.collectionPath'));
|
|
37
|
+
const services = await Services.load();
|
|
38
|
+
|
|
39
|
+
router.use(await metadataRouter(collectionPath, services));
|
|
40
|
+
router.use(servicesRouter(services));
|
|
31
41
|
router.use(versionsRouter);
|
|
32
42
|
|
|
33
43
|
return router;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
import express from 'express';
|
|
5
|
+
import yaml from 'js-yaml';
|
|
6
|
+
|
|
7
|
+
import Service from '../../archivist/services/service.js';
|
|
8
|
+
|
|
9
|
+
const METADATA_FILENAME = 'metadata.yml';
|
|
10
|
+
const PACKAGE_JSON_PATH = '../../../package.json';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @swagger
|
|
14
|
+
* tags:
|
|
15
|
+
* name: Metadata
|
|
16
|
+
* description: Collection metadata API
|
|
17
|
+
* components:
|
|
18
|
+
* schemas:
|
|
19
|
+
* Metadata:
|
|
20
|
+
* type: object
|
|
21
|
+
* description: Collection metadata
|
|
22
|
+
* properties:
|
|
23
|
+
* id:
|
|
24
|
+
* type: string
|
|
25
|
+
* description: Unique identifier of the collection
|
|
26
|
+
* name:
|
|
27
|
+
* type: string
|
|
28
|
+
* description: Display name of the collection
|
|
29
|
+
* tagline:
|
|
30
|
+
* type: string
|
|
31
|
+
* description: Short description of the collection
|
|
32
|
+
* description:
|
|
33
|
+
* type: string
|
|
34
|
+
* nullable: true
|
|
35
|
+
* description: Detailed description of the collection
|
|
36
|
+
* totalTerms:
|
|
37
|
+
* type: integer
|
|
38
|
+
* description: Total number of terms tracked in the collection
|
|
39
|
+
* totalServices:
|
|
40
|
+
* type: integer
|
|
41
|
+
* description: Total number of services tracked in the collection
|
|
42
|
+
* engineVersion:
|
|
43
|
+
* type: string
|
|
44
|
+
* description: Version of the Open Terms Archive engine in SemVer format (MAJOR.MINOR.PATCH)
|
|
45
|
+
* dataset:
|
|
46
|
+
* type: string
|
|
47
|
+
* format: uri
|
|
48
|
+
* description: URL to the dataset releases
|
|
49
|
+
* declarations:
|
|
50
|
+
* type: string
|
|
51
|
+
* format: uri
|
|
52
|
+
* description: URL to the declarations repository
|
|
53
|
+
* versions:
|
|
54
|
+
* type: string
|
|
55
|
+
* format: uri
|
|
56
|
+
* description: URL to the versions repository
|
|
57
|
+
* snapshots:
|
|
58
|
+
* type: string
|
|
59
|
+
* format: uri
|
|
60
|
+
* description: URL to the snapshots repository
|
|
61
|
+
* donations:
|
|
62
|
+
* type: string
|
|
63
|
+
* format: uri
|
|
64
|
+
* description: URL to the donations page
|
|
65
|
+
* logo:
|
|
66
|
+
* type: string
|
|
67
|
+
* format: uri
|
|
68
|
+
* nullable: true
|
|
69
|
+
* description: URL to the collection logo
|
|
70
|
+
* languages:
|
|
71
|
+
* type: array
|
|
72
|
+
* items:
|
|
73
|
+
* type: string
|
|
74
|
+
* description: List of ISO 639 language codes representing languages allowed by the collection
|
|
75
|
+
* jurisdictions:
|
|
76
|
+
* type: array
|
|
77
|
+
* items:
|
|
78
|
+
* type: string
|
|
79
|
+
* description: List of ISO 3166-2 country codes representing jurisdictions covered by the collection
|
|
80
|
+
* trackingPeriods:
|
|
81
|
+
* type: array
|
|
82
|
+
* items:
|
|
83
|
+
* type: object
|
|
84
|
+
* properties:
|
|
85
|
+
* startDate:
|
|
86
|
+
* type: string
|
|
87
|
+
* format: date
|
|
88
|
+
* description: The date when tracking started for this period
|
|
89
|
+
* schedule:
|
|
90
|
+
* type: string
|
|
91
|
+
* description: A cron expression defining when terms are tracked (e.g. "0 0 * * *" for daily at midnight)
|
|
92
|
+
* serverLocation:
|
|
93
|
+
* type: string
|
|
94
|
+
* description: The geographic location of the server used for tracking
|
|
95
|
+
* endDate:
|
|
96
|
+
* type: string
|
|
97
|
+
* format: date
|
|
98
|
+
* description: The date when tracking ended for this period
|
|
99
|
+
* governance:
|
|
100
|
+
* type: object
|
|
101
|
+
* additionalProperties:
|
|
102
|
+
* type: object
|
|
103
|
+
* properties:
|
|
104
|
+
* url:
|
|
105
|
+
* type: string
|
|
106
|
+
* format: uri
|
|
107
|
+
* description: URL to the entity's website
|
|
108
|
+
* logo:
|
|
109
|
+
* type: string
|
|
110
|
+
* format: uri
|
|
111
|
+
* description: URL to the entity's logo
|
|
112
|
+
* roles:
|
|
113
|
+
* type: array
|
|
114
|
+
* items:
|
|
115
|
+
* type: string
|
|
116
|
+
* enum: [host, administrator, curator, maintainer, sponsor]
|
|
117
|
+
* description: Roles of the entity within the governance
|
|
118
|
+
*/
|
|
119
|
+
export default async function metadataRouter(collectionPath, services) {
|
|
120
|
+
const router = express.Router();
|
|
121
|
+
|
|
122
|
+
const STATIC_METADATA = yaml.load(await fs.readFile(path.join(collectionPath, METADATA_FILENAME), 'utf8'));
|
|
123
|
+
const { version: engineVersion } = JSON.parse(await fs.readFile(new URL(PACKAGE_JSON_PATH, import.meta.url)));
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @swagger
|
|
127
|
+
* /metadata:
|
|
128
|
+
* get:
|
|
129
|
+
* summary: Get collection metadata
|
|
130
|
+
* tags: [Metadata]
|
|
131
|
+
* produces:
|
|
132
|
+
* - application/json
|
|
133
|
+
* responses:
|
|
134
|
+
* 200:
|
|
135
|
+
* description: Collection metadata
|
|
136
|
+
*/
|
|
137
|
+
router.get('/metadata', (req, res) => {
|
|
138
|
+
const dynamicMetadata = {
|
|
139
|
+
totalServices: Object.keys(services).length,
|
|
140
|
+
totalTerms: Service.getNumberOfTerms(services),
|
|
141
|
+
engineVersion,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
res.json({
|
|
145
|
+
...STATIC_METADATA,
|
|
146
|
+
...dynamicMetadata,
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
return router;
|
|
151
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import config from 'config';
|
|
5
|
+
import request from 'supertest';
|
|
6
|
+
|
|
7
|
+
import app from '../server.js';
|
|
8
|
+
|
|
9
|
+
const basePath = config.get('@opentermsarchive/engine.collection-api.basePath');
|
|
10
|
+
const { version: engineVersion } = JSON.parse(await fs.readFile(new URL('../../../package.json', import.meta.url)));
|
|
11
|
+
|
|
12
|
+
const EXPECTED_RESPONSE = {
|
|
13
|
+
totalServices: 7,
|
|
14
|
+
totalTerms: 8,
|
|
15
|
+
id: 'test',
|
|
16
|
+
name: 'test',
|
|
17
|
+
tagline: 'Test collection',
|
|
18
|
+
description: 'This is a test collection used for testing purposes.',
|
|
19
|
+
dataset: 'https://github.com/OpenTermsArchive/test-versions/releases',
|
|
20
|
+
declarations: 'https://github.com/OpenTermsArchive/test-declarations',
|
|
21
|
+
versions: 'https://github.com/OpenTermsArchive/test-versions',
|
|
22
|
+
snapshots: 'https://github.com/OpenTermsArchive/test-snapshots',
|
|
23
|
+
donations: null,
|
|
24
|
+
logo: 'https://opentermsarchive.org/images/logo/logo-open-terms-archive-black.png',
|
|
25
|
+
languages: [
|
|
26
|
+
'en',
|
|
27
|
+
],
|
|
28
|
+
jurisdictions: [
|
|
29
|
+
'EU',
|
|
30
|
+
],
|
|
31
|
+
governance: {
|
|
32
|
+
hosts: [
|
|
33
|
+
{ name: 'Localhost' },
|
|
34
|
+
],
|
|
35
|
+
administrators: [
|
|
36
|
+
{
|
|
37
|
+
name: 'Open Terms Archive',
|
|
38
|
+
url: 'https://opentermsarchive.org/',
|
|
39
|
+
logo: 'https://opentermsarchive.org/images/logo/logo-open-terms-archive-black.png',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
curators: [
|
|
43
|
+
{
|
|
44
|
+
name: 'Open Terms Archive',
|
|
45
|
+
url: 'https://opentermsarchive.org/',
|
|
46
|
+
logo: 'https://opentermsarchive.org/images/logo/logo-open-terms-archive-black.png',
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
maintainers: [
|
|
50
|
+
{
|
|
51
|
+
name: 'Open Terms Archive',
|
|
52
|
+
url: 'https://opentermsarchive.org/',
|
|
53
|
+
logo: 'https://opentermsarchive.org/images/logo/logo-open-terms-archive-black.png',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
sponsors: [
|
|
57
|
+
{
|
|
58
|
+
name: 'Open Terms Archive',
|
|
59
|
+
url: 'https://opentermsarchive.org/',
|
|
60
|
+
logo: 'https://opentermsarchive.org/images/logo/logo-open-terms-archive-black.png',
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
describe('Metadata API', () => {
|
|
67
|
+
describe('GET /metadata', () => {
|
|
68
|
+
let response;
|
|
69
|
+
|
|
70
|
+
before(async () => {
|
|
71
|
+
response = await request(app).get(`${basePath}/v1/metadata`);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('responds with 200 status code', () => {
|
|
75
|
+
expect(response.status).to.equal(200);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('responds with Content-Type application/json', () => {
|
|
79
|
+
expect(response.type).to.equal('application/json');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('returns expected metadata object', () => {
|
|
83
|
+
expect(response.body).to.deep.equal({
|
|
84
|
+
...EXPECTED_RESPONSE,
|
|
85
|
+
engineVersion,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
|
|
3
|
-
import * as Services from '../../archivist/services/index.js';
|
|
4
|
-
|
|
5
|
-
const services = await Services.load();
|
|
6
|
-
|
|
7
3
|
/**
|
|
8
4
|
* @swagger
|
|
9
5
|
* tags:
|
|
@@ -54,106 +50,108 @@ const services = await Services.load();
|
|
|
54
50
|
* items:
|
|
55
51
|
* type: string
|
|
56
52
|
*/
|
|
57
|
-
|
|
53
|
+
export default function servicesRouter(services) {
|
|
54
|
+
const router = express.Router();
|
|
58
55
|
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
router.get('/services', (req, res) => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
});
|
|
56
|
+
/**
|
|
57
|
+
* @swagger
|
|
58
|
+
* /services:
|
|
59
|
+
* get:
|
|
60
|
+
* summary: Enumerate all services.
|
|
61
|
+
* tags: [Services]
|
|
62
|
+
* produces:
|
|
63
|
+
* - application/json
|
|
64
|
+
* responses:
|
|
65
|
+
* 200:
|
|
66
|
+
* description: A JSON array of all services.
|
|
67
|
+
* content:
|
|
68
|
+
* application/json:
|
|
69
|
+
* schema:
|
|
70
|
+
* type: array
|
|
71
|
+
* items:
|
|
72
|
+
* type: object
|
|
73
|
+
* properties:
|
|
74
|
+
* id:
|
|
75
|
+
* type: string
|
|
76
|
+
* description: The ID of the service.
|
|
77
|
+
* name:
|
|
78
|
+
* type: string
|
|
79
|
+
* description: The name of the service.
|
|
80
|
+
* terms:
|
|
81
|
+
* type: array
|
|
82
|
+
* description: The declared terms types for this service.
|
|
83
|
+
* items:
|
|
84
|
+
* type: object
|
|
85
|
+
* properties:
|
|
86
|
+
* type:
|
|
87
|
+
* type: string
|
|
88
|
+
* description: The type of terms.
|
|
89
|
+
*/
|
|
90
|
+
router.get('/services', (req, res) => {
|
|
91
|
+
res.status(200).json(Object.values(services).map(service => ({
|
|
92
|
+
id: service.id,
|
|
93
|
+
name: service.name,
|
|
94
|
+
terms: service.getTermsTypes().map(type => ({ type })),
|
|
95
|
+
})));
|
|
96
|
+
});
|
|
100
97
|
|
|
101
|
-
/**
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
router.get('/service/:serviceId', (req, res) => {
|
|
134
|
-
|
|
135
|
-
|
|
98
|
+
/**
|
|
99
|
+
* @swagger
|
|
100
|
+
* /service/{serviceId}:
|
|
101
|
+
* get:
|
|
102
|
+
* summary: Retrieve the declaration of a specific service through its ID.
|
|
103
|
+
* tags: [Services]
|
|
104
|
+
* produces:
|
|
105
|
+
* - application/json
|
|
106
|
+
* parameters:
|
|
107
|
+
* - in: path
|
|
108
|
+
* name: serviceId
|
|
109
|
+
* description: The ID of the service.
|
|
110
|
+
* schema:
|
|
111
|
+
* type: string
|
|
112
|
+
* required: true
|
|
113
|
+
* examples:
|
|
114
|
+
* service-1:
|
|
115
|
+
* value: service-1
|
|
116
|
+
* summary: Simple service ID
|
|
117
|
+
* service-2:
|
|
118
|
+
* value: Service 2!
|
|
119
|
+
* summary: Service ID with spaces and special characters
|
|
120
|
+
* responses:
|
|
121
|
+
* 200:
|
|
122
|
+
* description: The full JSON declaration of the service with the given ID.
|
|
123
|
+
* content:
|
|
124
|
+
* application/json:
|
|
125
|
+
* schema:
|
|
126
|
+
* $ref: '#/components/schemas/Service'
|
|
127
|
+
* 404:
|
|
128
|
+
* description: No service matching the provided ID is found.
|
|
129
|
+
*/
|
|
130
|
+
router.get('/service/:serviceId', (req, res) => {
|
|
131
|
+
const matchedServiceID = Object.keys(services).find(key => key.toLowerCase() === req.params.serviceId?.toLowerCase());
|
|
132
|
+
const service = services[matchedServiceID];
|
|
136
133
|
|
|
137
|
-
|
|
138
|
-
|
|
134
|
+
if (!service) {
|
|
135
|
+
res.status(404).send('Service not found');
|
|
139
136
|
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
142
139
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
140
|
+
res.status(200).json({
|
|
141
|
+
id: service.id,
|
|
142
|
+
name: service.name,
|
|
143
|
+
terms: service.getTerms().map(terms => ({
|
|
144
|
+
type: terms.type,
|
|
145
|
+
sourceDocuments: terms.sourceDocuments.map(({ location, contentSelectors, insignificantContentSelectors, filters, executeClientScripts }) => ({
|
|
146
|
+
location,
|
|
147
|
+
contentSelectors,
|
|
148
|
+
insignificantContentSelectors,
|
|
149
|
+
executeClientScripts,
|
|
150
|
+
filters: filters?.map(filter => filter.name),
|
|
151
|
+
})),
|
|
154
152
|
})),
|
|
155
|
-
})
|
|
153
|
+
});
|
|
156
154
|
});
|
|
157
|
-
});
|
|
158
155
|
|
|
159
|
-
|
|
156
|
+
return router;
|
|
157
|
+
}
|
|
@@ -15,7 +15,7 @@ if (process.env.NODE_ENV !== 'test') {
|
|
|
15
15
|
|
|
16
16
|
const BASE_PATH = `/${config.get('@opentermsarchive/engine.collection-api.basePath')}/v1`.replace(/\/\/+/g, '/'); // ensure there are no double slashes
|
|
17
17
|
|
|
18
|
-
app.use(BASE_PATH, apiRouter(BASE_PATH));
|
|
18
|
+
app.use(BASE_PATH, await apiRouter(BASE_PATH));
|
|
19
19
|
app.use(errorsMiddleware);
|
|
20
20
|
|
|
21
21
|
const port = config.get('@opentermsarchive/engine.collection-api.port');
|