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
@@ -0,0 +1,163 @@
1
+ import BaseProvider from "./base-provider.js";
2
+ import jskos from "jskos-tools";
3
+ import * as _ from "../utils/lodash.js";
4
+ import * as errors from "../errors/index.js";
5
+ import * as utils from "../utils/index.js";
6
+ class OccurrencesApiProvider extends BaseProvider {
7
+ _setup() {
8
+ this._cache = [];
9
+ this._occurrencesSupportedSchemes = [];
10
+ this.has.occurrences = true;
11
+ this.has.mappings = true;
12
+ }
13
+ async _occurrencesIsSupported(scheme) {
14
+ if (this._occurrencesSupportedSchemes && this._occurrencesSupportedSchemes.length) {
15
+ } else {
16
+ try {
17
+ const url = utils.concatUrl(this._api.api, "voc");
18
+ const data = await this.axios({
19
+ method: "get",
20
+ url
21
+ });
22
+ this._occurrencesSupportedSchemes = data || [];
23
+ } catch (error) {
24
+ }
25
+ }
26
+ let supported = false;
27
+ for (let supportedScheme of this._occurrencesSupportedSchemes) {
28
+ if (jskos.compare(scheme, supportedScheme)) {
29
+ supported = true;
30
+ }
31
+ }
32
+ return supported;
33
+ }
34
+ async getMappings(config) {
35
+ const occurrences = await this.getOccurrences(config);
36
+ const fromScheme = _.get(config, "from.inScheme[0]") || config.fromScheme;
37
+ const toScheme = _.get(config, "to.inScheme[0]") || config.toScheme;
38
+ const mappings = [];
39
+ for (let occurrence of occurrences) {
40
+ if (!occurrence) {
41
+ continue;
42
+ }
43
+ let mapping = {};
44
+ mapping.from = _.get(occurrence, "memberSet[0]");
45
+ if (mapping.from) {
46
+ mapping.from = { memberSet: [mapping.from] };
47
+ } else {
48
+ mapping.from = null;
49
+ }
50
+ mapping.fromScheme = _.get(occurrence, "memberSet[0].inScheme[0]");
51
+ mapping.to = _.get(occurrence, "memberSet[1]");
52
+ if (mapping.to) {
53
+ mapping.to = { memberSet: [mapping.to] };
54
+ } else {
55
+ mapping.to = { memberSet: [] };
56
+ }
57
+ mapping.toScheme = _.get(occurrence, "memberSet[1].inScheme[0]");
58
+ if (fromScheme && mapping.fromScheme && !jskos.compare(mapping.fromScheme, fromScheme) || toScheme && mapping.toScheme && !jskos.compare(mapping.toScheme, toScheme)) {
59
+ [mapping.from, mapping.fromScheme, mapping.to, mapping.toScheme] = [mapping.to, mapping.toScheme, mapping.from, mapping.fromScheme];
60
+ }
61
+ if (!mapping.fromScheme && fromScheme) {
62
+ mapping.fromScheme = fromScheme;
63
+ }
64
+ if (!mapping.toScheme && toScheme) {
65
+ mapping.toScheme = toScheme;
66
+ }
67
+ mapping.type = [jskos.defaultMappingType.uri];
68
+ mapping._occurrence = occurrence;
69
+ mapping = jskos.addMappingIdentifiers(mapping);
70
+ if (occurrence.database) {
71
+ mapping.creator = [occurrence.database];
72
+ }
73
+ mappings.push(mapping);
74
+ }
75
+ return mappings;
76
+ }
77
+ async getOccurrences({ from, to, concepts, ...config }) {
78
+ let promises = [];
79
+ concepts = (concepts || []).concat([from, to]).filter((c) => !!c);
80
+ for (let concept of concepts) {
81
+ promises.push(this._occurrencesIsSupported(_.get(concept, "inScheme[0]")).then((supported) => {
82
+ if (supported && concept.uri) {
83
+ return concept.uri;
84
+ } else {
85
+ return null;
86
+ }
87
+ }));
88
+ }
89
+ let uris = await Promise.all(promises);
90
+ uris = uris.filter((uri) => uri != null);
91
+ if (uris.length == 0) {
92
+ throw new errors.InvalidOrMissingParameterError({ parameter: "concepts" });
93
+ }
94
+ promises = [];
95
+ for (let uri of uris) {
96
+ promises.push(this._getOccurrences({
97
+ ...config,
98
+ params: {
99
+ member: uri,
100
+ scheme: "*",
101
+ threshold: 5
102
+ }
103
+ }));
104
+ }
105
+ if (uris.length > 1) {
106
+ let urisString = uris.join(" ");
107
+ promises.push(this._getOccurrences({
108
+ ...config,
109
+ params: {
110
+ member: urisString,
111
+ threshold: 5
112
+ }
113
+ }));
114
+ }
115
+ const results = await Promise.all(promises);
116
+ let occurrences = _.concat([], ...results);
117
+ let existingUris = [];
118
+ let indexesToDelete = [];
119
+ for (let i = 0; i < occurrences.length; i += 1) {
120
+ let occurrence = occurrences[i];
121
+ if (!occurrence) {
122
+ continue;
123
+ }
124
+ let uris2 = occurrence.memberSet.reduce((total, current) => total.concat(current.uri), []).sort().join(" ");
125
+ if (existingUris.includes(uris2)) {
126
+ indexesToDelete.push(i);
127
+ } else {
128
+ existingUris.push(uris2);
129
+ }
130
+ }
131
+ indexesToDelete.forEach((value) => {
132
+ delete occurrences[value];
133
+ });
134
+ occurrences = occurrences.filter((o) => o != null);
135
+ return occurrences.sort((a, b) => parseInt(b.count || 0) - parseInt(a.count || 0));
136
+ }
137
+ async _getOccurrences(config) {
138
+ let resultsFromCache = this._cache.find((item) => {
139
+ return _.isEqual(item.config.params, config.params);
140
+ });
141
+ if (resultsFromCache) {
142
+ return resultsFromCache.data;
143
+ }
144
+ const data = await this.axios({
145
+ ...config,
146
+ method: "get",
147
+ url: this._api.api
148
+ });
149
+ this._cache.push({
150
+ config,
151
+ data
152
+ });
153
+ if (this._cache.length > 20) {
154
+ this._cache = this._cache.slice(this._cache.length - 20);
155
+ }
156
+ return data;
157
+ }
158
+ }
159
+ OccurrencesApiProvider.providerName = "OccurrencesApi";
160
+ OccurrencesApiProvider.stored = false;
161
+ export {
162
+ OccurrencesApiProvider as default
163
+ };
@@ -0,0 +1,140 @@
1
+ import BaseProvider from "./base-provider.js";
2
+ import jskos from "jskos-tools";
3
+ import * as _ from "../utils/lodash.js";
4
+ import * as errors from "../errors/index.js";
5
+ class ReconciliationApiProvider extends BaseProvider {
6
+ _setup() {
7
+ this.has.mappings = true;
8
+ this._cache = [];
9
+ }
10
+ async getMappings({ from, to, mode, ...config }) {
11
+ let schemes = [];
12
+ if (_.isArray(this.schemes)) {
13
+ schemes = this.schemes;
14
+ }
15
+ let swap;
16
+ let concept;
17
+ let fromConceptScheme = _.get(from, "inScheme[0]");
18
+ let toConceptScheme = _.get(to, "inScheme[0]");
19
+ let fromScheme;
20
+ let toScheme;
21
+ if (!from || jskos.isContainedIn(fromConceptScheme, schemes)) {
22
+ swap = true;
23
+ concept = to;
24
+ fromScheme = toConceptScheme;
25
+ toScheme = schemes.find((scheme) => jskos.compare(scheme, fromConceptScheme)) || schemes[0];
26
+ } else {
27
+ swap = false;
28
+ concept = from;
29
+ fromScheme = fromConceptScheme;
30
+ toScheme = schemes.find((scheme) => jskos.compare(scheme, toConceptScheme)) || schemes[0];
31
+ }
32
+ if (mode != "or") {
33
+ return [];
34
+ }
35
+ if (!this._api.api) {
36
+ throw new errors.MissingApiUrlError();
37
+ }
38
+ if (!concept) {
39
+ throw new errors.InvalidOrMissingParameterError({ parameter: swap ? "to" : "from" });
40
+ }
41
+ let language = jskos.languagePreference.selectLanguage(concept.prefLabel);
42
+ if (!language) {
43
+ throw new errors.InvalidOrMissingParameterError({ parameter: swap ? "to" : "from", message: "Missing language" });
44
+ }
45
+ let altLabels = _.get(concept, `altLabel.${language}`, []);
46
+ if (_.isString(altLabels)) {
47
+ altLabels = [altLabels];
48
+ }
49
+ let prefLabel = _.get(concept, `prefLabel.${language}`);
50
+ let labels = altLabels.concat([prefLabel]);
51
+ labels = [prefLabel];
52
+ let { url, data: results } = await this._getReconciliationResults({ ...config, labels, language });
53
+ results = [].concat(...Object.values(results).map((value) => value.result)).filter((r) => r);
54
+ results = results.sort((a, b) => {
55
+ if (a.score != b.score) {
56
+ return b.score - a.score;
57
+ }
58
+ if (a.match != b.match) {
59
+ if (a.match) {
60
+ return -1;
61
+ } else {
62
+ return 1;
63
+ }
64
+ }
65
+ return a.id.length - b.id.length;
66
+ });
67
+ let namespace = _.get(toScheme, "namespace", "");
68
+ let mappings = results.map((result) => ({
69
+ fromScheme,
70
+ from: { memberSet: [concept] },
71
+ toScheme,
72
+ to: {
73
+ memberSet: [
74
+ {
75
+ uri: namespace + result.id
76
+ }
77
+ ]
78
+ },
79
+ type: [
80
+ result.match ? "http://www.w3.org/2004/02/skos/core#exactMatch" : result.score >= 80 ? "http://www.w3.org/2004/02/skos/core#closeMatch" : "http://www.w3.org/2004/02/skos/core#mappingRelation"
81
+ ]
82
+ }));
83
+ if (swap) {
84
+ mappings = mappings.map((mapping) => Object.assign(mapping, {
85
+ fromScheme: mapping.toScheme,
86
+ from: mapping.to,
87
+ toScheme: mapping.fromScheme,
88
+ to: mapping.from
89
+ }));
90
+ }
91
+ mappings._url = url;
92
+ return mappings;
93
+ }
94
+ async _getReconciliationResults({ labels, language, ...config }) {
95
+ labels = labels.sort();
96
+ let resultsFromCache = this._cache.find((item) => {
97
+ return _.isEqual(item.labels, labels) && item.language == language;
98
+ });
99
+ if (resultsFromCache) {
100
+ return resultsFromCache;
101
+ }
102
+ let queries = {};
103
+ let index = 0;
104
+ for (let label of labels) {
105
+ queries[`q${index}`] = {
106
+ query: label
107
+ };
108
+ index += 1;
109
+ }
110
+ let url = this._api.api;
111
+ if (language) {
112
+ url = url.replace("{language}", language);
113
+ }
114
+ const encodedData = `queries=${encodeURIComponent(JSON.stringify(queries))}`;
115
+ _.set(config, ["headers", "Content-Type"], "application/x-www-form-urlencoded");
116
+ let data = await this.axios({
117
+ ...config,
118
+ method: "post",
119
+ url,
120
+ data: encodedData
121
+ });
122
+ data = data || {};
123
+ let newCacheEntry = {
124
+ labels,
125
+ language,
126
+ data,
127
+ url: `${url}${url.includes("?") ? "&" : "?"}${encodedData}`
128
+ };
129
+ this._cache.push(newCacheEntry);
130
+ if (this._cache.length > 20) {
131
+ this._cache = this._cache.slice(this._cache.length - 20);
132
+ }
133
+ return newCacheEntry;
134
+ }
135
+ }
136
+ ReconciliationApiProvider.providerName = "ReconciliationApi";
137
+ ReconciliationApiProvider.stored = false;
138
+ export {
139
+ ReconciliationApiProvider as default
140
+ };
@@ -0,0 +1,345 @@
1
+ import BaseProvider from "./base-provider.js";
2
+ import jskos from "jskos-tools";
3
+ import * as _ from "../utils/lodash.js";
4
+ import * as errors from "../errors/index.js";
5
+ class SkosmosApiProvider extends BaseProvider {
6
+ _setup() {
7
+ this.has.schemes = true;
8
+ this.has.top = false;
9
+ this.has.data = true;
10
+ this.has.concepts = true;
11
+ this.has.narrower = true;
12
+ this.has.ancestors = true;
13
+ this.has.types = true;
14
+ this.has.suggest = true;
15
+ this.has.search = true;
16
+ for (let scheme of this.schemes) {
17
+ scheme.concepts = [null];
18
+ scheme.topConcepts = [];
19
+ }
20
+ }
21
+ static _registryConfigForBartocApiConfig({ url, scheme } = {}) {
22
+ if (!url || !scheme) {
23
+ return null;
24
+ }
25
+ const config = {};
26
+ const match = url.match(/(.+\/)([^/]+)\/$/);
27
+ if (!match) {
28
+ return null;
29
+ }
30
+ config.api = match[1] + "rest/v1/";
31
+ scheme.VOCID = match[2];
32
+ config.schemes = [scheme];
33
+ return config;
34
+ }
35
+ get _language() {
36
+ return this.languages[0] || this._defaultLanguages[0] || "en";
37
+ }
38
+ _getApiUrl(scheme, endpoint, params) {
39
+ if (!scheme || !scheme.VOCID) {
40
+ throw new errors.InvalidOrMissingParameterError({ parameter: "scheme", message: "Missing scheme or VOCID property on scheme" });
41
+ }
42
+ endpoint = endpoint || "";
43
+ params = params || {};
44
+ if (!params.lang) {
45
+ params.lang = this._language;
46
+ }
47
+ const paramString = Object.keys(params).map((k) => `${k}=${encodeURIComponent(params[k])}`).join("&");
48
+ return `${this._api.api}${scheme.VOCID}${endpoint}${paramString ? "?" + paramString : ""}`;
49
+ }
50
+ _getDataUrl(concept, { addFormatParameter = true } = {}) {
51
+ const scheme = _.get(concept, "inScheme[0]");
52
+ if (!concept || !concept.uri) {
53
+ throw new errors.InvalidOrMissingParameterError({ parameter: "concept", message: "Missing concept URI" });
54
+ }
55
+ return this._getApiUrl(scheme, "/data", addFormatParameter ? { format: "application/json" } : {});
56
+ }
57
+ async _getSchemeUri(scheme) {
58
+ this._approvedSchemes = this._approvedSchemes || [];
59
+ this._rejectedSchemes = this._rejectedSchemes || [];
60
+ let _scheme = this._approvedSchemes.find((s) => jskos.compare(scheme, s));
61
+ if (_scheme) {
62
+ return _scheme.uri;
63
+ }
64
+ if (this._rejectedSchemes.find((s) => jskos.compare(scheme, s))) {
65
+ return null;
66
+ }
67
+ const url = this._getApiUrl(scheme, "/");
68
+ const data = await this.axios({
69
+ method: "get",
70
+ url
71
+ });
72
+ const resultScheme = data.conceptschemes.find((s) => jskos.compare(s, scheme));
73
+ if (resultScheme) {
74
+ this._approvedSchemes.push({
75
+ uri: resultScheme.uri,
76
+ identifier: jskos.getAllUris(scheme)
77
+ });
78
+ return resultScheme.uri;
79
+ } else {
80
+ this._rejectedSchemes.push({
81
+ uri: scheme.uri,
82
+ identifier: scheme.identifier
83
+ });
84
+ return null;
85
+ }
86
+ }
87
+ _toJskosConcept(skosmosConcept, { concept, scheme, result, language } = {}) {
88
+ if (!skosmosConcept) {
89
+ return null;
90
+ }
91
+ concept = jskos.deepCopy(concept || {});
92
+ language = language || skosmosConcept.lang || "en";
93
+ concept.uri = skosmosConcept.uri;
94
+ if (scheme) {
95
+ concept.inScheme = [scheme];
96
+ }
97
+ let prefLabel = skosmosConcept.matchedPrefLabel || skosmosConcept.prefLabel || skosmosConcept.label;
98
+ if (_.isString(prefLabel)) {
99
+ _.set(concept, `prefLabel.${language}`, prefLabel);
100
+ } else {
101
+ if (prefLabel && !_.isArray(prefLabel)) {
102
+ prefLabel = [prefLabel];
103
+ }
104
+ for (let label of prefLabel || []) {
105
+ _.set(concept, `prefLabel.${label.lang}`, label.value);
106
+ }
107
+ }
108
+ let altLabel = skosmosConcept.altLabel;
109
+ if (_.isString(altLabel)) {
110
+ _.set(concept, `altLabel.${language}`, [altLabel]);
111
+ } else {
112
+ if (altLabel && !_.isArray(altLabel)) {
113
+ altLabel = [altLabel];
114
+ }
115
+ for (let label of altLabel || []) {
116
+ if (_.get(concept, `altLabel.${label.lang}`)) {
117
+ concept.altLabel[label.lang].push(label.value);
118
+ concept.altLabel[label.lang] = _.uniq(concept.altLabel[label.lang]);
119
+ } else {
120
+ _.set(concept, `altLabel.${label.lang}`, [label.value]);
121
+ }
122
+ }
123
+ }
124
+ const notation = skosmosConcept.notation || skosmosConcept["skos:notation"] || jskos.notation(concept);
125
+ if (notation) {
126
+ concept.notation = [notation.value || notation];
127
+ }
128
+ if (skosmosConcept.broader) {
129
+ if (!_.isArray(skosmosConcept.broader)) {
130
+ skosmosConcept.broader = [skosmosConcept.broader];
131
+ }
132
+ concept.broader = skosmosConcept.broader.map((concept2) => _.isString(concept2) ? { uri: concept2 } : concept2);
133
+ }
134
+ if (skosmosConcept.hasChildren === true) {
135
+ concept.narrower = [null];
136
+ } else if (skosmosConcept.hasChildren === false) {
137
+ concept.narrower = [];
138
+ }
139
+ if (skosmosConcept.type && !_.isArray(skosmosConcept.type)) {
140
+ skosmosConcept.type = [skosmosConcept.type];
141
+ }
142
+ concept.type = concept.type || [];
143
+ for (let type of skosmosConcept.type || []) {
144
+ if (!jskos.isValidUri(type)) {
145
+ continue;
146
+ }
147
+ const uriScheme = type.slice(0, type.indexOf(":"));
148
+ if (result && result["@context"] && result["@context"][uriScheme]) {
149
+ type = type.replace(uriScheme + ":", result["@context"][uriScheme]);
150
+ }
151
+ concept.type.push(type);
152
+ }
153
+ concept.type = _.uniq(concept.type);
154
+ if (!concept.type.length) {
155
+ concept.type = ["http://www.w3.org/2004/02/skos/core#Concept"];
156
+ }
157
+ return concept;
158
+ }
159
+ async getSchemes({ ...config }) {
160
+ const schemes = [];
161
+ for (let scheme of this.schemes || []) {
162
+ const url = this._getApiUrl(scheme, "/");
163
+ const data = await this.axios({
164
+ ...config,
165
+ method: "get",
166
+ url
167
+ });
168
+ const resultScheme = data.conceptschemes.find((s) => jskos.compare(s, scheme));
169
+ const label = resultScheme && (resultScheme.prefLabel || resultScheme.label || resultScheme.title);
170
+ if (label) {
171
+ _.set(scheme, `prefLabel.${this._language}`, label);
172
+ }
173
+ schemes.push(scheme);
174
+ this._approvedSchemes = this._approvedSchemes || [];
175
+ if (!this._approvedSchemes.find((s) => jskos.compare(scheme, s))) {
176
+ this._approvedSchemes.push({
177
+ uri: resultScheme.uri,
178
+ identifier: jskos.getAllUris(scheme)
179
+ });
180
+ }
181
+ }
182
+ return schemes;
183
+ }
184
+ async getTop({ scheme, ...config }) {
185
+ const url = this._getApiUrl(scheme, "/topConcepts");
186
+ const schemeUri = await this._getSchemeUri(scheme);
187
+ if (!schemeUri) {
188
+ throw new errors.InvalidOrMissingParameterError({ parameter: "scheme", message: "Missing or unsupported scheme or VOCID property on scheme" });
189
+ }
190
+ _.set(config, "params.scheme", schemeUri);
191
+ const response = await this.axios({
192
+ ...config,
193
+ method: "get",
194
+ url
195
+ });
196
+ const concepts = [];
197
+ for (let concept of response.topconcepts || []) {
198
+ const newConcept = this._toJskosConcept(concept, {
199
+ scheme,
200
+ language: this._language
201
+ });
202
+ newConcept.topConceptOf = [scheme];
203
+ concepts.push(newConcept);
204
+ }
205
+ return concepts;
206
+ }
207
+ async getConcepts({ concepts, ...config }) {
208
+ if (!_.isArray(concepts)) {
209
+ concepts = [concepts];
210
+ }
211
+ concepts = concepts.map((c) => ({ uri: c.uri, inScheme: c.inScheme }));
212
+ const newConcepts = [];
213
+ for (let concept of concepts) {
214
+ const url = this._getDataUrl(concept, { addFormatParameter: false });
215
+ if (!url) {
216
+ continue;
217
+ }
218
+ const result = await this.axios({
219
+ ...config,
220
+ method: "get",
221
+ url,
222
+ params: {
223
+ uri: concept.uri,
224
+ format: "application/json"
225
+ }
226
+ });
227
+ const resultConcept = result && result.graph && result.graph.find((c) => jskos.compare(c, concept));
228
+ if (resultConcept) {
229
+ const newConcept = this._toJskosConcept(resultConcept, { concept, result });
230
+ for (let type of ["broader", "narrower"]) {
231
+ let relatives = resultConcept[type] || newConcept[type];
232
+ if (relatives && !_.isArray(relatives)) {
233
+ relatives = [relatives];
234
+ }
235
+ if (!relatives) {
236
+ relatives = [];
237
+ }
238
+ newConcept[type] = relatives.map((r) => this._toJskosConcept(result.graph.find((c) => jskos.compare(c, r)), { scheme: concept.inScheme[0], result }));
239
+ }
240
+ newConcept.ancestors = [];
241
+ newConcepts.push(newConcept);
242
+ }
243
+ }
244
+ return newConcepts;
245
+ }
246
+ async getNarrower({ concept, ...config }) {
247
+ if (!concept || !concept.uri) {
248
+ throw new errors.InvalidOrMissingParameterError({ parameter: "concept" });
249
+ }
250
+ const scheme = concept.inScheme[0];
251
+ const url = this._getApiUrl(scheme, "/children");
252
+ _.set(config, "params.uri", concept.uri);
253
+ const response = await this.axios({
254
+ ...config,
255
+ method: "get",
256
+ url
257
+ });
258
+ const concepts = (response.narrower || []).map((c) => this._toJskosConcept(c, { scheme }));
259
+ return concepts;
260
+ }
261
+ async getAncestors({ concept, ...config }) {
262
+ if (!concept || !concept.uri) {
263
+ throw new errors.InvalidOrMissingParameterError({ parameter: "concept" });
264
+ }
265
+ const scheme = concept.inScheme[0];
266
+ const url = this._getApiUrl(scheme, "/broaderTransitive");
267
+ _.set(config, "params.uri", concept.uri);
268
+ const response = await this.axios({
269
+ ...config,
270
+ method: "get",
271
+ url
272
+ });
273
+ let ancestors = [];
274
+ let uri = concept.uri;
275
+ while (uri) {
276
+ if (uri != concept.uri) {
277
+ const ancestor = _.get(response, `broaderTransitive["${uri}"]`);
278
+ ancestors = [ancestor].concat(ancestors);
279
+ }
280
+ uri = _.get(response, `broaderTransitive["${uri}"].broader[0]`);
281
+ }
282
+ const concepts = ancestors.map((c) => this._toJskosConcept(c, { scheme })).filter((c) => c.uri != concept.uri);
283
+ return concepts;
284
+ }
285
+ async suggest(config) {
286
+ config._raw = true;
287
+ const concepts = await this.search(config);
288
+ const result = [config.search, [], [], []];
289
+ for (let concept of concepts) {
290
+ const notation = jskos.notation(concept);
291
+ const label = jskos.prefLabel(concept);
292
+ result[1].push((notation ? notation + " " : "") + label);
293
+ result[2].push("");
294
+ result[3].push(concept.uri);
295
+ }
296
+ if (concepts._totalCount != void 0) {
297
+ result._totalCount = concepts._totalCount;
298
+ } else {
299
+ result._totalCount = concepts.length;
300
+ }
301
+ return result;
302
+ }
303
+ async search({ search, scheme, limit, types = [], ...config }) {
304
+ const url = this._getApiUrl(scheme, "/search");
305
+ _.set(config, "params.query", `${search}*`);
306
+ _.set(config, "params.unique", 1);
307
+ _.set(config, "params.maxhits", limit || 100);
308
+ _.set(config, "params.type", types.join(" "));
309
+ const response = await this.axios({
310
+ ...config,
311
+ method: "get",
312
+ url
313
+ });
314
+ const concepts = (response.results || []).map((c) => this._toJskosConcept(c, { scheme }));
315
+ return concepts;
316
+ }
317
+ async getTypes({ scheme, ...config }) {
318
+ const url = this._getApiUrl(scheme, "/types");
319
+ const types = [];
320
+ const response = await this.axios({
321
+ ...config,
322
+ method: "get",
323
+ url
324
+ });
325
+ for (let type of response && response.types || []) {
326
+ if (type.uri == "http://www.w3.org/2004/02/skos/core#Concept") {
327
+ continue;
328
+ }
329
+ if (type.label) {
330
+ type.prefLabel = {
331
+ [response["@context"]["@language"]]: type.label
332
+ };
333
+ delete type.label;
334
+ }
335
+ types.push(type);
336
+ }
337
+ types._url = url;
338
+ return types;
339
+ }
340
+ }
341
+ SkosmosApiProvider.providerName = "SkosmosApi";
342
+ SkosmosApiProvider.providerType = "http://bartoc.org/api-type/skosmos";
343
+ export {
344
+ SkosmosApiProvider as default
345
+ };