@opentermsarchive/engine 4.2.0 → 5.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Open Terms Archive Engine
2
2
 
3
- This codebase is a Node.js module enabling downloading, archiving and publishing versions of documents obtained online. It can be used independently from the Open Terms Archive ecosystem. For a high-level overview of Open Terms Archive’s wider goals and processes, please read its [public homepage](https://opentermsarchive.org).
3
+ This codebase is a Node.js module enabling downloading, archiving and publishing versions of terms obtained online. It can be used independently from the Open Terms Archive ecosystem. For a high-level overview of Open Terms Archive’s wider goals and processes, please read its [public homepage](https://opentermsarchive.org).
4
4
 
5
5
  For documentation, visit [docs.opentermsarchive.org](https://docs.opentermsarchive.org/)
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentermsarchive/engine",
3
- "version": "4.2.0",
3
+ "version": "5.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": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Service",
3
- "documents": {
3
+ "terms": {
4
4
  "Terms of Service": {
5
5
  "fetch": "https://domain.example/tos",
6
6
  "select": "body"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Service",
3
- "documents": {
3
+ "terms": {
4
4
  "Terms of Service": {
5
5
  "fetch": "https://domain.example/tos",
6
6
  "select": "body",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Service",
3
- "documents": {
3
+ "terms": {
4
4
  "Terms of Service": {
5
5
  "fetch": "https://domain.example/tos",
6
6
  "select": "body"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Service",
3
- "documents": {
3
+ "terms": {
4
4
  "Terms of Service": {
5
5
  "fetch": "https://domain.example/tos",
6
6
  "select": "body"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Service",
3
- "documents": {
3
+ "terms": {
4
4
  "Terms of Service": {
5
5
  "fetch": "https://domain.example/tos",
6
6
  "select": "body",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Service B",
3
- "documents": {
3
+ "terms": {
4
4
  "Terms of Service": {
5
5
  "fetch": "https://domain.example/tos",
6
6
  "select": "body"
@@ -50,14 +50,14 @@ export default class DeclarationUtils {
50
50
  if (modifiedFilePath.endsWith('.filters.js')) {
51
51
  const declaration = await this.getJSONFromFile(this.defaultBranch, `declarations/${serviceId}.json`);
52
52
 
53
- servicesTermsTypes[serviceId] = Object.keys(declaration.documents); // Considering how rarely filters are used, simply return all term types that could potentially be impacted to spare implementing a function change check
53
+ servicesTermsTypes[serviceId] = Object.keys(declaration.terms); // Considering how rarely filters are used, simply return all term types that could potentially be impacted to spare implementing a function change check
54
54
 
55
55
  return;
56
56
  }
57
57
 
58
58
  const originalService = await this.getJSONFromFile(this.defaultBranch, modifiedFilePath);
59
59
  const modifiedService = await this.getJSONFromFile('HEAD', modifiedFilePath);
60
- const modifiedServiceTermsTypes = Object.keys(modifiedService.documents);
60
+ const modifiedServiceTermsTypes = Object.keys(modifiedService.terms);
61
61
 
62
62
  if (!originalService) {
63
63
  servicesTermsTypes[serviceId] = modifiedServiceTermsTypes;
@@ -65,11 +65,11 @@ export default class DeclarationUtils {
65
65
  return;
66
66
  }
67
67
 
68
- const originalServiceTermsTypes = Object.keys(originalService.documents);
68
+ const originalServiceTermsTypes = Object.keys(originalService.terms);
69
69
 
70
70
  modifiedServiceTermsTypes.forEach(termsType => {
71
71
  const areTermsAdded = !originalServiceTermsTypes.includes(termsType);
72
- const areTermsModified = JSON.stringify(originalService.documents[termsType]) != JSON.stringify(modifiedService.documents[termsType]);
72
+ const areTermsModified = JSON.stringify(originalService.terms[termsType]) != JSON.stringify(modifiedService.terms[termsType]);
73
73
 
74
74
  if (!areTermsAdded && !areTermsModified) {
75
75
  return;
@@ -24,14 +24,14 @@ const schema = {
24
24
  type: 'object',
25
25
  additionalProperties: false,
26
26
  title: 'Service declaration',
27
- required: [ 'name', 'documents' ],
27
+ required: [ 'name', 'terms' ],
28
28
  properties: {
29
29
  name: {
30
30
  type: 'string',
31
31
  title: 'Service public name',
32
32
  examples: ['Facebook'],
33
33
  },
34
- documents: {
34
+ terms: {
35
35
  type: 'object',
36
36
  properties: termsProperties(),
37
37
  propertyNames: { enum: AVAILABLE_TYPES_NAME },
@@ -71,7 +71,12 @@ describe('Metadata file validation', () => {
71
71
  return `- ${basePath}: "${actualValue}" ${formatMessages[error.params.format]}`;
72
72
  }
73
73
 
74
- let message = `- ${basePath}: "${actualValue}" ${error.message}`;
74
+ let message = `- ${basePath}:`;
75
+
76
+ if (actualValue !== undefined && typeof actualValue !== 'object') {
77
+ message += ` "${actualValue}"`;
78
+ }
79
+ message += ` ${error.message}`;
75
80
 
76
81
  if (error.keyword === 'enum') {
77
82
  message += ` "${error.params.allowedValues.join('", "')}"`;
@@ -21,7 +21,7 @@ export async function load(servicesIdsToLoad = []) {
21
21
  const services = {};
22
22
 
23
23
  await Promise.all(servicesIds.map(async serviceId => {
24
- const { name, documents: terms } = await loadServiceDeclaration(serviceId);
24
+ const { name, terms } = await loadServiceDeclaration(serviceId);
25
25
 
26
26
  const service = new Service({ id: serviceId, name });
27
27
 
@@ -220,9 +220,9 @@ async function loadServiceHistoryFiles(serviceId) {
220
220
  }
221
221
  }
222
222
 
223
- Object.keys(serviceDeclaration.documents).forEach(termsType => {
223
+ Object.keys(serviceDeclaration.terms).forEach(termsType => {
224
224
  serviceHistory[termsType] = serviceHistory[termsType] || [];
225
- serviceHistory[termsType].push(serviceDeclaration.documents[termsType]);
225
+ serviceHistory[termsType].push(serviceDeclaration.terms[termsType]);
226
226
  });
227
227
 
228
228
  sortHistory(serviceHistory);
@@ -16,7 +16,7 @@ export default class Terms {
16
16
  toPersistence() {
17
17
  return {
18
18
  name: this.service.name,
19
- documents: {
19
+ terms: {
20
20
  [this.type]: this.hasMultipleSourceDocuments
21
21
  ? { combine: this.sourceDocuments.map(sourceDocument => sourceDocument.toPersistence()) }
22
22
  : this.sourceDocuments[0].toPersistence(),
@@ -65,7 +65,7 @@ describe('Terms', () => {
65
65
 
66
66
  const expectedResult = {
67
67
  name: service.name,
68
- documents: { [termsType]: document1AsJSON },
68
+ terms: { [termsType]: document1AsJSON },
69
69
  };
70
70
 
71
71
  expect(result).to.deep.equal(expectedResult);
@@ -76,7 +76,7 @@ describe('Terms', () => {
76
76
 
77
77
  const expectedResult = {
78
78
  name: service.name,
79
- documents: { [termsType]: { combine: [ document1AsJSON, document2AsJSON ] } },
79
+ terms: { [termsType]: { combine: [ document1AsJSON, document2AsJSON ] } },
80
80
  };
81
81
 
82
82
  expect(result).to.deep.equal(expectedResult);
@@ -20,110 +20,155 @@ const PACKAGE_JSON_PATH = '../../../package.json';
20
20
  * type: object
21
21
  * description: Collection metadata
22
22
  * additionalProperties: false
23
+ * required:
24
+ * - id
25
+ * - name
26
+ * - tagline
27
+ * - languages
28
+ * - jurisdictions
23
29
  * properties:
24
30
  * id:
25
31
  * type: string
26
- * description: Unique identifier of the collection
32
+ * description: Unique identifier derived from name (acronyms, dash-separated).
33
+ * example: demo
27
34
  * name:
28
35
  * type: string
29
- * description: Display name of the collection
36
+ * description: Display name of the collection.
37
+ * example: Demo Collection
30
38
  * tagline:
31
39
  * type: string
32
- * description: Short description of the collection
40
+ * description: Concise description of collection topic.
41
+ * example: Services used by Open Terms Archive
42
+ * languages:
43
+ * type: array
44
+ * description: List of [ISO 639-1 (two-letter)](https://en.wikipedia.org/wiki/ISO_639) language codes representing languages allowed in the collection.
45
+ * example: [en, fr, de]
46
+ * items:
47
+ * type: string
48
+ * format: iso639-1
49
+ * jurisdictions:
50
+ * type: array
51
+ * description: List of [ISO 3166-2 country codes](https://en.wikipedia.org/wiki/ISO_3166-2) representing jurisdictions covered by the collection.
52
+ * example: [EU]
53
+ * items:
54
+ * type: string
55
+ * format: iso3166-2
33
56
  * description:
34
57
  * type: string
35
- * nullable: true
36
58
  * description: Detailed description of the collection
59
+ * example: |
60
+ * The **Demo** collection tracks changes to the terms of use of services used by Open Terms Archive.
61
+ *
62
+ * This provides a reference collection for best practices and enables the Open Terms Archive Core Team to be a user of the software it produces.
37
63
  * totalTerms:
38
64
  * type: integer
39
- * description: Total number of terms tracked in the collection
65
+ * description: Total number of terms tracked in the collection.
66
+ * x-ota-generated: true
40
67
  * totalServices:
41
68
  * type: integer
42
- * description: Total number of services tracked in the collection
69
+ * description: Total number of services tracked in the collection.
70
+ * x-ota-generated: true
43
71
  * engineVersion:
44
72
  * type: string
45
- * description: Version of the Open Terms Archive engine in SemVer format (MAJOR.MINOR.PATCH)
73
+ * description: Version of the Open Terms Archive engine in SemVer format (MAJOR.MINOR.PATCH).
74
+ * x-ota-generated: true
46
75
  * dataset:
47
76
  * type: string
48
77
  * format: uri
49
- * description: URL to the dataset releases
78
+ * description: URL to the dataset releases.
79
+ * example: https://github.com/OpenTermsArchive/demo-versions/releases
50
80
  * declarations:
51
81
  * type: string
52
82
  * format: uri
53
- * description: URL to the declarations repository
83
+ * description: URL to the declarations repository.
84
+ * example: https://github.com/OpenTermsArchive/demo-declarations
54
85
  * versions:
55
86
  * type: string
56
87
  * format: uri
57
- * description: URL to the versions repository
88
+ * description: URL to the versions repository.
89
+ * example: https://github.com/OpenTermsArchive/demo-versions
58
90
  * snapshots:
59
91
  * type: string
60
92
  * format: uri
61
- * description: URL to the snapshots repository
93
+ * description: URL to the snapshots repository.
94
+ * example: https://github.com/OpenTermsArchive/demo-snapshots
62
95
  * donations:
63
96
  * type: string
64
97
  * format: uri
65
- * description: URL to the donations page
98
+ * description: URL to the donations page.
99
+ * example: https://opencollective.com/opentermsarchive
66
100
  * logo:
67
101
  * type: string
68
102
  * format: uri
69
- * nullable: true
70
- * description: URL to the collection logo
71
- * languages:
72
- * type: array
73
- * description: List of ISO 639-1 (two-letter) language codes representing languages allowed by the collection
74
- * items:
75
- * type: string
76
- * format: iso639-1
77
- * jurisdictions:
78
- * type: array
79
- * description: List of ISO 3166-2 country codes representing jurisdictions covered by the collection
80
- * items:
81
- * type: string
82
- * format: iso3166-2
103
+ * description: URL to the collection's logo. Optimized PNG transparent image (minimum width 240px).
104
+ * example: https://opentermsarchive.org/images/logo/logo-open-terms-archive-black.png
83
105
  * trackingPeriods:
84
106
  * type: array
107
+ * description: List of time periods during which terms were tracked, with their tracking configuration. Gaps between periods indicate times when tracking was interrupted.
85
108
  * items:
86
109
  * type: object
87
110
  * additionalProperties: false
111
+ * required:
112
+ * - startDate
113
+ * - schedule
114
+ * - serverLocation
88
115
  * properties:
89
116
  * startDate:
90
117
  * type: string
91
118
  * format: date
92
- * description: The date when tracking started for this period
119
+ * description: The date when tracking started for this period (ISO 8601 format YYYY-MM-DD).
120
+ * example: 2023-01-01
93
121
  * schedule:
94
122
  * type: string
95
123
  * format: cron-expression
96
- * description: A cron expression defining when terms are tracked (e.g. "0 0 * * *" for daily at midnight)
124
+ * description: A [cron expression](https://en.wikipedia.org/wiki/Cron#Cron_expression) that defines the tracking frequency.
125
+ * example: 0 0 * * *
97
126
  * serverLocation:
98
127
  * type: string
99
- * description: The geographic location of the server used for tracking
128
+ * description: The geographic location of the tracking server (city name and ISO 3166-2 country code).
129
+ * example: Paris, FR
100
130
  * endDate:
101
131
  * type: string
102
132
  * format: date
103
- * description: The date when tracking ended for this period
133
+ * description: The date when tracking ended for this period (ISO 8601 format YYYY-MM-DD). If not specified, tracking is ongoing.
134
+ * example: 2023-12-01
104
135
  * governance:
105
136
  * type: object
137
+ * description: Map of organizations involved in the collection's governance, with organization names as keys and governance objects as values.
106
138
  * additionalProperties:
107
139
  * type: object
108
140
  * additionalProperties: false
141
+ * required:
142
+ * - roles
109
143
  * properties:
110
144
  * url:
111
145
  * type: string
112
146
  * format: uri
113
147
  * description: URL to the entity's website
148
+ * example: https://opentermsarchive.org/
114
149
  * logo:
115
150
  * type: string
116
151
  * format: uri
117
- * description: URL to the entity's logo
152
+ * description: URL to the entity's logo. Optimized PNG transparent image (minimum width 240px).
153
+ * example: https://opentermsarchive.org/images/logo/logo-open-terms-archive-black.png
118
154
  * roles:
119
155
  * type: array
156
+ * description: Roles of the entity within the governance, see [collection governance](https://docs.opentermsarchive.org/collections/reference/governance/)
157
+ * example: [host, administrator]
120
158
  * items:
121
159
  * type: string
122
160
  * enum: [host, administrator, curator, maintainer, sponsor]
123
- * description: Roles of the entity within the governance
124
161
  * i18n:
125
162
  * type: object
126
163
  * description: Internationalization of any of the Metadata properties (except i18n itself) for different language codes
164
+ * example: |
165
+ * fr:
166
+ * name: Démo
167
+ * tagline: Services utilisés par Open Terms Archive
168
+ * governance:
169
+ * Ministry for Europe and Foreign Affairs:
170
+ * name: Ministère de l'Europe et des Affaires étrangères
171
+ * url: https://www.diplomatie.gouv.fr
127
172
  * additionalProperties:
128
173
  * type: object
129
174
  */