cocoda-sdk 1.0.13 → 2.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/LICENSE +1 -1
- package/README.md +74 -28
- package/dist/cjs/index.cjs +2673 -0
- package/dist/cocoda-sdk.js +33 -17423
- package/dist/cocoda-sdk.js.LICENSES.txt +105 -86
- package/dist/cocoda-sdk.js.map +7 -0
- package/dist/esm/errors/index.js +46 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/lib/CocodaSDK.js +269 -0
- package/dist/esm/providers/base-provider.js +368 -0
- package/dist/esm/providers/concept-api-provider.js +278 -0
- package/dist/esm/providers/index.js +20 -0
- package/dist/esm/providers/label-search-suggestion-provider.js +101 -0
- package/dist/esm/providers/loc-api-provider.js +185 -0
- package/dist/esm/providers/local-mappings-provider.js +337 -0
- package/dist/esm/providers/mappings-api-provider.js +264 -0
- package/dist/esm/providers/occurrences-api-provider.js +163 -0
- package/dist/esm/providers/reconciliation-api-provider.js +140 -0
- package/dist/esm/providers/skosmos-api-provider.js +345 -0
- package/{utils → dist/esm/utils}/index.js +40 -53
- package/dist/esm/utils/lodash.js +34 -0
- package/package.json +16 -17
- package/errors/index.js +0 -119
- package/index.js +0 -5
- package/lib/CocodaSDK.js +0 -360
- package/providers/base-provider.js +0 -581
- package/providers/concept-api-provider.js +0 -377
- package/providers/index.js +0 -34
- package/providers/label-search-suggestion-provider.js +0 -219
- package/providers/loc-api-provider.js +0 -275
- package/providers/local-mappings-provider.js +0 -459
- package/providers/mappings-api-provider.js +0 -396
- package/providers/occurrences-api-provider.js +0 -234
- package/providers/reconciliation-api-provider.js +0 -211
- package/providers/skosmos-api-provider.js +0 -441
- package/utils/lodash.js +0 -21
package/lib/CocodaSDK.js
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
const providers = require("../providers")
|
|
2
|
-
const errors = require("../errors")
|
|
3
|
-
const axios = require("axios")
|
|
4
|
-
const _ = require("../utils/lodash")
|
|
5
|
-
const jskos = require("jskos-tools")
|
|
6
|
-
|
|
7
|
-
class CocodaSDK {
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* CDK constructor.
|
|
11
|
-
*
|
|
12
|
-
* @param {Object} [config={}] Cocoda-stye config object
|
|
13
|
-
*/
|
|
14
|
-
constructor(config) {
|
|
15
|
-
this.config = config
|
|
16
|
-
this.axios = axios.create()
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Method to set the configuration.
|
|
21
|
-
*
|
|
22
|
-
* @param {Object} config Cocoda-stye config object
|
|
23
|
-
*/
|
|
24
|
-
setConfig(config) {
|
|
25
|
-
this.config = config
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Current configuration.
|
|
30
|
-
*
|
|
31
|
-
* @returns {Object} current configuration
|
|
32
|
-
*/
|
|
33
|
-
get config() {
|
|
34
|
-
return this._config
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Prepares config when set.
|
|
39
|
-
*
|
|
40
|
-
* @param {Object} config Cocoda config object
|
|
41
|
-
* @private
|
|
42
|
-
*/
|
|
43
|
-
set config(config) {
|
|
44
|
-
config = config || {}
|
|
45
|
-
// Preparations for config
|
|
46
|
-
// 1. Make sure config.registries exists
|
|
47
|
-
config.registries = config.registries || []
|
|
48
|
-
// 2. Initialize registries
|
|
49
|
-
config.registries = config.registries.map(registry => providers.init(registry)).filter(r => r)
|
|
50
|
-
// 3. Call setRegistries for registries if available
|
|
51
|
-
for (let registry of config.registries.filter(r => r.setRegistries)) {
|
|
52
|
-
registry.setRegistries(config.registries)
|
|
53
|
-
}
|
|
54
|
-
this._config = config
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Array of registered providers. Especially useful for implementating custom providers:
|
|
59
|
-
*
|
|
60
|
-
* class CustomProvider extends cdk.providers.Base {
|
|
61
|
-
* // ...
|
|
62
|
-
* }
|
|
63
|
-
*
|
|
64
|
-
* @returns {Array} array of registered providers
|
|
65
|
-
*/
|
|
66
|
-
get providers() {
|
|
67
|
-
return providers
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Creates a new CDK instance (same as `new CocodaSDK(config)`).
|
|
72
|
-
*
|
|
73
|
-
* @param {Object} config Cocoda config object
|
|
74
|
-
* @returns {CocodaSDK} new CDK instance
|
|
75
|
-
*/
|
|
76
|
-
createInstance(config) {
|
|
77
|
-
return new CocodaSDK(config)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Offer method to load a config file from URL.
|
|
82
|
-
*
|
|
83
|
-
* @param {string} url URL of config as JSON
|
|
84
|
-
*/
|
|
85
|
-
async loadConfig(url) {
|
|
86
|
-
const response = await this.axios.get(url)
|
|
87
|
-
this.config = response.data
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Method to load buildInfo.
|
|
92
|
-
*
|
|
93
|
-
* Callback will only be called if buildInfo changes; it will not be called when there is no previous value.
|
|
94
|
-
*
|
|
95
|
-
* @param {Object} config
|
|
96
|
-
* @param {string} [config.url] full URL for build-info.json (default is taken from config.cocodaBaseUrl)
|
|
97
|
-
* @param {Object} [config.buildInfo] current buildInfo
|
|
98
|
-
* @param {number} [config.interval=60000] interval to load buildInfo in ms
|
|
99
|
-
* @param {Function} config.callback callback function called with two parameters (error, buildInfo, previousBuildInfo)
|
|
100
|
-
* @returns {Object} object with two function properties, `stop` to cancel the repeating request, `start` to restart the repeating request, as well as three convenience properties, `isPaused` (whether it is currently paused), `lastResult`, `hasErrored` (whether the last call of the function has errored)
|
|
101
|
-
*/
|
|
102
|
-
loadBuildInfo({ url, buildInfo = null, interval = 60000, callback, ...config }) {
|
|
103
|
-
if (!url && !this.config.cocodaBaseUrl) {
|
|
104
|
-
throw new errors.CDKError({ message: "Could not determine URL to load build config." })
|
|
105
|
-
}
|
|
106
|
-
if (!url) {
|
|
107
|
-
url = `${this.config.cocodaBaseUrl}build-info.json`
|
|
108
|
-
}
|
|
109
|
-
return this.repeat({
|
|
110
|
-
...config,
|
|
111
|
-
function: async () => {
|
|
112
|
-
return (await this.axios.get(url, {
|
|
113
|
-
headers: {
|
|
114
|
-
"Cache-Control": "no-cache",
|
|
115
|
-
},
|
|
116
|
-
})).data
|
|
117
|
-
},
|
|
118
|
-
interval,
|
|
119
|
-
callback: (error, result, previousResult) => {
|
|
120
|
-
if (error) {
|
|
121
|
-
callback(error)
|
|
122
|
-
} else if (previousResult || (!previousResult && buildInfo && !_.isEqual(result, buildInfo))) {
|
|
123
|
-
callback(null, result, previousResult || buildInfo)
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
})
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Method to get a registry by URI.
|
|
131
|
-
*
|
|
132
|
-
* @param {string} uri URI of registry in config
|
|
133
|
-
* @returns {?Object} initialized registry from config if found
|
|
134
|
-
*/
|
|
135
|
-
getRegistryForUri(uri) {
|
|
136
|
-
return this.config.registries.find(r => r.uri == uri)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Method to initialize registry.
|
|
141
|
-
*
|
|
142
|
-
* @param {Object} registry JSKOS registry object
|
|
143
|
-
* @returns {Object} initialized registry
|
|
144
|
-
*/
|
|
145
|
-
initializeRegistry(registry) {
|
|
146
|
-
return providers.init(registry)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Method to add custom provider.
|
|
151
|
-
*
|
|
152
|
-
* @param {Object} provider provider class that extends BaseProvider
|
|
153
|
-
*/
|
|
154
|
-
addProvider(provider) {
|
|
155
|
-
providers.addProvider(provider)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Repeatedly call a certain function.
|
|
160
|
-
*
|
|
161
|
-
* Notes:
|
|
162
|
-
* - Callback will only be called if the results were changed.
|
|
163
|
-
* - The function will only be repeated after the previous call is resolved. This means that the total interval duration is (interval + duration of function call).
|
|
164
|
-
*
|
|
165
|
-
* Example:
|
|
166
|
-
* ```js
|
|
167
|
-
* cdk.repeat({
|
|
168
|
-
* function: () => registry.getMappings(),
|
|
169
|
-
* callback: (error, result) => console.log(result),
|
|
170
|
-
* })
|
|
171
|
-
* ```
|
|
172
|
-
*
|
|
173
|
-
* @param {Object} config
|
|
174
|
-
* @param {string} config.function a function to be called (can be async)
|
|
175
|
-
* @param {number} [config.interval=15000] interval in ms
|
|
176
|
-
* @param {Function} config.callback callback function called with two parameters (error, result, previousResult)
|
|
177
|
-
* @param {boolean} [config.callImmediately=true] whether to call the function immediately
|
|
178
|
-
* @returns {Object} object with two function properties, `stop` to cancel the repeating request, `start` to restart the repeating request, as well as three convenience properties, `isPaused` (whether it is currently paused), `lastResult`, `hasErrored` (whether the last call of the function has errored)
|
|
179
|
-
*/
|
|
180
|
-
repeat({ function: func, interval = 15000, callback, callImmediately = true } = {}) {
|
|
181
|
-
// Check parameters
|
|
182
|
-
// ? Are these thorough checks really necessary?
|
|
183
|
-
if (!func) {
|
|
184
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "function" })
|
|
185
|
-
}
|
|
186
|
-
if (typeof func != "function") {
|
|
187
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "function", message: "function needs to be a function" })
|
|
188
|
-
}
|
|
189
|
-
// Wrap function so that it will definitely be async
|
|
190
|
-
const asyncFunc = async () => func()
|
|
191
|
-
interval = parseInt(interval)
|
|
192
|
-
if (isNaN(interval)) {
|
|
193
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "interval" })
|
|
194
|
-
}
|
|
195
|
-
if (!callback) {
|
|
196
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "callback" })
|
|
197
|
-
}
|
|
198
|
-
if (typeof callback != "function") {
|
|
199
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "callback", message: "callback needs to be a function" })
|
|
200
|
-
}
|
|
201
|
-
// Prepare repeat cache
|
|
202
|
-
let repeat = {
|
|
203
|
-
timer: null,
|
|
204
|
-
result: null,
|
|
205
|
-
error: null,
|
|
206
|
-
isPaused: false,
|
|
207
|
-
}
|
|
208
|
-
// Functions to handle results and errors
|
|
209
|
-
const handleResult = (result) => {
|
|
210
|
-
const previousResult = repeat.result
|
|
211
|
-
if (!_.isEqual(previousResult, result)) {
|
|
212
|
-
repeat.result = result
|
|
213
|
-
repeat.error = null
|
|
214
|
-
callback(null, result, previousResult)
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const handleError = (error) => {
|
|
218
|
-
repeat.error = error
|
|
219
|
-
callback(error)
|
|
220
|
-
}
|
|
221
|
-
// Method to call a method after timeout if necessary
|
|
222
|
-
const repeatIfNecessary = toCall => {
|
|
223
|
-
if (repeat.isPaused) {
|
|
224
|
-
return
|
|
225
|
-
}
|
|
226
|
-
repeat.timer = setTimeout(() => {
|
|
227
|
-
toCall()
|
|
228
|
-
}, interval)
|
|
229
|
-
}
|
|
230
|
-
// Method to call the function, handle result/error, and repeat if necessary
|
|
231
|
-
const call = () => asyncFunc().then(handleResult).catch(handleError).then(() => repeatIfNecessary(call))
|
|
232
|
-
// Method to set up the repeating call (skip initial call if necessary)
|
|
233
|
-
const setup = (_callImmediately = callImmediately) => {
|
|
234
|
-
if (_callImmediately) {
|
|
235
|
-
call()
|
|
236
|
-
} else {
|
|
237
|
-
repeatIfNecessary(call)
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
// Set up
|
|
241
|
-
setup()
|
|
242
|
-
// Return object with methods to start/stop the interval and an indicator whether it is paused
|
|
243
|
-
return {
|
|
244
|
-
start: (...params) => {
|
|
245
|
-
repeat.isPaused = false
|
|
246
|
-
setup(...params)
|
|
247
|
-
},
|
|
248
|
-
stop: () => {
|
|
249
|
-
repeat.isPaused = true
|
|
250
|
-
// If timer is available, clear immediately, if not, wait for one interval
|
|
251
|
-
if (repeat.timer) {
|
|
252
|
-
clearTimeout(repeat.timer)
|
|
253
|
-
} else {
|
|
254
|
-
setTimeout(() => {
|
|
255
|
-
repeat.timer && clearTimeout(repeat.timer)
|
|
256
|
-
}, interval)
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
|
-
get isPaused() {
|
|
260
|
-
return repeat.isPaused
|
|
261
|
-
},
|
|
262
|
-
get lastResult() {
|
|
263
|
-
return repeat.result
|
|
264
|
-
},
|
|
265
|
-
get hasErrored() {
|
|
266
|
-
return !!repeat.error
|
|
267
|
-
},
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Gets schemes from all registries that support schemes and merges the results.
|
|
273
|
-
*
|
|
274
|
-
* @param {Object} [config={}] configuration object that will be used as a parameter for internal `getSchemes` calls
|
|
275
|
-
* @returns {Object[]} array of JSKOS schemes
|
|
276
|
-
*/
|
|
277
|
-
async getSchemes(config = {}) {
|
|
278
|
-
let schemes = [], promises = []
|
|
279
|
-
|
|
280
|
-
for (let registry of this.config.registries) {
|
|
281
|
-
if (registry.has.schemes) {
|
|
282
|
-
let promise = registry.getSchemes(config).then(results => {
|
|
283
|
-
for (let scheme of results) {
|
|
284
|
-
// Add scheme specific custom properties
|
|
285
|
-
scheme.__DETAILSLOADED__ = 1
|
|
286
|
-
scheme.type = scheme.type || ["http://www.w3.org/2004/02/skos/core#ConceptScheme"]
|
|
287
|
-
// Check if scheme is already loaded
|
|
288
|
-
let otherScheme = schemes.find(s => jskos.compare(s, scheme)), prio, otherPrio, override = false
|
|
289
|
-
if (otherScheme) {
|
|
290
|
-
// Set priorities as index of registry array
|
|
291
|
-
prio = this.config.registries.indexOf(registry)
|
|
292
|
-
if (prio != -1) {
|
|
293
|
-
prio = this.config.registries.length - prio
|
|
294
|
-
}
|
|
295
|
-
otherPrio = this.config.registries.indexOf(_.get(otherScheme, "_registry"))
|
|
296
|
-
if (otherPrio != -1) {
|
|
297
|
-
otherPrio = this.config.registries.length - otherPrio
|
|
298
|
-
}
|
|
299
|
-
let currentHasConcepts = !scheme.concepts ? 0 : (scheme.concepts.length == 0 ? -1 : 1)
|
|
300
|
-
let otherHasConcepts = !otherScheme.concepts ? 0 : (otherScheme.concepts.length == 0 ? -1 : 1)
|
|
301
|
-
// Use existence of concepts first, priority second
|
|
302
|
-
if (currentHasConcepts > otherHasConcepts) {
|
|
303
|
-
override = true
|
|
304
|
-
} else if (currentHasConcepts < otherHasConcepts) {
|
|
305
|
-
override = false
|
|
306
|
-
} else {
|
|
307
|
-
override = otherPrio < prio
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
if (!otherScheme || override) {
|
|
311
|
-
if (override) {
|
|
312
|
-
// Find and remove scheme from schemes array
|
|
313
|
-
let otherSchemeIndex = schemes.findIndex(s => jskos.compare(s, otherScheme))
|
|
314
|
-
if (otherSchemeIndex != -1) {
|
|
315
|
-
schemes.splice(otherSchemeIndex, 1)
|
|
316
|
-
}
|
|
317
|
-
// Integrate details from existing scheme
|
|
318
|
-
scheme = jskos.merge(scheme, otherScheme, { mergeUris: true, skipPaths: ["_registry"] })
|
|
319
|
-
}
|
|
320
|
-
scheme._registry = registry
|
|
321
|
-
// Save scheme in objects and push into schemes array
|
|
322
|
-
schemes.push(scheme)
|
|
323
|
-
} else {
|
|
324
|
-
// Integrate details into existing scheme
|
|
325
|
-
let index = schemes.findIndex(s => jskos.compare(s, scheme))
|
|
326
|
-
if (index != -1) {
|
|
327
|
-
let registry = schemes[index]._registry
|
|
328
|
-
schemes[index] = jskos.merge(schemes[index], _.omit(scheme, ["concepts", "topConcepts"]), { mergeUris: true, skipPaths: ["_registry"] })
|
|
329
|
-
schemes[index]._registry = registry
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}).catch(error => {
|
|
334
|
-
// TODO
|
|
335
|
-
console.warn("Couldn't load schemes for registry", registry.uri, error)
|
|
336
|
-
})
|
|
337
|
-
promises.push(promise)
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
return Promise.all(promises).then(() => {
|
|
342
|
-
// Remove certain properties from objects
|
|
343
|
-
// ? Why?
|
|
344
|
-
for (let scheme of schemes) {
|
|
345
|
-
if (scheme.concepts && scheme.concepts.length == 0) {
|
|
346
|
-
delete scheme.concepts
|
|
347
|
-
}
|
|
348
|
-
if (scheme.topConcepts && scheme.topConcepts.length == 0) {
|
|
349
|
-
delete scheme.topConcepts
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
schemes = schemes.filter(scheme => scheme != null)
|
|
353
|
-
schemes = jskos.sortSchemes(schemes)
|
|
354
|
-
return schemes
|
|
355
|
-
})
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
module.exports = CocodaSDK
|