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.
Files changed (36) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +74 -28
  3. package/dist/cjs/index.cjs +2673 -0
  4. package/dist/cocoda-sdk.js +33 -17423
  5. package/dist/cocoda-sdk.js.LICENSES.txt +105 -86
  6. package/dist/cocoda-sdk.js.map +7 -0
  7. package/dist/esm/errors/index.js +46 -0
  8. package/dist/esm/index.js +9 -0
  9. package/dist/esm/lib/CocodaSDK.js +269 -0
  10. package/dist/esm/providers/base-provider.js +368 -0
  11. package/dist/esm/providers/concept-api-provider.js +278 -0
  12. package/dist/esm/providers/index.js +20 -0
  13. package/dist/esm/providers/label-search-suggestion-provider.js +101 -0
  14. package/dist/esm/providers/loc-api-provider.js +185 -0
  15. package/dist/esm/providers/local-mappings-provider.js +337 -0
  16. package/dist/esm/providers/mappings-api-provider.js +264 -0
  17. package/dist/esm/providers/occurrences-api-provider.js +163 -0
  18. package/dist/esm/providers/reconciliation-api-provider.js +140 -0
  19. package/dist/esm/providers/skosmos-api-provider.js +345 -0
  20. package/{utils → dist/esm/utils}/index.js +40 -53
  21. package/dist/esm/utils/lodash.js +34 -0
  22. package/package.json +16 -17
  23. package/errors/index.js +0 -119
  24. package/index.js +0 -5
  25. package/lib/CocodaSDK.js +0 -360
  26. package/providers/base-provider.js +0 -581
  27. package/providers/concept-api-provider.js +0 -377
  28. package/providers/index.js +0 -34
  29. package/providers/label-search-suggestion-provider.js +0 -219
  30. package/providers/loc-api-provider.js +0 -275
  31. package/providers/local-mappings-provider.js +0 -459
  32. package/providers/mappings-api-provider.js +0 -396
  33. package/providers/occurrences-api-provider.js +0 -234
  34. package/providers/reconciliation-api-provider.js +0 -211
  35. package/providers/skosmos-api-provider.js +0 -441
  36. 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