@isrd-isi-edu/ermrestjs 2.0.0 → 2.0.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/js/core.js +46 -23
- package/package.json +2 -2
- package/src/index.ts +2 -0
- package/src/models/errors.ts +6 -0
- package/src/models/reference/reference.ts +6 -4
- package/src/services/error.ts +20 -2
- package/src/utils/constants.ts +1 -0
- package/dist/ermrest.d.ts +0 -3481
- package/dist/ermrest.js +0 -45
- package/dist/ermrest.js.gz +0 -0
- package/dist/ermrest.js.map +0 -1
- package/dist/ermrest.min.js +0 -45
- package/dist/ermrest.min.js.gz +0 -0
- package/dist/ermrest.min.js.map +0 -1
- package/dist/ermrest.ver.txt +0 -1
- package/dist/stats.html +0 -4949
package/js/core.js
CHANGED
|
@@ -205,6 +205,10 @@ import {
|
|
|
205
205
|
*/
|
|
206
206
|
function Catalogs(server) {
|
|
207
207
|
this._server = server;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @type {{[catalogId: string]: Catalog}}
|
|
211
|
+
*/
|
|
208
212
|
this._catalogs = {};
|
|
209
213
|
}
|
|
210
214
|
|
|
@@ -243,21 +247,28 @@ import {
|
|
|
243
247
|
get: function (id, dontFetchSchema) {
|
|
244
248
|
// do introspection here and return a promise
|
|
245
249
|
|
|
246
|
-
|
|
250
|
+
const defer = ConfigService.q.defer();
|
|
251
|
+
let catalog;
|
|
247
252
|
|
|
248
253
|
// create a new catalog object if the object has not been created before
|
|
249
254
|
if (id in this._catalogs) {
|
|
250
|
-
catalog =
|
|
255
|
+
catalog = this._catalogs[id];
|
|
251
256
|
} else {
|
|
252
|
-
catalog = new Catalog(
|
|
257
|
+
catalog = new Catalog(this._server, id);
|
|
253
258
|
}
|
|
254
259
|
|
|
255
260
|
// make sure the catalog is introspected.
|
|
256
261
|
// the introspect function might or might not
|
|
257
|
-
catalog._introspect(dontFetchSchema).then(
|
|
258
|
-
|
|
262
|
+
catalog._introspect(dontFetchSchema).then(() => {
|
|
263
|
+
/**
|
|
264
|
+
* TODO the catalog id might have changed if the version was corrected.
|
|
265
|
+
* with the current implementation, the next time this function is called,
|
|
266
|
+
* it will not use the cached catalog and will create a new one (so a new request).
|
|
267
|
+
* We might be able to improve this in the future.
|
|
268
|
+
*/
|
|
269
|
+
this._catalogs[id] = catalog;
|
|
259
270
|
defer.resolve(catalog);
|
|
260
|
-
}).catch(
|
|
271
|
+
}).catch((error) => {
|
|
261
272
|
defer.reject(error);
|
|
262
273
|
});
|
|
263
274
|
|
|
@@ -318,6 +329,11 @@ import {
|
|
|
318
329
|
// this property is needed by _determineDisplayName
|
|
319
330
|
this.name = id;
|
|
320
331
|
|
|
332
|
+
/**
|
|
333
|
+
* Indicates whether the version in the catalog ID was corrected to match the server's snaptime.
|
|
334
|
+
*/
|
|
335
|
+
this.versionCorrected = false;
|
|
336
|
+
|
|
321
337
|
this._nameStyle = {}; // Used in the displayname to store the name styles.
|
|
322
338
|
|
|
323
339
|
// NOTE we still haven't fetched the catalog, so we don't have the catalog annotation here.
|
|
@@ -460,21 +476,28 @@ import {
|
|
|
460
476
|
* @private
|
|
461
477
|
*/
|
|
462
478
|
_introspect: function (dontFetchSchema) {
|
|
463
|
-
var defer = ConfigService.q.defer()
|
|
479
|
+
var defer = ConfigService.q.defer();
|
|
464
480
|
|
|
465
481
|
// load the catalog (or use the one that is cached)
|
|
466
|
-
this._get().then(
|
|
467
|
-
|
|
482
|
+
this._get().then((response) => {
|
|
483
|
+
this.snaptime = response.snaptime;
|
|
484
|
+
|
|
485
|
+
let versionCorrected = false;
|
|
486
|
+
if (isStringAndNotEmpty(this.version) && this.version !== this.snaptime) {
|
|
487
|
+
this.version = this.snaptime;
|
|
488
|
+
this.id = this.id.split("@")[0] + "@" + this.version;
|
|
489
|
+
this.versionCorrected = true;
|
|
490
|
+
}
|
|
468
491
|
|
|
469
492
|
if ("features" in response) {
|
|
470
|
-
for (var k in
|
|
471
|
-
|
|
493
|
+
for (var k in this.features) {
|
|
494
|
+
this.features[k] = response.features[k];
|
|
472
495
|
}
|
|
473
496
|
}
|
|
474
497
|
|
|
475
|
-
|
|
498
|
+
this.annotations = new Annotations();
|
|
476
499
|
for (var uri in response.annotations) {
|
|
477
|
-
|
|
500
|
+
this.annotations._push(new Annotation("catalog", uri, response.annotations[uri]));
|
|
478
501
|
}
|
|
479
502
|
|
|
480
503
|
/**
|
|
@@ -482,7 +505,7 @@ import {
|
|
|
482
505
|
* This should be done before initializing tables because tables require this field.
|
|
483
506
|
* @type {boolean|null}
|
|
484
507
|
*/
|
|
485
|
-
|
|
508
|
+
this.isGenerated = _processACLAnnotation(this.annotations, _annotations.GENERATED, false);
|
|
486
509
|
|
|
487
510
|
/**
|
|
488
511
|
* whether catalog is immutable.
|
|
@@ -491,32 +514,32 @@ import {
|
|
|
491
514
|
* null: annotation is not defined
|
|
492
515
|
* @type {boolean|null}
|
|
493
516
|
*/
|
|
494
|
-
|
|
517
|
+
this.isImmutable = _processACLAnnotation(this.annotations, _annotations.IMMUTABLE, null);
|
|
495
518
|
|
|
496
519
|
/**
|
|
497
520
|
* whether catalog is non-deletable
|
|
498
521
|
* @type {boolean}
|
|
499
522
|
*/
|
|
500
|
-
|
|
523
|
+
this.isNonDeletable = _processACLAnnotation(this.annotations, _annotations.NON_DELETABLE, false);
|
|
501
524
|
|
|
502
525
|
/**
|
|
503
526
|
* this will make sure the nameStyle is populated on the catalog as well,
|
|
504
527
|
* so schema can use it.
|
|
505
528
|
*/
|
|
506
|
-
_determineDisplayName(
|
|
529
|
+
_determineDisplayName(this, true);
|
|
507
530
|
|
|
508
|
-
if (dontFetchSchema === true ||
|
|
509
|
-
defer.resolve();
|
|
531
|
+
if (dontFetchSchema === true || this._schemaFetched) {
|
|
532
|
+
defer.resolve({ versionCorrected });
|
|
510
533
|
} else {
|
|
511
534
|
// load all schemas
|
|
512
|
-
|
|
513
|
-
defer.resolve();
|
|
514
|
-
}).catch(
|
|
535
|
+
this._fetchSchema().then(() => {
|
|
536
|
+
defer.resolve({ versionCorrected });
|
|
537
|
+
}).catch((err) => {
|
|
515
538
|
throw err;
|
|
516
539
|
});
|
|
517
540
|
}
|
|
518
541
|
|
|
519
|
-
}).catch(
|
|
542
|
+
}).catch((response) => {
|
|
520
543
|
defer.reject(ErrorService.responseToError(response));
|
|
521
544
|
});
|
|
522
545
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isrd-isi-edu/ermrestjs",
|
|
3
3
|
"description": "ERMrest client library in JavaScript",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.1",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">= 20.0.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"spark-md5": "^3.0.0",
|
|
55
55
|
"terser": "^5.43.1",
|
|
56
56
|
"typescript": "~5.8.3",
|
|
57
|
-
"vite": "^6.
|
|
57
|
+
"vite": "^6.4.1",
|
|
58
58
|
"vite-plugin-compression2": "^2.2.1"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
ConflictError,
|
|
17
17
|
IntegrityConflictError,
|
|
18
18
|
DuplicateConflictError,
|
|
19
|
+
SnapshotNotFoundError,
|
|
19
20
|
PreconditionFailedError,
|
|
20
21
|
InternalServerError,
|
|
21
22
|
BadGatewayError,
|
|
@@ -170,6 +171,7 @@ export {
|
|
|
170
171
|
ConflictError,
|
|
171
172
|
IntegrityConflictError,
|
|
172
173
|
DuplicateConflictError,
|
|
174
|
+
SnapshotNotFoundError,
|
|
173
175
|
PreconditionFailedError,
|
|
174
176
|
InternalServerError,
|
|
175
177
|
BadGatewayError,
|
package/src/models/errors.ts
CHANGED
|
@@ -96,6 +96,12 @@ export class DuplicateConflictError extends ConflictError {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
export class SnapshotNotFoundError extends ERMrestError {
|
|
100
|
+
constructor(status: string, message: string, subMessage?: string) {
|
|
101
|
+
super(_HTTPErrorCodes.CONFLICT, _errorStatus.SNAPSHOT_NOT_FOUND, message, subMessage);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
99
105
|
export class PreconditionFailedError extends ERMrestError {
|
|
100
106
|
constructor(status: string, message: string) {
|
|
101
107
|
const usedStatus = isStringAndNotEmpty(status) ? status : _errorStatus.PRECONDITION_FAILED;
|
|
@@ -122,13 +122,15 @@ export const resolve = async (uri: string, contextHeaderParams?: any): Promise<R
|
|
|
122
122
|
await onload();
|
|
123
123
|
//added try block to make sure it rejects all parse() related error
|
|
124
124
|
// It should have been taken care by outer try but did not work
|
|
125
|
-
const
|
|
125
|
+
const loc = parse(uri);
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
console.log(loc.catalog);
|
|
128
128
|
|
|
129
|
-
const
|
|
129
|
+
const server = ermrestFactory.getServer(loc.service, contextHeaderParams);
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
const catalog = await server.catalogs.get(loc.catalog);
|
|
132
|
+
|
|
133
|
+
return new Reference(loc, catalog);
|
|
132
134
|
};
|
|
133
135
|
|
|
134
136
|
/**
|
package/src/services/error.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import moment from 'moment-timezone';
|
|
2
|
+
|
|
1
3
|
// models
|
|
2
4
|
import { Reference } from '@isrd-isi-edu/ermrestjs/src/models/reference';
|
|
3
5
|
|
|
4
|
-
import { contextHeaderName, _operationsFlag } from '@isrd-isi-edu/ermrestjs/src/utils/constants';
|
|
6
|
+
import { contextHeaderName, _operationsFlag, _dataFormats } from '@isrd-isi-edu/ermrestjs/src/utils/constants';
|
|
5
7
|
import {
|
|
6
8
|
ERMrestError,
|
|
7
9
|
NoConnectionError,
|
|
@@ -18,12 +20,15 @@ import {
|
|
|
18
20
|
IntegrityConflictError,
|
|
19
21
|
DuplicateConflictError,
|
|
20
22
|
ConflictError,
|
|
23
|
+
SnapshotNotFoundError,
|
|
21
24
|
} from '@isrd-isi-edu/ermrestjs/src/models/errors';
|
|
22
25
|
import { fixedEncodeURIComponent } from '@isrd-isi-edu/ermrestjs/src/utils/value-utils';
|
|
23
26
|
|
|
24
27
|
// legacy
|
|
28
|
+
|
|
25
29
|
import { parse } from '@isrd-isi-edu/ermrestjs/js/parser';
|
|
26
30
|
import { ermrestFactory } from '@isrd-isi-edu/ermrestjs/js/core';
|
|
31
|
+
import HistoryService from '@isrd-isi-edu/ermrestjs/src/services/history';
|
|
27
32
|
|
|
28
33
|
export default class ErrorService {
|
|
29
34
|
/**
|
|
@@ -121,7 +126,20 @@ export default class ErrorService {
|
|
|
121
126
|
const conflictErrorPrefix = ['409 Conflict\nThe request conflicts with the state of the server. ', 'Request conflicts with state of server.'];
|
|
122
127
|
let siteAdminMsg = '\nIf you have trouble removing dependencies please contact the site administrator.';
|
|
123
128
|
|
|
124
|
-
if (generatedErrMessage.indexOf('
|
|
129
|
+
if (generatedErrMessage.indexOf('Requested catalog revision ') > -1 && generatedErrMessage.indexOf('is prior to any known revision.') > -1) {
|
|
130
|
+
const match = generatedErrMessage.match(/Requested catalog revision "([^"]+)"/);
|
|
131
|
+
const snapshot = match ? match[1] : '';
|
|
132
|
+
let formattedTime = '';
|
|
133
|
+
if (snapshot) {
|
|
134
|
+
formattedTime = HistoryService.snapshotToDatetimeISO(snapshot, true);
|
|
135
|
+
if (formattedTime) {
|
|
136
|
+
formattedTime = moment(formattedTime).format(_dataFormats.DATETIME.display);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const newMessage = `The requested snapshot time ${formattedTime ? '(' + formattedTime + ') ' : ''}is older than any available history.`;
|
|
140
|
+
|
|
141
|
+
return new SnapshotNotFoundError(errorStatusText, newMessage);
|
|
142
|
+
} else if (generatedErrMessage.indexOf('violates foreign key constraint') > -1 && actionFlag === _operationsFlag.DELETE) {
|
|
125
143
|
let referenceTable: any = '';
|
|
126
144
|
|
|
127
145
|
let detail: string | number = generatedErrMessage.search(/DETAIL:/g);
|
package/src/utils/constants.ts
CHANGED
|
@@ -327,6 +327,7 @@ export const _errorStatus = Object.freeze({
|
|
|
327
327
|
INVALID_PAGE: 'Invalid Page Criteria',
|
|
328
328
|
INVALID_SERVER_RESPONSE: 'Invalid Server Response',
|
|
329
329
|
UNSUPPORTED_FILTERS: 'Unsupported Filters',
|
|
330
|
+
SNAPSHOT_NOT_FOUND: 'Snapshot Not Found',
|
|
330
331
|
});
|
|
331
332
|
|
|
332
333
|
export const _errorMessage = Object.freeze({
|