@ocfl/ocfl 0.1.1 → 0.2.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.
- package/README.md +6 -1
- package/index.js +27 -15
- package/lib/extension.js +3 -3
- package/lib/extensions/000N-path-direct-storage-layout.js +61 -0
- package/lib/extensions/index.js +2 -1
- package/lib/object.js +36 -15
- package/lib/storage.js +24 -23
- package/lib/types.d.ts +9 -0
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# ocfl-js - Common modules
|
|
2
2
|
This is JavaScript/Node.js library to create and interact with Oxford Common File Layout (OCFL) storage and objects within it.
|
|
3
3
|
This package contains abstract classes definition. Do not use this package directly. To work with an actual OCFL storage and object, use the following concrete implementation:
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
* ocfl-fs - File system backend
|
|
5
6
|
|
|
6
7
|
## Extensions
|
|
7
8
|
This library by default includes all the community extensions defined in the [OCFL Community Extensions page](https://github.com/OCFL/extensions). The implementation is organised in the ocfl-extensions package.
|
|
@@ -14,3 +15,7 @@ To implement a local extension in this library, first follow the description in
|
|
|
14
15
|
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
|
|
19
|
+
## Implementation
|
|
20
|
+
|
|
21
|
+
A new data store backend can be implemented by creating a new package with a store class that extends the `OcflStore` class and implements its methods. Please see the source code of ocfl-fs as an example implementation
|
package/index.js
CHANGED
|
@@ -21,11 +21,12 @@ const { OcflConstants, OcflDigest, OcflExtension, OcflStorageLayout, OcflStore,
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* @typedef {Object} StorageLayout
|
|
24
|
-
* @property {typeof extensions.FlatDirectStorageLayout}
|
|
25
|
-
* @property {typeof extensions.FlatOmitPrefixStorageLayout}
|
|
26
|
-
* @property {typeof extensions.HashAndIdNTupleStorageLayout}
|
|
27
|
-
* @property {typeof extensions.HashedNTupleStorageLayout}
|
|
28
|
-
* @property {typeof extensions.NTupleOmitPrefixStorageLayout}
|
|
24
|
+
* @property {typeof extensions.FlatDirectStorageLayout} FlatDirectStorageLayout
|
|
25
|
+
* @property {typeof extensions.FlatOmitPrefixStorageLayout} FlatOmitPrefixStorageLayout
|
|
26
|
+
* @property {typeof extensions.HashAndIdNTupleStorageLayout} HashAndIdNTupleStorageLayout
|
|
27
|
+
* @property {typeof extensions.HashedNTupleStorageLayout} HashedNTupleStorageLayout
|
|
28
|
+
* @property {typeof extensions.NTupleOmitPrefixStorageLayout} NTupleOmitPrefixStorageLayout
|
|
29
|
+
* @property {typeof extensions.PathDirectStorageLayout} PathDirectStorageLayout
|
|
29
30
|
*/
|
|
30
31
|
/** @typedef {import('./lib/extension.js').OcflExtensionConfig} OcflExtensionConfig */
|
|
31
32
|
|
|
@@ -73,7 +74,7 @@ class Ocfl {
|
|
|
73
74
|
get StorageLayout() { return OcflStorageLayout.layout }
|
|
74
75
|
|
|
75
76
|
/**
|
|
76
|
-
*
|
|
77
|
+
* Instantiate a storage layout from extension name or config
|
|
77
78
|
* @param {string|OcflExtensionConfig} config - Layout name or config
|
|
78
79
|
*/
|
|
79
80
|
storageLayout(config) {
|
|
@@ -90,7 +91,7 @@ class Ocfl {
|
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
/**
|
|
93
|
-
*
|
|
94
|
+
* Instantiate an OCFL Object object
|
|
94
95
|
* @param {OcflObjectConfig} config
|
|
95
96
|
* @param {SO} [storeOptions]
|
|
96
97
|
* @return {OcflObject}
|
|
@@ -100,7 +101,7 @@ class Ocfl {
|
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
/**
|
|
103
|
-
*
|
|
104
|
+
* Instantiate an OCFL Storage object
|
|
104
105
|
* @param {OcflStorageConfig} config
|
|
105
106
|
* @param {SO} [storeOptions]
|
|
106
107
|
* @return {OcflStorage}
|
|
@@ -109,16 +110,27 @@ class Ocfl {
|
|
|
109
110
|
return new OcflStorageImpl(config, this.#store.getInstance(storeOptions));
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Create a new OCFL Storage
|
|
115
|
+
* @param {OcflStorageConfig} config
|
|
116
|
+
* @param {SO} [storeOptions]
|
|
117
|
+
* @return {Promise<OcflStorage>}
|
|
118
|
+
*/
|
|
119
|
+
async createStorage(config, storeOptions = this.#defaultOptions) {
|
|
120
|
+
return (new OcflStorageImpl(config, this.#store.getInstance(storeOptions))).create();
|
|
117
121
|
}
|
|
118
|
-
async load(config) {
|
|
119
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Load an existing OCFL Storage
|
|
125
|
+
* @param {OcflStorageConfig} config
|
|
126
|
+
* @param {SO} [storeOptions]
|
|
127
|
+
* @return {Promise<OcflStorage>}
|
|
128
|
+
*/
|
|
129
|
+
async loadStorage(config, storeOptions = this.#defaultOptions) {
|
|
130
|
+
return (new OcflStorageImpl(config, this.#store.getInstance(storeOptions))).load();
|
|
120
131
|
}
|
|
121
|
-
}
|
|
132
|
+
}
|
|
133
|
+
|
|
122
134
|
|
|
123
135
|
|
|
124
136
|
module.exports = {
|
package/lib/extension.js
CHANGED
|
@@ -7,7 +7,7 @@ const { NotImplementedError } = require("./error");
|
|
|
7
7
|
const extensionByName = {};
|
|
8
8
|
/** Index by extension class name */
|
|
9
9
|
const extensionByClassName = {};
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
const storageLayout = {};
|
|
12
12
|
|
|
13
13
|
/** @typedef {{ extensionName?: string;[key: string]: any; }} OcflExtensionConfig */
|
|
@@ -110,7 +110,7 @@ class OcflExtension {
|
|
|
110
110
|
*/
|
|
111
111
|
constructor(config, defaultConfig) {
|
|
112
112
|
/** @type {C} */
|
|
113
|
-
this.parameters = defaultConfig ? Object.create(/**@type{object}*/(defaultConfig)) : {};
|
|
113
|
+
this.parameters = typeof defaultConfig === 'object' ? Object.create(/**@type{object}*/(defaultConfig)) : {};
|
|
114
114
|
if (typeof config === 'object') {
|
|
115
115
|
for (let k in config) {
|
|
116
116
|
if (k in defaultConfig) this.parameters[k] = config[k];
|
|
@@ -157,7 +157,7 @@ class OcflExtension {
|
|
|
157
157
|
class OcflStorageLayout extends OcflExtension {
|
|
158
158
|
|
|
159
159
|
static get layout() {
|
|
160
|
-
return storageLayout;
|
|
160
|
+
return /** @type StorageLayout */(storageLayout);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
/**
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const { OcflStorageLayout } = require("../extension");
|
|
2
|
+
const { OcflDigest } = require("../digest");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
5
|
+
const DefaultConfig = {
|
|
6
|
+
extensionName: '000N-path-direct-storage-layout',
|
|
7
|
+
omitScheme: false,
|
|
8
|
+
/** @type {any} */
|
|
9
|
+
replace: [],
|
|
10
|
+
suffix: '/__object__'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/** @typedef {Partial<typeof DefaultConfig>} PathDirectStorageLayoutConfig */
|
|
14
|
+
/**
|
|
15
|
+
* @extends {OcflStorageLayout<typeof DefaultConfig>}
|
|
16
|
+
*/
|
|
17
|
+
class PathDirectStorageLayout extends OcflStorageLayout {
|
|
18
|
+
static get NAME() { return DefaultConfig.extensionName; }
|
|
19
|
+
static get DESCRIPTION() {
|
|
20
|
+
return "OCFL object identifiers are used directly as the path.";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {PathDirectStorageLayoutConfig} [config]
|
|
26
|
+
*/
|
|
27
|
+
constructor(config) {
|
|
28
|
+
super(config, DefaultConfig);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {string} id
|
|
33
|
+
* @return {string}
|
|
34
|
+
*/
|
|
35
|
+
map(id) {
|
|
36
|
+
var suffix = this.parameters.suffix;
|
|
37
|
+
if (suffix && id.endsWith(suffix)) throw new Error(`Identifier cannot end with '${suffix}'`);
|
|
38
|
+
var p = id ?? '';
|
|
39
|
+
for (const r of this.parameters.replace) {
|
|
40
|
+
p = p.replace(r[0], r[1]);
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
let u = new URL(p);
|
|
44
|
+
let parts = [];
|
|
45
|
+
if (!this.parameters.omitScheme && u.protocol !== 'file:') {
|
|
46
|
+
parts.push(u.protocol.replace(':', ''));
|
|
47
|
+
}
|
|
48
|
+
if (u.hostname) {
|
|
49
|
+
parts.push(u.hostname.replace(',', '_').replace(';', '/'));
|
|
50
|
+
}
|
|
51
|
+
p = path.join(parts.join('_'), u.pathname + u.search + u.hash);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
}
|
|
54
|
+
p = p.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
55
|
+
return path.join(p, this.parameters.suffix);
|
|
56
|
+
//if (/^\w+:/.test(id)) {
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = { PathDirectStorageLayout };
|
package/lib/extensions/index.js
CHANGED
|
@@ -6,7 +6,8 @@ module.exports = {
|
|
|
6
6
|
...require('./0004-hashed-n-tuple-storage-layout'),
|
|
7
7
|
// ...require('./0005-mutable-head'),
|
|
8
8
|
...require('./0006-flat-omit-prefix-storage-layout'),
|
|
9
|
-
...require('./0007-n-tuple-omit-prefix-storage-layout')
|
|
9
|
+
...require('./0007-n-tuple-omit-prefix-storage-layout'),
|
|
10
|
+
...require('./000N-path-direct-storage-layout')
|
|
10
11
|
//...require('./0008-schema-registry')
|
|
11
12
|
};
|
|
12
13
|
//const { DigestAlgorithm } = require('./0001-digest-algorithms.js');
|
package/lib/object.js
CHANGED
|
@@ -123,13 +123,19 @@ class OcflObject {
|
|
|
123
123
|
* Identifier of the OCFL Object
|
|
124
124
|
* @return {string}
|
|
125
125
|
*/
|
|
126
|
-
get id() { throw new NotImplementedError() }
|
|
126
|
+
get id() { throw new NotImplementedError(); }
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
|
-
* The
|
|
129
|
+
* The absolute path to the root of this OCFL Object
|
|
130
130
|
* @return {string}
|
|
131
131
|
*/
|
|
132
|
-
get root() { throw new NotImplementedError() }
|
|
132
|
+
get root() { throw new NotImplementedError(); }
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The absolute path to the temporary workspace of this OCFL Object
|
|
136
|
+
* @return {string}
|
|
137
|
+
*/
|
|
138
|
+
get workspace() { throw new NotImplementedError(); }
|
|
133
139
|
|
|
134
140
|
toString() { return `OcflObject { root: ${this.root}, id: ${this.id} }`; }
|
|
135
141
|
|
|
@@ -140,7 +146,7 @@ class OcflObject {
|
|
|
140
146
|
* @param {string} [version] - Full name of the version, eg: v1, v2, v3
|
|
141
147
|
* @returns {Promise<OcflObjectInventory>}
|
|
142
148
|
*/
|
|
143
|
-
async getInventory(version = 'latest') { throw new NotImplementedError() }
|
|
149
|
+
async getInventory(version = 'latest') { throw new NotImplementedError(); }
|
|
144
150
|
|
|
145
151
|
/**
|
|
146
152
|
* Update the content files or directories as one transaction and commit the changes as a new version.
|
|
@@ -150,7 +156,7 @@ class OcflObject {
|
|
|
150
156
|
* @param {ObjectUpdateMode} [mode=UPDATE_MODE.MERGE]
|
|
151
157
|
* @return {Promise<?OcflObjectTransaction>}
|
|
152
158
|
*/
|
|
153
|
-
async update(updater, mode
|
|
159
|
+
async update(updater, mode) { throw new NotImplementedError(); }
|
|
154
160
|
|
|
155
161
|
/**
|
|
156
162
|
* Import one or more content files or directories to the object
|
|
@@ -199,7 +205,8 @@ class OcflObject {
|
|
|
199
205
|
|
|
200
206
|
/**
|
|
201
207
|
* Iterate through the content files contained in the specified version.
|
|
202
|
-
* Returns an
|
|
208
|
+
* Returns an Iterator that contains FileRef which consists of logical path, content path, and digest, in no particular order.
|
|
209
|
+
* The iterator is implemented as a generator.
|
|
203
210
|
* @param {string} [version]
|
|
204
211
|
* @return {Promise<Generator<OcflObjectFile, void, unknown>>}
|
|
205
212
|
*/
|
|
@@ -224,7 +231,7 @@ class OcflObject {
|
|
|
224
231
|
* @type { GetFileByLogical & GetFileByOpt }
|
|
225
232
|
*/
|
|
226
233
|
// @ts-ignore
|
|
227
|
-
getFile = function (opt, version) { }
|
|
234
|
+
getFile = function (opt, version) { };
|
|
228
235
|
|
|
229
236
|
/**
|
|
230
237
|
* Count the number of files contained in this object
|
|
@@ -258,6 +265,8 @@ class OcflObjectImpl extends OcflObject {
|
|
|
258
265
|
/** @type {string} */
|
|
259
266
|
#root;
|
|
260
267
|
/** @type {string} */
|
|
268
|
+
#workspace;
|
|
269
|
+
/** @type {string} */
|
|
261
270
|
#id;
|
|
262
271
|
/** @type {OcflExtension[]} */
|
|
263
272
|
#extensions;
|
|
@@ -283,13 +292,14 @@ class OcflObjectImpl extends OcflObject {
|
|
|
283
292
|
this.digestAlgorithm = DIGEST.of(config.digestAlgorithm || 'sha512');
|
|
284
293
|
if (!this.digestAlgorithm) throw new Error('Invalid digest algorithm. Must be one of `sha256` or `sha512`.');
|
|
285
294
|
//this.fixityDigest = config.fixityDigest ?? this.digestAlgorithm;
|
|
286
|
-
this
|
|
295
|
+
this.#workspace = config.workspace ? path.resolve(config.workspace) : undefined;
|
|
287
296
|
this.contentDirectory = config.contentDirectory ?? 'content';
|
|
288
297
|
/** @type Object.<string, OcflObjectInventory> */
|
|
289
298
|
this._inventory = {};
|
|
290
299
|
}
|
|
291
300
|
get id() { return this._inventory?.latest?.id || this.#id; }
|
|
292
301
|
get root() { return this.#root; }
|
|
302
|
+
get workspace() { return this.#workspace; }
|
|
293
303
|
|
|
294
304
|
async getInventory(version = 'latest') {
|
|
295
305
|
if (!this._inventory[version]) {
|
|
@@ -324,7 +334,7 @@ class OcflObjectImpl extends OcflObject {
|
|
|
324
334
|
OcflDigest.digestAsync(data.digestAlgorithm, datastr)
|
|
325
335
|
]));
|
|
326
336
|
digest = digest.match(/[^\s]+/)?.[0];
|
|
327
|
-
if (digest !== actualDigest) throw new Error(
|
|
337
|
+
if (digest !== actualDigest) throw new Error(`Inventory file ${this.root}/${invPath} digest mismatch: recorded=${digest} actual=${actualDigest}`);
|
|
328
338
|
//return new OcflObjectInventory({ data, digest });
|
|
329
339
|
return new OcflObjectInventory(data);
|
|
330
340
|
}
|
|
@@ -373,13 +383,13 @@ class OcflObjectImpl extends OcflObject {
|
|
|
373
383
|
*/
|
|
374
384
|
readFile = async function (relPath, options) {
|
|
375
385
|
return this.#store.readFile(path.join(this.root, relPath), options);
|
|
376
|
-
}
|
|
386
|
+
};
|
|
377
387
|
|
|
378
388
|
getFile = function (opt, version) {
|
|
379
389
|
var obj = this;
|
|
380
390
|
var opt_ = typeof opt === 'string' ? { logicalPath: opt, version: version } : opt;
|
|
381
391
|
return new OcflObjectFile(this, opt_);
|
|
382
|
-
}
|
|
392
|
+
};
|
|
383
393
|
|
|
384
394
|
// async _resolveContentPath({ logicalPath = '', contentPath = '', digest = '', version = '' }) {
|
|
385
395
|
// if (!contentPath) {
|
|
@@ -477,6 +487,7 @@ class OcflObjectImpl extends OcflObject {
|
|
|
477
487
|
// workspace dir exists, abort update
|
|
478
488
|
throw new Error('Uncommitted changes detected. Object is being updated by other process or there has been a failed update attempt');
|
|
479
489
|
}
|
|
490
|
+
await this._validateObjectPath();
|
|
480
491
|
let createdDir = await this.#store.mkdir(workspacePath);
|
|
481
492
|
if (!this.workspace) await this._ensureNamaste();
|
|
482
493
|
return createTransactionProxy(new OcflObjectTransactionImpl(this, this.#store, inventory, workspaceVersionPath, createdDir));
|
|
@@ -491,18 +502,28 @@ class OcflObjectImpl extends OcflObject {
|
|
|
491
502
|
return;
|
|
492
503
|
}
|
|
493
504
|
// namaste not found, check if object root is not empty
|
|
505
|
+
let files;
|
|
494
506
|
try {
|
|
495
|
-
|
|
496
|
-
if (files.length > 0) throw new Error('Cannot create an OCFL Object in a non-empty directory');
|
|
507
|
+
files = await this.#store.readdir(this.root);
|
|
497
508
|
} catch (error) {
|
|
498
509
|
}
|
|
510
|
+
if (files && files.length > 0) throw new Error('Cannot create an OCFL Object in a non-empty directory');
|
|
499
511
|
//create the namaste file
|
|
500
512
|
let filePath = path.join(this.root, NAMASTE_T + prefix + this.ocflVersion);
|
|
501
513
|
await this.#store.writeFile(filePath, prefix + this.ocflVersion + '\n', 'utf8');
|
|
502
514
|
}
|
|
503
515
|
|
|
516
|
+
// all the parent directories cannot be an ocfl object
|
|
517
|
+
async _validateObjectPath() {
|
|
518
|
+
var p = this.root;
|
|
519
|
+
while (p !== '.' && p !== '/' ) {
|
|
520
|
+
p = path.dirname(p);
|
|
521
|
+
let nv = await findNamasteVersion(this.#store, NAMASTE_PREFIX_OBJECT, p);
|
|
522
|
+
if (nv) throw new Error(`Object root cannot be nested under another object ${p}`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
504
526
|
async isObject(aPath) { }
|
|
505
|
-
async importDir(id, sourceDir) { }
|
|
506
527
|
getVersionString(i) { }
|
|
507
528
|
async determineVersion() { }
|
|
508
529
|
nameVersion(version) {
|
|
@@ -540,7 +561,7 @@ const proxyHandler = {
|
|
|
540
561
|
}
|
|
541
562
|
}
|
|
542
563
|
}
|
|
543
|
-
}
|
|
564
|
+
};
|
|
544
565
|
|
|
545
566
|
/**
|
|
546
567
|
* Return any OcflObject implementation as OcflObject.
|
package/lib/storage.js
CHANGED
|
@@ -7,8 +7,8 @@ const { OcflStorageLayout } = require("./extension");
|
|
|
7
7
|
const { HashedNTupleStorageLayout } = require("./extensions/0004-hashed-n-tuple-storage-layout");
|
|
8
8
|
const { OcflObject, OcflObjectImpl } = require("./object");
|
|
9
9
|
const { isDirEmpty, findNamasteVersion } = require("./utils.js");
|
|
10
|
-
const { OCFL_VERSION, OCFL_VERSIONS, OCFL_LAYOUT,
|
|
11
|
-
EXTENSIONS_DIR, EXTENSION_CONFIG,
|
|
10
|
+
const { OCFL_VERSION, OCFL_VERSIONS, OCFL_LAYOUT,
|
|
11
|
+
EXTENSIONS_DIR, EXTENSION_CONFIG,
|
|
12
12
|
NAMASTE_PREFIX_STORAGE, NAMASTE_PREFIX_OBJECT, NAMASTE_T } = require('./constants').OcflConstants;
|
|
13
13
|
const DIGEST = require('./digest').OcflDigest.CONTENT;
|
|
14
14
|
|
|
@@ -66,42 +66,44 @@ class OcflStorage {
|
|
|
66
66
|
* Create the storage root in the underlying storage backend
|
|
67
67
|
* @param {Object} [options] - Additional options for creating storage root
|
|
68
68
|
* @param {boolean} [options.ocflSpecText=false] - If true, create a copy of the OCFL specification text in the storage root
|
|
69
|
+
* @return {Promise<OcflStorage>}
|
|
69
70
|
*/
|
|
70
71
|
async create(options) { throw new NotImplementedError(); }
|
|
71
72
|
|
|
72
|
-
/**
|
|
73
|
-
* Check if the storage root path points to an existing file or non-empty directory in the underlying backend store.
|
|
74
|
-
* The existing directory may or may not be a valid OCFL Storage.
|
|
75
|
-
* @return {Promise<boolean>}
|
|
76
|
-
*/
|
|
77
|
-
async exists() { throw new NotImplementedError(); }
|
|
78
|
-
|
|
79
73
|
/**
|
|
80
74
|
* Check namaste, retrieve storage layout extension, and read its config file.
|
|
81
|
-
* @return {Promise<
|
|
75
|
+
* @return {Promise<OcflStorage>}
|
|
82
76
|
*/
|
|
83
77
|
async load() { throw new NotImplementedError(); }
|
|
84
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Check if the storage root path points to an existing file or non-empty directory in the underlying backend store.
|
|
81
|
+
* The existing directory may or may not be a valid OCFL Storage.
|
|
82
|
+
* @return {Promise<boolean>}
|
|
83
|
+
*/
|
|
84
|
+
async exists() { throw new NotImplementedError(); }
|
|
85
|
+
|
|
85
86
|
/**
|
|
86
87
|
*
|
|
87
|
-
* @return {
|
|
88
|
+
* @return {AsyncIterableIterator<OcflObject>}
|
|
88
89
|
*/
|
|
89
90
|
[Symbol.asyncIterator]() { throw new NotImplementedError(); }
|
|
90
91
|
|
|
91
92
|
/**
|
|
92
|
-
* Return all OCFL objects
|
|
93
|
-
* @return {
|
|
93
|
+
* Return a new AsyncIterator that contains all the OCFL objects in this Storage.
|
|
94
|
+
* @return {AsyncIterableIterator<OcflObject>}
|
|
94
95
|
*/
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
objects() {
|
|
97
|
+
return this[Symbol.asyncIterator]();
|
|
98
|
+
// const objects = [];
|
|
99
|
+
// for await (const o of this) objects.push(o);
|
|
100
|
+
// return objects;
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
async delete(id) {
|
|
102
104
|
return this.remove(id);
|
|
103
105
|
}
|
|
104
|
-
|
|
106
|
+
|
|
105
107
|
async purge(id) {
|
|
106
108
|
return this.remove(id);
|
|
107
109
|
}
|
|
@@ -188,7 +190,7 @@ class OcflStorageImpl extends OcflStorage {
|
|
|
188
190
|
object(opt) {
|
|
189
191
|
let id, root;
|
|
190
192
|
if (typeof opt === 'string') id = opt;
|
|
191
|
-
else ({id, root} = opt);
|
|
193
|
+
else ({ id, root } = opt);
|
|
192
194
|
let relObjectRoot = root || this.objectRoot(id);
|
|
193
195
|
return new OcflObjectImpl({
|
|
194
196
|
id,
|
|
@@ -230,7 +232,7 @@ class OcflStorageImpl extends OcflStorage {
|
|
|
230
232
|
|
|
231
233
|
//@todo: load storage level extensions
|
|
232
234
|
|
|
233
|
-
return
|
|
235
|
+
return this;
|
|
234
236
|
}
|
|
235
237
|
|
|
236
238
|
/**
|
|
@@ -264,11 +266,9 @@ class OcflStorageImpl extends OcflStorage {
|
|
|
264
266
|
if (options?.ocflSpecText) {
|
|
265
267
|
|
|
266
268
|
}
|
|
269
|
+
return this;
|
|
267
270
|
}
|
|
268
271
|
|
|
269
|
-
/**
|
|
270
|
-
* @return {AsyncIterator<OcflObject, OcflObject>}
|
|
271
|
-
*/
|
|
272
272
|
[Symbol.asyncIterator]() {
|
|
273
273
|
let store = this.#store;
|
|
274
274
|
let workspace = this.#workspace;
|
|
@@ -276,6 +276,7 @@ class OcflStorageImpl extends OcflStorage {
|
|
|
276
276
|
let root = this.root;
|
|
277
277
|
let stack = [this.#store.opendir(this.root)];
|
|
278
278
|
return {
|
|
279
|
+
[Symbol.asyncIterator]() { return this; },
|
|
279
280
|
async next() {
|
|
280
281
|
let dirp;
|
|
281
282
|
while ((dirp = stack.pop())) {
|
package/lib/types.d.ts
CHANGED
|
@@ -42,3 +42,12 @@ interface ReadFile {
|
|
|
42
42
|
| BufferEncoding
|
|
43
43
|
): Promise<string>;
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
type StorageLayout = {
|
|
47
|
+
FlatDirectStorageLayout: typeof import('./extensions/0002-flat-direct-storage-layout').FlatDirectStorageLayout
|
|
48
|
+
HashAndIdNTupleStorageLayout: typeof import('./extensions/0003-hash-and-id-n-tuple-storage-layout').HashAndIdNTupleStorageLayout
|
|
49
|
+
HashedNTupleStorageLayout: typeof import('./extensions/0004-hashed-n-tuple-storage-layout').HashedNTupleStorageLayout
|
|
50
|
+
FlatOmitPrefixStorageLayout: typeof import('./extensions/0006-flat-omit-prefix-storage-layout').FlatOmitPrefixStorageLayout
|
|
51
|
+
NTupleOmitPrefixStorageLayout: typeof import('./extensions/0007-n-tuple-omit-prefix-storage-layout').NTupleOmitPrefixStorageLayout
|
|
52
|
+
PathDirectStorageLayout: typeof import('./extensions/000N-path-direct-storage-layout').PathDirectStorageLayout
|
|
53
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ocfl/ocfl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Oxford Common File Layout (OCFL) JS library",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
@@ -33,11 +33,13 @@
|
|
|
33
33
|
"Peter Sefton (https://orcid.org/0000-0002-3545-944X)"
|
|
34
34
|
],
|
|
35
35
|
"license": "GPL-3.0-or-later",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"blake2": "^4.1.1"
|
|
38
|
+
},
|
|
36
39
|
"devDependencies": {
|
|
37
40
|
"@types/mocha": "^9.1.1",
|
|
38
41
|
"@types/node": "^17.0.33",
|
|
39
|
-
"
|
|
40
|
-
"jsdoc": "^3.6.10",
|
|
42
|
+
"typedoc": "^0.23.15",
|
|
41
43
|
"mocha": "^10.0.0"
|
|
42
44
|
},
|
|
43
45
|
"mocha": {
|
|
@@ -48,9 +50,6 @@
|
|
|
48
50
|
],
|
|
49
51
|
"recursive": true
|
|
50
52
|
},
|
|
51
|
-
"dependencies": {
|
|
52
|
-
"blake2": "^4.1.1"
|
|
53
|
-
},
|
|
54
53
|
"bugs": {
|
|
55
54
|
"url": "https://github.com/Arkisto-Platform/ocfl-js/issues"
|
|
56
55
|
},
|
|
@@ -59,5 +58,10 @@
|
|
|
59
58
|
"lib": "lib",
|
|
60
59
|
"test": "test"
|
|
61
60
|
},
|
|
62
|
-
"files": [
|
|
61
|
+
"files": [
|
|
62
|
+
"index.js",
|
|
63
|
+
"index.mjs",
|
|
64
|
+
"lib",
|
|
65
|
+
"resources"
|
|
66
|
+
]
|
|
63
67
|
}
|