cocoda-sdk 3.0.3 → 3.2.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
@@ -21,6 +21,7 @@
21
21
  - [Registry Methods - General](#registry-methods---general)
22
22
  - [Registry Methods - Concept Schemes](#registry-methods---concept-schemes)
23
23
  - [Registry Methods - Concepts](#registry-methods---concepts)
24
+ - [Registry Methods - Concordances](#registry-methods---concordances)
24
25
  - [Registry Methods - Mappings](#registry-methods---mappings)
25
26
  - [Registry Methods - Annotations](#registry-methods---annotations)
26
27
  - [Registry Methods - Various](#registry-methods---various)
@@ -164,6 +165,8 @@ The following providers are also exported, but have to be added via `cdk.addProv
164
165
  - `SkosmosApi` - access to concept schemes and concepts via a [Skosmos](https://github.com/NatLibFi/Skosmos) API
165
166
  - `LocApi` - access to concept schemes and concepts via the [Library of Congress Linked Data Service](https://id.loc.gov/)
166
167
  - **This integration is currently experimental and only supports LCSH and LCNAF.**
168
+ - `Skohub` - access to concept schemes and concepts via a [SkoHub Vocabs](https://blog.lobid.org/2019/09/27/presenting-skohub-vocabs.html)
169
+ - **This integration is currently experimental. Only vocabularies that use a [slash namespace pattern]([hash](https://www.w3.org/2001/sw/BestPractices/VM/http-examples/2006-01-18/#slash)) with dereferenceable URIs are supported.**
167
170
  - `ReconciliationApi` - access to mapping suggestions via a [OpenRefine Reconciliation API](https://github.com/OpenRefine/OpenRefine/wiki/Reconciliation-Service-API)
168
171
  - `OccurrencesApi` - access to concept occurrences via [occurrences-api](https://github.com/gbv/occurrences-api) (will be changed to [occurrences-server](https://github.com/gbv/occurrences-server) in the future)
169
172
  - `LabelSearchSuggestion` - access to mapping suggestions using other registries' search endpoints (using [jskos-server])
@@ -348,6 +351,23 @@ Please refer to the [documentation](https://gbv.github.io/cocoda-sdk/CocodaSDK.h
348
351
  - [ConceptApiProvider - suggest](https://gbv.github.io/cocoda-sdk/ConceptApiProvider.html#suggest)
349
352
  - [SkosmosApiProvider - suggest](https://gbv.github.io/cocoda-sdk/SkosmosApiProvider.html#suggest)
350
353
 
354
+ ### Registry Methods - Concordances
355
+
356
+ #### `registry.getConcordances`
357
+ - [MappingsApiProvider - getConcordances](https://gbv.github.io/cocoda-sdk/MappingsApiProvider.html#getConcordances)
358
+
359
+ #### `registry.postConcordance`
360
+ - [MappingsApiProvider - postConcordance](https://gbv.github.io/cocoda-sdk/MappingsApiProvider.html#postConcordance)
361
+
362
+ #### `registry.putConcordance`
363
+ - [MappingsApiProvider - putConcordance](https://gbv.github.io/cocoda-sdk/MappingsApiProvider.html#putConcordance)
364
+
365
+ #### `registry.patchConcordance`
366
+ - [MappingsApiProvider - patchConcordance](https://gbv.github.io/cocoda-sdk/MappingsApiProvider.html#patchConcordance)
367
+
368
+ #### `registry.deleteConcordance`
369
+ - [MappingsApiProvider - deleteConcordance](https://gbv.github.io/cocoda-sdk/MappingsApiProvider.html#deleteConcordance)
370
+
351
371
  ### Registry Methods - Mappings
352
372
 
353
373
  #### `registry.getMappings`
@@ -4,27 +4,20 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
8
7
  var __export = (target, all) => {
9
8
  for (var name in all)
10
9
  __defProp(target, name, { get: all[name], enumerable: true });
11
10
  };
12
- var __reExport = (target, module2, copyDefault, desc) => {
13
- if (module2 && typeof module2 === "object" || typeof module2 === "function") {
14
- for (let key of __getOwnPropNames(module2))
15
- if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default"))
16
- __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
16
  }
18
- return target;
17
+ return to;
19
18
  };
20
- var __toESM = (module2, isNodeMode) => {
21
- return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", !isNodeMode && module2 && module2.__esModule ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
22
- };
23
- var __toCommonJS = /* @__PURE__ */ ((cache) => {
24
- return (module2, temp) => {
25
- return cache && cache.get(module2) || (temp = __reExport(__markAsModule({}), module2, 1), cache && cache.set(module2, temp), temp);
26
- };
27
- })(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0);
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
21
 
29
22
  // src/index.js
30
23
  var src_exports = {};
@@ -38,11 +31,13 @@ __export(src_exports, {
38
31
  MappingsApiProvider: () => MappingsApiProvider,
39
32
  OccurrencesApiProvider: () => OccurrencesApiProvider,
40
33
  ReconciliationApiProvider: () => ReconciliationApiProvider,
34
+ SkohubProvider: () => SkohubProvider,
41
35
  SkosmosApiProvider: () => SkosmosApiProvider,
42
36
  addAllProviders: () => addAllProviders,
43
37
  cdk: () => cdk,
44
38
  errors: () => errors_exports
45
39
  });
40
+ module.exports = __toCommonJS(src_exports);
46
41
 
47
42
  // src/errors/index.js
48
43
  var errors_exports = {};
@@ -114,7 +109,7 @@ var import_omit = __toESM(require("lodash/omit.js"), 1);
114
109
  var import_concat = __toESM(require("lodash/concat.js"), 1);
115
110
 
116
111
  // src/lib/CocodaSDK.js
117
- var import_jskos_tools10 = __toESM(require("jskos-tools"), 1);
112
+ var import_jskos_tools11 = __toESM(require("jskos-tools"), 1);
118
113
 
119
114
  // src/providers/index.js
120
115
  var providers_exports = {};
@@ -127,6 +122,7 @@ __export(providers_exports, {
127
122
  MappingsApiProvider: () => MappingsApiProvider,
128
123
  OccurrencesApiProvider: () => OccurrencesApiProvider,
129
124
  ReconciliationApiProvider: () => ReconciliationApiProvider,
125
+ SkohubProvider: () => SkohubProvider,
130
126
  SkosmosApiProvider: () => SkosmosApiProvider
131
127
  });
132
128
 
@@ -336,10 +332,12 @@ var BaseProvider = class {
336
332
  this._config = {};
337
333
  this.setRetryConfig();
338
334
  this.axios.interceptors.request.use((config) => {
339
- const language = import_uniq.default([].concat(import_get.default(config, "params.language", "").split(","), this.languages, this._defaultLanguages).filter((lang) => lang != "")).join(",");
340
- import_set.default(config, "params.language", language);
341
- if (this.has.auth && this._auth.bearerToken && !import_get.default(config, "headers.Authorization")) {
342
- import_set.default(config, "headers.Authorization", `Bearer ${this._auth.bearerToken}`);
335
+ if (!config._skipAdditionalParameters) {
336
+ const language = import_uniq.default([].concat(import_get.default(config, "params.language", "").split(","), this.languages, this._defaultLanguages).filter((lang) => lang != "")).join(",");
337
+ import_set.default(config, "params.language", language);
338
+ if (this.has.auth && this._auth.bearerToken && !import_get.default(config, "headers.Authorization")) {
339
+ import_set.default(config, "headers.Authorization", `Bearer ${this._auth.bearerToken}`);
340
+ }
343
341
  }
344
342
  if (config.url.startsWith("http:") && typeof window !== "undefined" && window.location.protocol == "https:") {
345
343
  throw new import_axios.default.Cancel("Can't call http API from https.");
@@ -1072,7 +1070,13 @@ var MappingsApiProvider = class extends BaseProvider {
1072
1070
  this.has.mappings.delete = !!import_get.default(this._config, "mappings.delete");
1073
1071
  this.has.mappings.anonymous = !!import_get.default(this._config, "mappings.anonymous");
1074
1072
  }
1075
- this.has.concordances = !!this._api.concordances;
1073
+ this.has.concordances = this._api.concordances ? {} : false;
1074
+ if (this.has.concordances) {
1075
+ this.has.concordances.read = !!import_get.default(this._config, "concordances.read");
1076
+ this.has.concordances.create = !!import_get.default(this._config, "concordances.create");
1077
+ this.has.concordances.update = !!import_get.default(this._config, "concordances.update");
1078
+ this.has.concordances.delete = !!import_get.default(this._config, "concordances.delete");
1079
+ }
1076
1080
  this.has.annotations = this._api.annotations ? {} : false;
1077
1081
  if (this.has.annotations) {
1078
1082
  this.has.annotations.read = !!import_get.default(this._config, "annotations.read");
@@ -1108,7 +1112,7 @@ var MappingsApiProvider = class extends BaseProvider {
1108
1112
  throw error;
1109
1113
  }
1110
1114
  }
1111
- async getMappings({ from, fromScheme, to, toScheme, creator, type, partOf, offset, limit, direction, mode, identifier, sort, order, ...config }) {
1115
+ async getMappings({ from, fromScheme, to, toScheme, creator, type, partOf, offset, limit, direction, mode, identifier, cardinality, annotatedBy, annotatedFor, annotatedWith, sort, order, ...config }) {
1112
1116
  let params = {}, url = this._api.mappings;
1113
1117
  if (from) {
1114
1118
  params.from = import_isString.default(from) ? from : from.uri;
@@ -1140,6 +1144,18 @@ var MappingsApiProvider = class extends BaseProvider {
1140
1144
  if (direction) {
1141
1145
  params.direction = direction;
1142
1146
  }
1147
+ if (cardinality) {
1148
+ params.cardinality = cardinality;
1149
+ }
1150
+ if (annotatedBy) {
1151
+ params.annotatedBy = annotatedBy;
1152
+ }
1153
+ if (annotatedFor) {
1154
+ params.annotatedFor = annotatedFor;
1155
+ }
1156
+ if (annotatedWith) {
1157
+ params.annotatedWith = annotatedWith;
1158
+ }
1143
1159
  if (mode) {
1144
1160
  params.mode = mode;
1145
1161
  }
@@ -1205,8 +1221,6 @@ var MappingsApiProvider = class extends BaseProvider {
1205
1221
  if (!mapping) {
1206
1222
  throw new InvalidOrMissingParameterError({ parameter: "mapping" });
1207
1223
  }
1208
- mapping = import_jskos_tools3.default.minifyMapping(mapping);
1209
- mapping = import_jskos_tools3.default.addMappingIdentifiers(mapping);
1210
1224
  const uri = mapping.uri;
1211
1225
  if (!uri || !uri.startsWith(this._api.mappings)) {
1212
1226
  throw new InvalidOrMissingParameterError({ parameter: "mapping", message: "URI doesn't seem to be part of this registry." });
@@ -1215,7 +1229,7 @@ var MappingsApiProvider = class extends BaseProvider {
1215
1229
  ...config,
1216
1230
  method: "patch",
1217
1231
  url: uri,
1218
- data: mapping,
1232
+ data: import_omit.default(mapping, "uri"),
1219
1233
  params: {
1220
1234
  ...this._defaultParams,
1221
1235
  ...config.params || {}
@@ -1298,6 +1312,74 @@ var MappingsApiProvider = class extends BaseProvider {
1298
1312
  url: this._api.concordances
1299
1313
  });
1300
1314
  }
1315
+ async postConcordance({ concordance, ...config }) {
1316
+ if (!concordance) {
1317
+ throw new InvalidOrMissingParameterError({ parameter: "concordance" });
1318
+ }
1319
+ return this.axios({
1320
+ ...config,
1321
+ method: "post",
1322
+ url: this._api.concordances,
1323
+ data: concordance,
1324
+ params: {
1325
+ ...this._defaultParams,
1326
+ ...config.params || {}
1327
+ }
1328
+ });
1329
+ }
1330
+ async putConcordance({ concordance, ...config }) {
1331
+ if (!concordance) {
1332
+ throw new InvalidOrMissingParameterError({ parameter: "concordance" });
1333
+ }
1334
+ const uri = concordance.uri;
1335
+ if (!uri || !uri.startsWith(this._api.concordances)) {
1336
+ throw new InvalidOrMissingParameterError({ parameter: "concordance", message: "URI doesn't seem to be part of this registry." });
1337
+ }
1338
+ return this.axios({
1339
+ ...config,
1340
+ method: "put",
1341
+ url: uri,
1342
+ data: concordance,
1343
+ params: {
1344
+ ...this._defaultParams,
1345
+ ...config.params || {}
1346
+ }
1347
+ });
1348
+ }
1349
+ async patchConcordance({ concordance, ...config }) {
1350
+ if (!concordance) {
1351
+ throw new InvalidOrMissingParameterError({ parameter: "concordance" });
1352
+ }
1353
+ const uri = concordance.uri;
1354
+ if (!uri || !uri.startsWith(this._api.concordances)) {
1355
+ throw new InvalidOrMissingParameterError({ parameter: "concordance", message: "URI doesn't seem to be part of this registry." });
1356
+ }
1357
+ return this.axios({
1358
+ ...config,
1359
+ method: "patch",
1360
+ url: uri,
1361
+ data: import_omit.default(concordance, "uri"),
1362
+ params: {
1363
+ ...this._defaultParams,
1364
+ ...config.params || {}
1365
+ }
1366
+ });
1367
+ }
1368
+ async deleteConcordance({ concordance, ...config }) {
1369
+ if (!concordance) {
1370
+ throw new InvalidOrMissingParameterError({ parameter: "concordance" });
1371
+ }
1372
+ const uri = concordance.uri;
1373
+ if (!uri || !uri.startsWith(this._api.concordances)) {
1374
+ throw new InvalidOrMissingParameterError({ parameter: "concordance", message: "URI doesn't seem to be part of this registry." });
1375
+ }
1376
+ await this.axios({
1377
+ ...config,
1378
+ method: "delete",
1379
+ url: uri
1380
+ });
1381
+ return true;
1382
+ }
1301
1383
  };
1302
1384
  MappingsApiProvider.providerName = "MappingsApi";
1303
1385
  MappingsApiProvider.stored = true;
@@ -2517,6 +2599,229 @@ var LocApiProvider = class extends BaseProvider {
2517
2599
  LocApiProvider.providerName = "LocApi";
2518
2600
  LocApiProvider.providerType = "http://bartoc.org/api-type/loc";
2519
2601
 
2602
+ // src/providers/skohub-provider.js
2603
+ var import_jskos_tools10 = __toESM(require("jskos-tools"), 1);
2604
+ var import_flexsearch = __toESM(require("flexsearch"), 1);
2605
+ function decodeUnicode(text) {
2606
+ return text.replace(/\\u[\dA-F]{4}/gi, function(match) {
2607
+ return String.fromCharCode(parseInt(match.replace(/\\u/g, ""), 16));
2608
+ });
2609
+ }
2610
+ var SkohubProvider = class extends BaseProvider {
2611
+ _prepare() {
2612
+ this.has.schemes = true;
2613
+ this.has.top = true;
2614
+ this.has.data = true;
2615
+ this.has.concepts = true;
2616
+ this.has.narrower = true;
2617
+ this.has.ancestors = true;
2618
+ this.has.suggest = true;
2619
+ this.has.search = true;
2620
+ listOfCapabilities.filter((c) => !this.has[c]).forEach((c) => {
2621
+ this.has[c] = false;
2622
+ });
2623
+ }
2624
+ _setup() {
2625
+ this._index = {};
2626
+ this._conceptCache = {};
2627
+ this._schemeCache = {};
2628
+ }
2629
+ static _registryConfigForBartocApiConfig({ url, scheme } = {}) {
2630
+ if (!url || !scheme) {
2631
+ return null;
2632
+ }
2633
+ const newScheme = { uri: url, identifier: import_jskos_tools10.default.getAllUris(scheme).filter((uri) => uri !== url) };
2634
+ return { schemes: [newScheme] };
2635
+ }
2636
+ async _loadScheme({ scheme, ...config }) {
2637
+ let uris = import_jskos_tools10.default.getAllUris(scheme);
2638
+ for (let uri2 of uris) {
2639
+ if (this._schemeCache[uri2]) {
2640
+ return this._schemeCache[uri2];
2641
+ }
2642
+ }
2643
+ const schemeFromList = this.schemes.find((s) => import_jskos_tools10.default.compare(s, scheme));
2644
+ if (!schemeFromList || !schemeFromList.uri) {
2645
+ throw new InvalidRequestError({ message: `Tried to load unsupported scheme (${scheme && scheme.uri})` });
2646
+ }
2647
+ const uri = schemeFromList.uri;
2648
+ uris = import_uniq.default(uris.concat(import_jskos_tools10.default.getAllUris(schemeFromList)));
2649
+ let postfix = ".json";
2650
+ if (uri.endsWith("/")) {
2651
+ postfix = "index.json";
2652
+ }
2653
+ const data = await this.axios({ ...config, url: `${uri}${postfix}`, _skipAdditionalParameters: true });
2654
+ if (data.id !== uri) {
2655
+ throw new InvalidRequestError({ message: "Skohub URL did not return expected concept scheme" });
2656
+ }
2657
+ const { title, preferredNamespaceUri, hasTopConcept, description } = data;
2658
+ scheme = { uri, identifier: uris.filter((u) => u !== uri) };
2659
+ scheme.prefLabel = title;
2660
+ Object.keys(scheme.prefLabel || {}).forEach((key) => {
2661
+ scheme.prefLabel[key] = decodeUnicode(scheme.prefLabel[key]);
2662
+ });
2663
+ scheme.namespace = preferredNamespaceUri;
2664
+ scheme.topConcepts = (hasTopConcept || []).map((c) => this._toJskosConcept(c));
2665
+ scheme.concepts = [null];
2666
+ if (description) {
2667
+ scheme.definition = description;
2668
+ Object.keys(scheme.definition).forEach((key) => {
2669
+ scheme.definition[key] = [decodeUnicode(scheme.definition[key])];
2670
+ });
2671
+ }
2672
+ for (let key of Object.keys(scheme).filter((key2) => !scheme[key2])) {
2673
+ delete scheme[key];
2674
+ }
2675
+ for (let uri2 of uris) {
2676
+ this._schemeCache[uri2] = scheme;
2677
+ }
2678
+ return scheme;
2679
+ }
2680
+ async _loadConcept({ uri, ...config }) {
2681
+ if (this._conceptCache[uri]) {
2682
+ return this._conceptCache[uri];
2683
+ }
2684
+ try {
2685
+ const data = await this.axios({ ...config, url: `${uri}.json`, _skipAdditionalParameters: true });
2686
+ if (data.id !== uri) {
2687
+ throw new InvalidRequestError({ message: "Skohub URL did not return expected concept URI" });
2688
+ }
2689
+ const concept = this._toJskosConcept(data);
2690
+ this._conceptCache[uri] = concept;
2691
+ return concept;
2692
+ } catch (error) {
2693
+ return null;
2694
+ }
2695
+ }
2696
+ _toJskosConcept(data) {
2697
+ const concept = { uri: data.id };
2698
+ concept.prefLabel = data.prefLabel;
2699
+ Object.keys(concept.prefLabel || {}).forEach((key) => {
2700
+ concept.prefLabel[key] = decodeUnicode(concept.prefLabel[key]);
2701
+ });
2702
+ concept.narrower = (data.narrower || []).map((c) => this._toJskosConcept(c));
2703
+ concept.notation = data.notation || [];
2704
+ if (data.broader && data.broader.id) {
2705
+ concept.broader = [{ uri: data.broader.id }];
2706
+ }
2707
+ if (data.inScheme && data.inScheme.id) {
2708
+ concept.inScheme = [{ uri: data.inScheme.id }];
2709
+ }
2710
+ if (data.scopeNote) {
2711
+ concept.scopeNote = data.scopeNote;
2712
+ Object.keys(concept.scopeNote).forEach((key) => {
2713
+ concept.scopeNote[key] = [decodeUnicode(concept.scopeNote[key])];
2714
+ });
2715
+ }
2716
+ return concept;
2717
+ }
2718
+ async getSchemes({ ...config }) {
2719
+ return Promise.all(this.schemes.map((scheme) => this._loadScheme({ ...config, scheme })));
2720
+ }
2721
+ async getTop({ scheme, ...config }) {
2722
+ if (!scheme || !scheme.uri) {
2723
+ throw new InvalidOrMissingParameterError({ parameter: "scheme", message: "Missing scheme URI" });
2724
+ }
2725
+ scheme = await this._loadScheme({ scheme, ...config });
2726
+ return scheme.topConcepts || [];
2727
+ }
2728
+ async getConcepts({ concepts, ...config }) {
2729
+ if (!import_isArray.default(concepts)) {
2730
+ concepts = [concepts];
2731
+ }
2732
+ return (await Promise.all(concepts.map(({ uri }) => this._loadConcept({ ...config, uri })))).filter(Boolean);
2733
+ }
2734
+ async getAncestors({ concept, ...config }) {
2735
+ if (!concept || !concept.uri) {
2736
+ throw new InvalidOrMissingParameterError({ parameter: "concept" });
2737
+ }
2738
+ if (concept.ancestors && concept.ancestors[0] !== null) {
2739
+ return concept.ancestors;
2740
+ }
2741
+ concept = await this._loadConcept({ ...config, uri: concept.uri });
2742
+ if (!concept || !concept.broader || !concept.broader.length) {
2743
+ return [];
2744
+ }
2745
+ const broader = concept.broader[0];
2746
+ return [broader].concat(await this.getAncestors({ concept: broader, ...config })).map((c) => ({ uri: c.uri }));
2747
+ }
2748
+ async getNarrower({ concept, ...config }) {
2749
+ if (!concept || !concept.uri) {
2750
+ throw new InvalidOrMissingParameterError({ parameter: "concept" });
2751
+ }
2752
+ if (concept.narrower && concept.narrower[0] !== null) {
2753
+ return concept.narrower;
2754
+ }
2755
+ concept = await this._loadConcept({ ...config, uri: concept.uri });
2756
+ return concept.narrower;
2757
+ }
2758
+ async search({ search, scheme, limit = 100 }) {
2759
+ scheme = await this._loadScheme({ scheme });
2760
+ if (!scheme || !scheme.uri) {
2761
+ throw new InvalidOrMissingParameterError({ parameter: "scheme" });
2762
+ }
2763
+ if (!search) {
2764
+ throw new InvalidOrMissingParameterError({ parameter: "search" });
2765
+ }
2766
+ let index;
2767
+ if (!this._index[scheme.uri]) {
2768
+ this._index[scheme.uri] = {};
2769
+ }
2770
+ for (const lang of [""].concat(this.languages)) {
2771
+ if (this._index[scheme.uri][lang]) {
2772
+ index = this._index[scheme.uri][lang];
2773
+ break;
2774
+ }
2775
+ if (this._index[scheme.uri][lang] === null) {
2776
+ continue;
2777
+ }
2778
+ try {
2779
+ let postfix = lang ? `.${lang}.index` : ".index";
2780
+ if (scheme.uri.endsWith("/")) {
2781
+ postfix = `index${postfix}`;
2782
+ }
2783
+ const data = await this.axios({ url: `${scheme.uri}${postfix}`, _skipAdditionalParameters: true });
2784
+ if (data.length < 100) {
2785
+ this._index[scheme.uri][lang] = null;
2786
+ continue;
2787
+ }
2788
+ index = import_flexsearch.default.create();
2789
+ index.import(data);
2790
+ this._index[scheme.uri][lang] = index;
2791
+ break;
2792
+ } catch (error) {
2793
+ this._index[scheme.uri][lang] = null;
2794
+ }
2795
+ }
2796
+ if (!index) {
2797
+ throw new InvalidRequestError({ message: "Could not find search index for any of the available languages " + this.languages.join(",") });
2798
+ }
2799
+ const result = index.search(search);
2800
+ const concepts = await this.getConcepts({ concepts: result.map((uri) => ({ uri })) });
2801
+ return concepts.slice(0, limit);
2802
+ }
2803
+ async suggest(config) {
2804
+ config._raw = true;
2805
+ const concepts = await this.search(config);
2806
+ const result = [config.search, [], [], []];
2807
+ for (let concept of concepts) {
2808
+ const notation = import_jskos_tools10.default.notation(concept);
2809
+ const label = import_jskos_tools10.default.prefLabel(concept);
2810
+ result[1].push((notation ? notation + " " : "") + label);
2811
+ result[2].push("");
2812
+ result[3].push(concept.uri);
2813
+ }
2814
+ if (concepts._totalCount != void 0) {
2815
+ result._totalCount = concepts._totalCount;
2816
+ } else {
2817
+ result._totalCount = concepts.length;
2818
+ }
2819
+ return result;
2820
+ }
2821
+ };
2822
+ SkohubProvider.providerName = "Skohub";
2823
+ SkohubProvider.providerType = "http://bartoc.org/api-type/skohub";
2824
+
2520
2825
  // src/lib/CocodaSDK.js
2521
2826
  var providers = {
2522
2827
  [BaseProvider.providerName]: BaseProvider,
@@ -2629,7 +2934,8 @@ var CocodaSDK = class {
2629
2934
  timer: null,
2630
2935
  result: null,
2631
2936
  error: null,
2632
- isPaused: false
2937
+ isPaused: false,
2938
+ interval
2633
2939
  };
2634
2940
  const handleResult = (result) => {
2635
2941
  const previousResult = repeat.result;
@@ -2649,7 +2955,7 @@ var CocodaSDK = class {
2649
2955
  }
2650
2956
  repeat.timer = setTimeout(() => {
2651
2957
  toCall();
2652
- }, interval);
2958
+ }, repeat.interval);
2653
2959
  };
2654
2960
  const call = () => asyncFunc().then(handleResult).catch(handleError).then(() => repeatIfNecessary(call));
2655
2961
  const setup = (_callImmediately = callImmediately) => {
@@ -2672,7 +2978,7 @@ var CocodaSDK = class {
2672
2978
  } else {
2673
2979
  setTimeout(() => {
2674
2980
  repeat.timer && clearTimeout(repeat.timer);
2675
- }, interval);
2981
+ }, repeat.interval);
2676
2982
  }
2677
2983
  },
2678
2984
  get isPaused() {
@@ -2683,6 +2989,12 @@ var CocodaSDK = class {
2683
2989
  },
2684
2990
  get hasErrored() {
2685
2991
  return !!repeat.error;
2992
+ },
2993
+ get interval() {
2994
+ return repeat.interval;
2995
+ },
2996
+ set interval(value) {
2997
+ repeat.interval = value;
2686
2998
  }
2687
2999
  };
2688
3000
  }
@@ -2695,7 +3007,7 @@ var CocodaSDK = class {
2695
3007
  scheme._registry = registry;
2696
3008
  scheme.__DETAILSLOADED__ = 1;
2697
3009
  scheme.type = scheme.type || ["http://www.w3.org/2004/02/skos/core#ConceptScheme"];
2698
- let otherScheme = schemes.find((s) => import_jskos_tools10.default.compare(s, scheme)), prio, otherPrio, override = false;
3010
+ let otherScheme = schemes.find((s) => import_jskos_tools11.default.compare(s, scheme)), prio, otherPrio, override = false;
2699
3011
  if (otherScheme) {
2700
3012
  prio = this.config.registries.indexOf(registry);
2701
3013
  if (prio != -1) {
@@ -2717,19 +3029,19 @@ var CocodaSDK = class {
2717
3029
  }
2718
3030
  if (!otherScheme || override) {
2719
3031
  if (override) {
2720
- let otherSchemeIndex = schemes.findIndex((s) => import_jskos_tools10.default.compare(s, otherScheme));
3032
+ let otherSchemeIndex = schemes.findIndex((s) => import_jskos_tools11.default.compare(s, otherScheme));
2721
3033
  if (otherSchemeIndex != -1) {
2722
3034
  schemes.splice(otherSchemeIndex, 1);
2723
3035
  }
2724
- scheme = import_jskos_tools10.default.merge(scheme, import_omit.default(otherScheme, ["concepts", "topConcepts"]), { mergeUris: true, skipPaths: ["_registry"] });
3036
+ scheme = import_jskos_tools11.default.merge(scheme, import_omit.default(otherScheme, ["concepts", "topConcepts"]), { mergeUris: true, skipPaths: ["_registry"] });
2725
3037
  }
2726
3038
  scheme._registry = registry;
2727
3039
  schemes.push(scheme);
2728
3040
  } else {
2729
- const index = schemes.findIndex((s) => import_jskos_tools10.default.compare(s, scheme));
3041
+ const index = schemes.findIndex((s) => import_jskos_tools11.default.compare(s, scheme));
2730
3042
  if (index != -1) {
2731
3043
  const otherSchemeRegistry = schemes[index]._registry;
2732
- schemes[index] = import_jskos_tools10.default.merge(schemes[index], import_omit.default(scheme, ["concepts", "topConcepts"]), { mergeUris: true, skipPaths: ["_registry"] });
3044
+ schemes[index] = import_jskos_tools11.default.merge(schemes[index], import_omit.default(scheme, ["concepts", "topConcepts"]), { mergeUris: true, skipPaths: ["_registry"] });
2733
3045
  schemes[index]._registry = otherSchemeRegistry;
2734
3046
  }
2735
3047
  }
@@ -2751,7 +3063,7 @@ var CocodaSDK = class {
2751
3063
  scheme._registry = newRegistry;
2752
3064
  }
2753
3065
  });
2754
- return import_jskos_tools10.default.sortSchemes(schemes.filter(Boolean));
3066
+ return import_jskos_tools11.default.sortSchemes(schemes.filter(Boolean));
2755
3067
  }
2756
3068
  registryForScheme(scheme) {
2757
3069
  let registry = scheme._registry;
@@ -2762,7 +3074,7 @@ var CocodaSDK = class {
2762
3074
  const url = config.url;
2763
3075
  if (registryCache[url]) {
2764
3076
  const registry2 = registryCache[url];
2765
- if (Array.isArray(registry2._jskos.schemes) && !import_jskos_tools10.default.isContainedIn(scheme, registry2._jskos.schemes)) {
3077
+ if (Array.isArray(registry2._jskos.schemes) && !import_jskos_tools11.default.isContainedIn(scheme, registry2._jskos.schemes)) {
2766
3078
  registry2._jskos.schemes.push(scheme);
2767
3079
  }
2768
3080
  return registry2;
@@ -2798,7 +3110,6 @@ var cdk = new CocodaSDK();
2798
3110
  function addAllProviders(_cdk) {
2799
3111
  Object.values(providers_exports).forEach((provider) => (_cdk || cdk).addProvider(provider));
2800
3112
  }
2801
- module.exports = __toCommonJS(src_exports);
2802
3113
  // Annotate the CommonJS export names for ESM import in node:
2803
3114
  0 && (module.exports = {
2804
3115
  BaseProvider,
@@ -2810,6 +3121,7 @@ module.exports = __toCommonJS(src_exports);
2810
3121
  MappingsApiProvider,
2811
3122
  OccurrencesApiProvider,
2812
3123
  ReconciliationApiProvider,
3124
+ SkohubProvider,
2813
3125
  SkosmosApiProvider,
2814
3126
  addAllProviders,
2815
3127
  cdk,