cocoda-sdk 2.0.13 → 3.0.2

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.
@@ -21,6 +21,7 @@ const providers = {
21
21
  };
22
22
  providers.addProvider(ConceptApiProvider);
23
23
  providers.addProvider(MappingsApiProvider);
24
+ const registryCache = {};
24
25
  class CocodaSDK {
25
26
  constructor(config) {
26
27
  this.config = config;
@@ -173,9 +174,10 @@ class CocodaSDK {
173
174
  async getSchemes(config = {}) {
174
175
  let schemes = [], promises = [];
175
176
  for (let registry of this.config.registries) {
176
- if (registry.has.schemes) {
177
+ if (registry.has.schemes !== false) {
177
178
  let promise = registry.getSchemes(config).then((results) => {
178
179
  for (let scheme of results) {
180
+ const currentSchemeRegistry = scheme._registry;
179
181
  scheme.__DETAILSLOADED__ = 1;
180
182
  scheme.type = scheme.type || ["http://www.w3.org/2004/02/skos/core#ConceptScheme"];
181
183
  let otherScheme = schemes.find((s) => jskos.compare(s, scheme)), prio, otherPrio, override = false;
@@ -206,14 +208,14 @@ class CocodaSDK {
206
208
  }
207
209
  scheme = jskos.merge(scheme, _.omit(otherScheme, ["concepts", "topConcepts"]), { mergeUris: true, skipPaths: ["_registry"] });
208
210
  }
209
- scheme._registry = registry;
211
+ scheme._registry = currentSchemeRegistry;
210
212
  schemes.push(scheme);
211
213
  } else {
212
- let index = schemes.findIndex((s) => jskos.compare(s, scheme));
214
+ const index = schemes.findIndex((s) => jskos.compare(s, scheme));
213
215
  if (index != -1) {
214
- let registry2 = schemes[index]._registry;
216
+ const otherSchemeRegistry = schemes[index]._registry;
215
217
  schemes[index] = jskos.merge(schemes[index], _.omit(scheme, ["concepts", "topConcepts"]), { mergeUris: true, skipPaths: ["_registry"] });
216
- schemes[index]._registry = registry2;
218
+ schemes[index]._registry = otherSchemeRegistry;
217
219
  }
218
220
  }
219
221
  }
@@ -232,22 +234,34 @@ class CocodaSDK {
232
234
  return registry;
233
235
  }
234
236
  for (let { type, ...config } of scheme.API || []) {
235
- const provider = Object.values(providers).find((p) => p.providerType === type);
236
- if (!provider || !provider._registryConfigForBartocApiConfig) {
237
- continue;
238
- }
239
- const providerName = provider.providerName;
240
- config.scheme = scheme;
241
- config = providers[providerName]._registryConfigForBartocApiConfig(config);
242
- if (!config) {
243
- continue;
244
- }
245
- config.provider = providerName;
246
- try {
247
- registry = this.initializeRegistry(config);
248
- return registry;
249
- } catch (error) {
250
- continue;
237
+ const url = config.url;
238
+ if (registryCache[url]) {
239
+ const registry2 = registryCache[url];
240
+ if (Array.isArray(registry2._jskos.schemes) && !jskos.isContainedIn(scheme, registry2._jskos.schemes)) {
241
+ registry2._jskos.schemes.push(scheme);
242
+ }
243
+ return registry2;
244
+ } else {
245
+ const provider = Object.values(providers).find((p) => p.providerType === type);
246
+ if (!provider || !provider._registryConfigForBartocApiConfig) {
247
+ continue;
248
+ }
249
+ const providerName = provider.providerName;
250
+ config.scheme = scheme;
251
+ config = providers[providerName]._registryConfigForBartocApiConfig(config);
252
+ if (!config) {
253
+ continue;
254
+ }
255
+ config.provider = providerName;
256
+ try {
257
+ registry = this.initializeRegistry(config);
258
+ if (registry) {
259
+ registryCache[url] = registry;
260
+ return registry;
261
+ }
262
+ } catch (error) {
263
+ continue;
264
+ }
251
265
  }
252
266
  }
253
267
  return null;
@@ -20,7 +20,7 @@ class BaseProvider {
20
20
  this._repeating = [];
21
21
  this._api = {
22
22
  status: registry.status,
23
- schemes: registry.schemes,
23
+ schemes: Array.isArray(registry.schemes) ? void 0 : registry.schemes,
24
24
  top: registry.top,
25
25
  data: registry.data,
26
26
  concepts: registry.concepts,
@@ -283,6 +283,9 @@ class BaseProvider {
283
283
  return jskos.isContainedIn(scheme, schemes);
284
284
  }
285
285
  adjustConcept(concept) {
286
+ if (!concept || concept.__SAVED__) {
287
+ return concept;
288
+ }
286
289
  concept._getNarrower = (config) => {
287
290
  return this.getNarrower({ ...config, concept });
288
291
  };
@@ -307,7 +310,20 @@ class BaseProvider {
307
310
  return registries;
308
311
  }
309
312
  adjustScheme(scheme) {
310
- scheme._registry = this.cdk && this.cdk.registryForScheme(scheme) || this;
313
+ if (!scheme || scheme.__SAVED__) {
314
+ return scheme;
315
+ }
316
+ const previousRegistry = scheme._registry;
317
+ scheme._registry = this.cdk && this.cdk.registryForScheme(scheme);
318
+ if (!scheme._registry || previousRegistry === scheme._registry) {
319
+ scheme._registry = previousRegistry || this;
320
+ } else {
321
+ ["concepts", "topConcepts"].forEach((key) => {
322
+ if (Array.isArray(scheme[key]) && (scheme[key].length === 0 || scheme[key][0] === null)) {
323
+ delete scheme[key];
324
+ }
325
+ });
326
+ }
311
327
  if (scheme._registry) {
312
328
  scheme._getTop = (config) => {
313
329
  return scheme._registry.getTop({ ...config, scheme });
@@ -18,6 +18,9 @@ class ConceptApiProvider extends BaseProvider {
18
18
  this.has.suggest = true;
19
19
  this.has.search = true;
20
20
  this.has.auth = true;
21
+ utils.listOfCapabilities.filter((c) => !this.has[c]).forEach((c) => {
22
+ this.has[c] = false;
23
+ });
21
24
  }
22
25
  _setup() {
23
26
  if (this._api.api) {
@@ -39,6 +42,9 @@ class ConceptApiProvider extends BaseProvider {
39
42
  }
40
43
  }
41
44
  this.has.schemes = !!this._api.schemes;
45
+ if (!this.has.schemes && Array.isArray(this.schemes)) {
46
+ this.has.schemes = true;
47
+ }
42
48
  this.has.top = !!this._api.top;
43
49
  this.has.data = !!this._api.data;
44
50
  this.has.concepts = !!this._api.concepts || this.has.data;
@@ -49,15 +55,16 @@ class ConceptApiProvider extends BaseProvider {
49
55
  this.has.search = !!this._api.search;
50
56
  this.has.auth = _.get(this._config, "auth.key") != null;
51
57
  this._defaultParams = {
52
- properties: "uri,prefLabel,notation,inScheme"
58
+ properties: "+created,issued,modified,editorialNote,scopeNote"
53
59
  };
54
60
  }
55
- static _registryConfigForBartocApiConfig({ url } = {}) {
56
- if (!url) {
61
+ static _registryConfigForBartocApiConfig({ url, scheme } = {}) {
62
+ if (!url || !scheme) {
57
63
  return null;
58
64
  }
59
65
  return {
60
- api: url
66
+ api: url,
67
+ schemes: [scheme]
61
68
  };
62
69
  }
63
70
  async _getSchemeUri(scheme) {
@@ -70,7 +77,9 @@ class ConceptApiProvider extends BaseProvider {
70
77
  if (this._rejectedSchemes.find((s) => jskos.compare(scheme, s))) {
71
78
  return null;
72
79
  }
73
- const schemes = await this.getSchemes({ uri: jskos.getAllUris(scheme) });
80
+ const schemes = await this.getSchemes({ params: {
81
+ uri: jskos.getAllUris(scheme).join("|")
82
+ } });
74
83
  const resultScheme = schemes.find((s) => jskos.compare(s, scheme));
75
84
  if (resultScheme) {
76
85
  this._approvedSchemes.push({
@@ -88,11 +97,11 @@ class ConceptApiProvider extends BaseProvider {
88
97
  }
89
98
  async getSchemes(config) {
90
99
  if (!this._api.schemes) {
100
+ if (Array.isArray(this.schemes)) {
101
+ return this.schemes;
102
+ }
91
103
  throw new errors.MissingApiUrlError();
92
104
  }
93
- if (Array.isArray(this._api.schemes)) {
94
- return this._api.schemes;
95
- }
96
105
  const schemes = await this.axios({
97
106
  ...config,
98
107
  method: "get",
@@ -103,8 +112,8 @@ class ConceptApiProvider extends BaseProvider {
103
112
  ...config.params || {}
104
113
  }
105
114
  });
106
- if (Array.isArray(this._jskos.schemes)) {
107
- return utils.withCustomProps(schemes.filter((s) => jskos.isContainedIn(s, this._jskos.schemes)), schemes);
115
+ if (Array.isArray(this.schemes)) {
116
+ return utils.withCustomProps(schemes.filter((s) => jskos.isContainedIn(s, this.schemes)), schemes);
108
117
  } else {
109
118
  return schemes;
110
119
  }
@@ -136,7 +145,7 @@ class ConceptApiProvider extends BaseProvider {
136
145
  });
137
146
  }
138
147
  async getConcepts({ concepts, ...config }) {
139
- if (!this.has.data) {
148
+ if (this.has.data === false) {
140
149
  throw new errors.MissingApiUrlError();
141
150
  }
142
151
  if (!concepts) {
@@ -196,26 +205,24 @@ class ConceptApiProvider extends BaseProvider {
196
205
  }
197
206
  });
198
207
  }
199
- async suggest({ scheme, use = "notation,label", types = [], sort = "score", ...config }) {
208
+ async suggest({ use = "notation,label", types = [], sort = "score", ...config }) {
200
209
  return this._search({
201
210
  ...config,
202
211
  endpoint: "suggest",
203
212
  params: {
204
213
  ...config.params,
205
- voc: _.get(scheme, "uri", ""),
206
214
  type: types.join("|"),
207
215
  use,
208
216
  sort
209
217
  }
210
218
  });
211
219
  }
212
- async search({ scheme, types = [], ...config }) {
220
+ async search({ types = [], ...config }) {
213
221
  return this._search({
214
222
  ...config,
215
223
  endpoint: "search",
216
224
  params: {
217
225
  ...config.params,
218
- voc: _.get(scheme, "uri", ""),
219
226
  type: types.join("|")
220
227
  }
221
228
  });
@@ -237,7 +244,7 @@ class ConceptApiProvider extends BaseProvider {
237
244
  endpoint: "voc-search"
238
245
  });
239
246
  }
240
- async _search({ endpoint, search, limit, offset, params, ...config }) {
247
+ async _search({ endpoint, scheme, search, limit, offset, params, ...config }) {
241
248
  let url = this._api[endpoint];
242
249
  if (!url) {
243
250
  throw new errors.MissingApiUrlError();
@@ -247,6 +254,7 @@ class ConceptApiProvider extends BaseProvider {
247
254
  }
248
255
  limit = limit || this._jskos.suggestResultLimit || 100;
249
256
  offset = offset || 0;
257
+ const voc = scheme && await this._getSchemeUri(scheme);
250
258
  url = url.replace("{searchTerms}", search);
251
259
  return this.axios({
252
260
  ...config,
@@ -257,7 +265,8 @@ class ConceptApiProvider extends BaseProvider {
257
265
  count: limit,
258
266
  offset,
259
267
  search,
260
- query: search
268
+ query: search,
269
+ voc
261
270
  },
262
271
  method: "get",
263
272
  url
@@ -1,11 +1,15 @@
1
1
  import BaseProvider from "./base-provider.js";
2
2
  import jskos from "jskos-tools";
3
3
  import * as _ from "../utils/lodash.js";
4
+ import { listOfCapabilities } from "../utils/index.js";
4
5
  import * as errors from "../errors/index.js";
5
6
  class LabelSearchSuggestionProvider extends BaseProvider {
6
- _setup() {
7
+ _prepare() {
7
8
  this._cache = [];
8
9
  this.has.mappings = true;
10
+ listOfCapabilities.filter((c) => !this.has[c]).forEach((c) => {
11
+ this.has[c] = false;
12
+ });
9
13
  }
10
14
  supportsScheme(scheme) {
11
15
  return _.get(scheme, "_registry.has.search", false);
@@ -54,6 +58,8 @@ class LabelSearchSuggestionProvider extends BaseProvider {
54
58
  if (!label) {
55
59
  return [];
56
60
  }
61
+ const regexResult = /^[\s\wäüöÄÜÖß]*\w/.exec(label);
62
+ label = regexResult ? regexResult[0] : label;
57
63
  const results = await this._getResults({ ...config, label, targetScheme, limit });
58
64
  let mappings = results.map((result) => ({
59
65
  fromScheme: sourceScheme,
@@ -78,7 +84,7 @@ class LabelSearchSuggestionProvider extends BaseProvider {
78
84
  return resultsFromCache;
79
85
  }
80
86
  const registry = _.get(targetScheme, "_registry");
81
- if (!registry || !registry.has.search) {
87
+ if (!registry || registry.has.search === false) {
82
88
  return [];
83
89
  }
84
90
  const data = await registry.search({
@@ -1,5 +1,6 @@
1
1
  import BaseProvider from "./base-provider.js";
2
2
  import * as errors from "../errors/index.js";
3
+ import { listOfCapabilities } from "../utils/index.js";
3
4
  import jskos from "jskos-tools";
4
5
  import axios from "axios";
5
6
  const locUriPrefix = "http://id.loc.gov/authorities/";
@@ -70,7 +71,7 @@ function madsToJskosConcept(data, { scheme }) {
70
71
  return concept;
71
72
  }
72
73
  class LocApiProvider extends BaseProvider {
73
- _setup() {
74
+ _prepare() {
74
75
  this.has.schemes = true;
75
76
  this.has.top = false;
76
77
  this.has.data = true;
@@ -79,6 +80,9 @@ class LocApiProvider extends BaseProvider {
79
80
  this.has.ancestors = false;
80
81
  this.has.suggest = true;
81
82
  this.has.search = true;
83
+ listOfCapabilities.filter((c) => !this.has[c]).forEach((c) => {
84
+ this.has[c] = false;
85
+ });
82
86
  }
83
87
  static _registryConfigForBartocApiConfig({ scheme } = {}) {
84
88
  if (!scheme || !supportedSchemes.find((s) => jskos.compare(s, scheme))) {
@@ -4,15 +4,21 @@ import * as _ from "../utils/lodash.js";
4
4
  import localforage from "localforage";
5
5
  import { v4 as uuid } from "uuid";
6
6
  import * as errors from "../errors/index.js";
7
+ import { listOfCapabilities } from "../utils/index.js";
7
8
  const uriPrefix = "urn:uuid:";
8
9
  class LocalMappingsProvider extends BaseProvider {
9
- _setup() {
10
+ _prepare() {
10
11
  this.has.mappings = {
11
12
  read: true,
12
13
  create: true,
13
14
  update: true,
14
15
  delete: true
15
16
  };
17
+ listOfCapabilities.filter((c) => !this.has[c]).forEach((c) => {
18
+ this.has[c] = false;
19
+ });
20
+ }
21
+ _setup() {
16
22
  this.queue = [];
17
23
  this.localStorageKey = "cocoda-mappings--" + this._path;
18
24
  let oldLocalStorageKey = "mappings";
@@ -8,6 +8,12 @@ class MappingsApiProvider extends BaseProvider {
8
8
  if (this._api.api && this._api.status === void 0) {
9
9
  this._api.status = utils.concatUrl(this._api.api, "/status");
10
10
  }
11
+ this.has.mappings = true;
12
+ this.has.concordances = true;
13
+ this.has.annotations = true;
14
+ utils.listOfCapabilities.filter((c) => !this.has[c]).forEach((c) => {
15
+ this.has[c] = false;
16
+ });
11
17
  }
12
18
  _setup() {
13
19
  if (this._api.api) {
@@ -4,11 +4,14 @@ import * as _ from "../utils/lodash.js";
4
4
  import * as errors from "../errors/index.js";
5
5
  import * as utils from "../utils/index.js";
6
6
  class OccurrencesApiProvider extends BaseProvider {
7
- _setup() {
7
+ _prepare() {
8
8
  this._cache = [];
9
9
  this._occurrencesSupportedSchemes = [];
10
10
  this.has.occurrences = true;
11
11
  this.has.mappings = true;
12
+ utils.listOfCapabilities.filter((c) => !this.has[c]).forEach((c) => {
13
+ this.has[c] = false;
14
+ });
12
15
  }
13
16
  async _occurrencesIsSupported(scheme) {
14
17
  if (this._occurrencesSupportedSchemes && this._occurrencesSupportedSchemes.length) {
@@ -2,10 +2,14 @@ import BaseProvider from "./base-provider.js";
2
2
  import jskos from "jskos-tools";
3
3
  import * as _ from "../utils/lodash.js";
4
4
  import * as errors from "../errors/index.js";
5
+ import { listOfCapabilities } from "../utils/index.js";
5
6
  class ReconciliationApiProvider extends BaseProvider {
6
- _setup() {
7
- this.has.mappings = true;
7
+ _prepare() {
8
8
  this._cache = [];
9
+ this.has.mappings = true;
10
+ listOfCapabilities.filter((c) => !this.has[c]).forEach((c) => {
11
+ this.has[c] = false;
12
+ });
9
13
  }
10
14
  async getMappings({ from, to, mode, ...config }) {
11
15
  let schemes = [];
@@ -2,8 +2,9 @@ import BaseProvider from "./base-provider.js";
2
2
  import jskos from "jskos-tools";
3
3
  import * as _ from "../utils/lodash.js";
4
4
  import * as errors from "../errors/index.js";
5
+ import { listOfCapabilities } from "../utils/index.js";
5
6
  class SkosmosApiProvider extends BaseProvider {
6
- _setup() {
7
+ _prepare() {
7
8
  this.has.schemes = true;
8
9
  this.has.top = true;
9
10
  this.has.data = true;
@@ -13,6 +14,9 @@ class SkosmosApiProvider extends BaseProvider {
13
14
  this.has.types = true;
14
15
  this.has.suggest = true;
15
16
  this.has.search = true;
17
+ listOfCapabilities.filter((c) => !this.has[c]).forEach((c) => {
18
+ this.has[c] = false;
19
+ });
16
20
  }
17
21
  static _registryConfigForBartocApiConfig({ url, scheme } = {}) {
18
22
  if (!url || !scheme) {
@@ -143,8 +143,25 @@ function withCustomProps(arr, from) {
143
143
  arr._url = from._url;
144
144
  return arr;
145
145
  }
146
+ const listOfCapabilities = [
147
+ "schemes",
148
+ "top",
149
+ "data",
150
+ "concepts",
151
+ "narrower",
152
+ "ancestors",
153
+ "types",
154
+ "suggest",
155
+ "search",
156
+ "auth",
157
+ "mappings",
158
+ "concordances",
159
+ "annotations",
160
+ "occurrences"
161
+ ];
146
162
  export {
147
163
  concatUrl,
164
+ listOfCapabilities,
148
165
  requestMethods,
149
166
  withCustomProps
150
167
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cocoda-sdk",
3
- "version": "2.0.13",
3
+ "version": "3.0.2",
4
4
  "description": "SDK for Cocoda",
5
5
  "main": "dist/cjs/index.cjs",
6
6
  "module": "dist/esm/index.js",