@ocfl/ocfl 0.4.0 → 1.0.0-beta.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.
Files changed (138) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +24 -9
  3. package/dist/constants.d.ts +15 -0
  4. package/dist/constants.d.ts.map +1 -0
  5. package/dist/constants.js +14 -0
  6. package/dist/constants.js.map +1 -0
  7. package/dist/digest.d.ts +58 -0
  8. package/dist/digest.d.ts.map +1 -0
  9. package/dist/digest.js +204 -0
  10. package/dist/digest.js.map +1 -0
  11. package/dist/error.d.ts +5 -0
  12. package/dist/error.d.ts.map +1 -0
  13. package/dist/error.js +9 -0
  14. package/dist/error.js.map +1 -0
  15. package/dist/extension.d.ts +82 -0
  16. package/dist/extension.d.ts.map +1 -0
  17. package/dist/extension.js +169 -0
  18. package/dist/extension.js.map +1 -0
  19. package/dist/extensions/0002-flat-direct-storage-layout.d.ts +12 -0
  20. package/dist/extensions/0002-flat-direct-storage-layout.d.ts.map +1 -0
  21. package/dist/extensions/0002-flat-direct-storage-layout.js +34 -0
  22. package/dist/extensions/0002-flat-direct-storage-layout.js.map +1 -0
  23. package/dist/extensions/0003-hash-and-id-n-tuple-storage-layout.d.ts +15 -0
  24. package/dist/extensions/0003-hash-and-id-n-tuple-storage-layout.d.ts.map +1 -0
  25. package/dist/extensions/0003-hash-and-id-n-tuple-storage-layout.js +49 -0
  26. package/dist/extensions/0003-hash-and-id-n-tuple-storage-layout.js.map +1 -0
  27. package/dist/extensions/0004-hashed-n-tuple-storage-layout.d.ts +17 -0
  28. package/dist/extensions/0004-hashed-n-tuple-storage-layout.d.ts.map +1 -0
  29. package/dist/extensions/0004-hashed-n-tuple-storage-layout.js +54 -0
  30. package/dist/extensions/0004-hashed-n-tuple-storage-layout.js.map +1 -0
  31. package/dist/extensions/0006-flat-omit-prefix-storage-layout.d.ts +6 -0
  32. package/dist/extensions/0006-flat-omit-prefix-storage-layout.d.ts.map +1 -0
  33. package/dist/extensions/0006-flat-omit-prefix-storage-layout.js +8 -0
  34. package/dist/extensions/0006-flat-omit-prefix-storage-layout.js.map +1 -0
  35. package/dist/extensions/0007-n-tuple-omit-prefix-storage-layout.d.ts +6 -0
  36. package/dist/extensions/0007-n-tuple-omit-prefix-storage-layout.d.ts.map +1 -0
  37. package/dist/extensions/0007-n-tuple-omit-prefix-storage-layout.js +8 -0
  38. package/dist/extensions/0007-n-tuple-omit-prefix-storage-layout.js.map +1 -0
  39. package/dist/extensions/0009-digest-algorithms.d.ts +9 -0
  40. package/dist/extensions/0009-digest-algorithms.d.ts.map +1 -0
  41. package/dist/extensions/0009-digest-algorithms.js +11 -0
  42. package/dist/extensions/0009-digest-algorithms.js.map +1 -0
  43. package/dist/extensions/000N-path-direct-storage-layout.d.ts +16 -0
  44. package/dist/extensions/000N-path-direct-storage-layout.d.ts.map +1 -0
  45. package/dist/extensions/000N-path-direct-storage-layout.js +46 -0
  46. package/dist/extensions/000N-path-direct-storage-layout.js.map +1 -0
  47. package/dist/extensions/index.d.ts +23 -0
  48. package/dist/extensions/index.d.ts.map +1 -0
  49. package/dist/extensions/index.js +8 -0
  50. package/dist/extensions/index.js.map +1 -0
  51. package/dist/file.d.ts +87 -0
  52. package/dist/file.d.ts.map +1 -0
  53. package/dist/file.js +118 -0
  54. package/dist/file.js.map +1 -0
  55. package/dist/index.d.ts +61 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +73 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/inventory.d.ts +155 -0
  60. package/dist/inventory.d.ts.map +1 -0
  61. package/dist/inventory.js +591 -0
  62. package/dist/inventory.js.map +1 -0
  63. package/dist/object.d.ts +188 -0
  64. package/dist/object.d.ts.map +1 -0
  65. package/dist/object.js +425 -0
  66. package/dist/object.js.map +1 -0
  67. package/dist/storage.d.ts +94 -0
  68. package/dist/storage.d.ts.map +1 -0
  69. package/dist/storage.js +302 -0
  70. package/dist/storage.js.map +1 -0
  71. package/dist/store.d.ts +100 -0
  72. package/dist/store.d.ts.map +1 -0
  73. package/dist/store.js +157 -0
  74. package/dist/store.js.map +1 -0
  75. package/dist/transaction.d.ts +155 -0
  76. package/dist/transaction.d.ts.map +1 -0
  77. package/dist/transaction.js +394 -0
  78. package/dist/transaction.js.map +1 -0
  79. package/dist/types.d.ts +107 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +2 -0
  82. package/dist/types.js.map +1 -0
  83. package/dist/utils.d.ts +24 -0
  84. package/dist/utils.d.ts.map +1 -0
  85. package/dist/utils.js +85 -0
  86. package/dist/utils.js.map +1 -0
  87. package/dist/validation.d.ts +32 -0
  88. package/dist/validation.d.ts.map +1 -0
  89. package/dist/validation.js +31 -0
  90. package/dist/validation.js.map +1 -0
  91. package/package.json +31 -51
  92. package/src/constants.ts +16 -0
  93. package/src/digest.ts +258 -0
  94. package/src/error.ts +9 -0
  95. package/src/extension.ts +204 -0
  96. package/{lib/extensions/0002-flat-direct-storage-layout.js → src/extensions/0002-flat-direct-storage-layout.ts} +15 -22
  97. package/src/extensions/0003-hash-and-id-n-tuple-storage-layout.ts +56 -0
  98. package/src/extensions/0004-hashed-n-tuple-storage-layout.ts +59 -0
  99. package/src/extensions/0006-flat-omit-prefix-storage-layout.ts +9 -0
  100. package/src/extensions/0007-n-tuple-omit-prefix-storage-layout.ts +9 -0
  101. package/src/extensions/0009-digest-algorithms.ts +12 -0
  102. package/src/extensions/000N-path-direct-storage-layout.ts +51 -0
  103. package/src/extensions/index.ts +24 -0
  104. package/src/file.ts +161 -0
  105. package/src/index.ts +92 -0
  106. package/src/inventory.ts +634 -0
  107. package/src/object.ts +473 -0
  108. package/src/storage.ts +342 -0
  109. package/src/store.ts +199 -0
  110. package/src/transaction.ts +455 -0
  111. package/{lib/types.d.ts → src/types.ts} +28 -74
  112. package/src/utils.ts +94 -0
  113. package/src/validation.ts +46 -0
  114. package/index.js +0 -129
  115. package/index.mjs +0 -18
  116. package/lib/constants.js +0 -24
  117. package/lib/digest.js +0 -307
  118. package/lib/enum.js +0 -90
  119. package/lib/error.js +0 -19
  120. package/lib/extension.js +0 -194
  121. package/lib/extensions/0003-hash-and-id-n-tuple-storage-layout.js +0 -60
  122. package/lib/extensions/0004-hashed-n-tuple-storage-layout.js +0 -63
  123. package/lib/extensions/0005-mutable-head.js +0 -0
  124. package/lib/extensions/0006-flat-omit-prefix-storage-layout.js +0 -7
  125. package/lib/extensions/0007-n-tuple-omit-prefix-storage-layout.js +0 -7
  126. package/lib/extensions/0008-schema-registry.js +0 -0
  127. package/lib/extensions/0009-digest-algorithms.js +0 -18
  128. package/lib/extensions/000N-path-direct-storage-layout.js +0 -61
  129. package/lib/extensions/index.js +0 -13
  130. package/lib/file.js +0 -147
  131. package/lib/index.js +0 -13
  132. package/lib/inventory.js +0 -564
  133. package/lib/object.js +0 -499
  134. package/lib/storage.js +0 -338
  135. package/lib/store.js +0 -191
  136. package/lib/transaction.js +0 -448
  137. package/lib/utils.js +0 -122
  138. package/lib/validation.js +0 -174
package/lib/storage.js DELETED
@@ -1,338 +0,0 @@
1
- //@ts-check
2
- //@todo add default layout
3
- const path = require("path");
4
- const validation = require('./validation.js');
5
- const { NotImplementedError } = require("./error");
6
- const { OcflStorageLayout } = require("./extension");
7
- const { HashedNTupleStorageLayout } = require("./extensions/0004-hashed-n-tuple-storage-layout");
8
- const { OcflObject } = require("./object");
9
- const { isDirEmpty, findNamasteVersion } = require("./utils.js");
10
- const { OCFL_VERSION, OCFL_VERSIONS, OCFL_LAYOUT,
11
- EXTENSIONS_DIR, EXTENSION_CONFIG,
12
- NAMASTE_PREFIX_STORAGE, NAMASTE_PREFIX_OBJECT, NAMASTE_T } = require('./constants').OcflConstants;
13
- const { OcflDigest } = require('./digest');
14
-
15
- const DEFAULT_LAYOUT = HashedNTupleStorageLayout;
16
-
17
- /** @typedef {import('./store').OcflStore} OcflStore */
18
- /** @typedef {import('./types.js').OcflExtensionConfig} OcflExtensionConfig */
19
- /** @typedef {import('./types.js').OcflVersion} OcflVersion */
20
-
21
-
22
- /**
23
- * An abstraction to represent the OCFL Storage Root, which is
24
- * a base directory used to store OCFL Objects, identified by a [NAMASTE] file “0=ocfl_1.1”.
25
- */
26
-
27
- class OcflStorage {
28
- //static LAYOUT;
29
- ocflVersion;
30
-
31
- /**
32
- * Get the storage root
33
- * @return {string}
34
- */
35
- get root() { throw new NotImplementedError(); }
36
-
37
- /**
38
- * Construct the path of the object root relative to the storage root
39
- * The path is mapped from the object identifier using the algorithm defined in the chosen
40
- * storage layout extension (specified in {@link OcflStorageConfig}).
41
- * @param {string} id - Identifier of the object
42
- * @return {string}
43
- */
44
- objectRoot(id) { throw new NotImplementedError(); }
45
-
46
- /**
47
- * Absolute path to the object root
48
- * @param {string} id - Identifier of the object
49
- */
50
- objectRootAbs(id) {
51
- return path.join(this.root, this.objectRoot(id));
52
- }
53
-
54
- /**
55
- * Get an existing object in the Storage or create a new one.
56
- * @param {string|{id?:string, root?:string}} opt - A unique identifier for the OCFL Object, should be a URI
57
- * @return {OcflObject}
58
- */
59
- object(opt) { throw new NotImplementedError(); }
60
-
61
- /**
62
- * Check if the storage has already the object with the given id.
63
- * @param {*} id
64
- */
65
- async has(id) {
66
- return this.object(id).exists();
67
- }
68
-
69
- /**
70
- * Create the storage root in the underlying storage backend
71
- * @param {Object} [options] - Additional options for creating storage root
72
- * @param {boolean} [options.ocflSpecText=false] - If true, create a copy of the OCFL specification text in the storage root
73
- * @return {Promise<OcflStorage>}
74
- */
75
- async create(options) { throw new NotImplementedError(); }
76
-
77
- /**
78
- * Check namaste, retrieve storage layout extension, and read its config file.
79
- * @return {Promise<OcflStorage>}
80
- */
81
- async load() { throw new NotImplementedError(); }
82
-
83
- /**
84
- * Check if the storage root path points to an existing file or non-empty directory in the underlying backend store.
85
- * The existing directory may or may not be a valid OCFL Storage.
86
- * @return {Promise<boolean>}
87
- */
88
- async exists() { throw new NotImplementedError(); }
89
-
90
- /**
91
- *
92
- * @return {AsyncIterableIterator<OcflObject>}
93
- */
94
- [Symbol.asyncIterator]() { throw new NotImplementedError(); }
95
-
96
- /**
97
- * Return a new AsyncIterator that contains all the OCFL objects in this Storage.
98
- * @return {AsyncIterableIterator<OcflObject>}
99
- */
100
- objects() {
101
- return this[Symbol.asyncIterator]();
102
- // const objects = [];
103
- // for await (const o of this) objects.push(o);
104
- // return objects;
105
- }
106
-
107
- async delete(id) {
108
- return this.remove(id);
109
- }
110
-
111
- async purge(id) {
112
- return this.remove(id);
113
- }
114
-
115
- async remove(id) { throw new NotImplementedError(); }
116
-
117
- };
118
-
119
- /**
120
- * @typedef {Object} OcflStorageConfig
121
- * @property {string} root - Absolute path to the ocfl storage root
122
- * @property {string} [workspace] - Absolute path to storage workspace directory
123
- * @property {OcflStorageLayout|OcflExtensionConfig|string} [layout] - A layout that identifies an arrangement of directories and OCFL objects under the storage root
124
- * @property {('sha256' | 'sha512')} [digestAlgorithm] - Digest algorithm for content-addressing, must use either sha512 or sha256
125
- * @property {string} [contentDirectory='content'] - Content directory name. Only applies to a newly created object.
126
- * @property {string} [ocflVersion=c.OCFL_VERSION] - Ocfl version. Only applies to a newly created object.
127
- * @property {string[]} [fixityAlgorithms] - A default list of digest algorithm names to be added to the fixity block of objects under this storage.
128
- */
129
-
130
- /**
131
- * General implementation of {@link OcflStorage} that can uses different datastore backends.
132
- * This class provides common functionalities for the subclasses and
133
- * at the same provide encapsulation emulating private and protected methods.
134
- */
135
- class OcflStorageImpl extends OcflStorage {
136
-
137
- /** @type {string} */
138
- #root;
139
- /** @type {string} */
140
- #workspace;
141
- /** @type {OcflStorageLayout} */
142
- #layout;
143
- /** @type {OcflStore} */
144
- #store;
145
- #objectConfig;
146
-
147
- /**
148
- *
149
- * @param {OcflStorageConfig} config
150
- * @param {OcflStore} store
151
- */
152
- constructor(config, store) {
153
- super();
154
- if (!store) throw new TypeError('[OcflStorage] store is required.');
155
- if (!config.root) throw new TypeError('[OcflStorage] config.root is required.');
156
- this.#store = store;
157
- const { root, workspace, layout, ocflVersion, ...objectConfig } = config;
158
- this.#root = path.resolve(root);
159
- this.#workspace = workspace ? path.resolve(workspace) : path.join(this.#root, 'extensions/workspace');
160
- if (this.#workspace && this.#workspace.startsWith(this.#root + path.sep) && !this.#workspace.startsWith(this.#root + path.sep + 'extensions' + path.sep)) {
161
- throw new Error('[OcflStorage] config.workspace cannot be the same as or a subpath of config.root');
162
- }
163
- if (layout) {
164
- this.#layout = layout instanceof OcflStorageLayout ? layout : this.#createLayout(layout);
165
- }
166
- this.ocflVersion = ocflVersion || OCFL_VERSION;
167
- this.#objectConfig = objectConfig;
168
- }
169
-
170
- /**
171
- *
172
- * @param {OcflExtensionConfig|string} option
173
- */
174
- #createLayout(option) {
175
- let name = typeof option === 'string' ? option : option?.extensionName;
176
- let config = typeof option === 'object' ? option : null;
177
- if (name) {
178
- return OcflStorageLayout.class(name).create(config);
179
- }
180
- // else if (useDefault) {
181
- // return DEFAULT_LAYOUT.create(config);
182
- // }
183
- }
184
-
185
- get root() { return this.#root; }
186
-
187
- objectRoot(id) {
188
- if (!this.#layout) throw new Error('[OcflStorage] No layout defined');
189
- return this.#layout.map(id);
190
- }
191
-
192
- /**
193
- * The root param is a relative path to the storage root.
194
- * @param {string|{id?:string, root?:string}} opt
195
- */
196
- object(opt) {
197
- let id, root;
198
- if (typeof opt === 'string') id = opt;
199
- else ({ id, root } = opt);
200
- let relObjectRoot = root || this.objectRoot(id);
201
- return new OcflObject({
202
- id,
203
- root: path.join(this.root, relObjectRoot),
204
- // @todo:use extension workspace if not defined
205
- workspace: this.#workspace ? path.join(this.#workspace, relObjectRoot) : undefined,
206
- ocflVersion: /** @type {OcflVersion} */(this.ocflVersion),
207
- ...this.#objectConfig
208
- }, this.#store);
209
- }
210
-
211
- async exists() {
212
- return !(await isDirEmpty(this.#store, this.root));
213
- }
214
-
215
- async load() {
216
- let prefix = NAMASTE_PREFIX_STORAGE;
217
- let tasks = [
218
- findNamasteVersion(this.#store, prefix, this.root),
219
- this.#store.readFile(path.join(this.root, OCFL_LAYOUT), 'utf8')
220
- ];
221
- // @ts-ignore
222
- let [ocflVersion, layout] = (await Promise.allSettled(tasks)).map(r => r.value);
223
- if (!ocflVersion) throw new Error('Invalid storage root');//throw validation.createError(67, this.root);
224
- let layoutName, layoutConfig;
225
- // load layout
226
- try {
227
- if (layout) layoutName = JSON.parse(layout).extension;
228
- } catch (error) {
229
- }
230
- // load ext config if exists
231
- try {
232
- let cfgstr = await this.#store.readFile(path.join(this.root, EXTENSIONS_DIR, layoutName, EXTENSION_CONFIG), 'utf8');
233
- layoutConfig = JSON.parse(/**@type{string}*/(cfgstr));
234
- } catch (error) {
235
- }
236
- this.#layout = this.#createLayout(layoutConfig || layoutName);
237
- const layoutDigestAlgorithm = this.#layout.get('digestAlgorithm');
238
- if (layoutDigestAlgorithm) await OcflDigest.initSync(layoutDigestAlgorithm);
239
- //@todo: load storage level extensions
240
-
241
- return this;
242
- }
243
-
244
- /**
245
- * @param {Object} [options] - Additional options for creating storage root
246
- * @param {boolean} [options.ocflSpecText=false] - If true, create a copy of the OCFL specification text in the storage root
247
- */
248
- async create(options) {
249
- if (await this.exists()) {
250
- //cannot create, storage root already exists .
251
- throw new Error('[OcflStorage] Cannot create storage root in a non-empty directory');
252
- } else {
253
- await this.#store.mkdir(this.root);
254
- }
255
- // create namaste
256
- let prefix = NAMASTE_PREFIX_STORAGE;
257
- let filenamePrefix = NAMASTE_T + prefix;
258
- let filePath = path.join(this.root, filenamePrefix + this.ocflVersion);
259
- await this.#store.writeFile(filePath, prefix + this.ocflVersion + '\n', 'utf8');
260
-
261
- // create layout
262
- if (!this.#layout) {
263
- this.#layout = new DEFAULT_LAYOUT();
264
- }
265
- const layoutDigestAlgorithm = this.#layout.get('digestAlgorithm');
266
- if (layoutDigestAlgorithm) await OcflDigest.initSync(layoutDigestAlgorithm);
267
- let layout = { extension: this.#layout.name, description: this.#layout.description };
268
- await this.#store.writeFile(path.join(this.root, OCFL_LAYOUT), JSON.stringify(layout, null, 2), 'utf8');
269
- if (this.#layout.config) {
270
- await this.#store.writeFile(path.join(this.root, EXTENSIONS_DIR, this.#layout.name, EXTENSION_CONFIG), JSON.stringify(this.#layout.config, null, 2), 'utf8');
271
- }
272
-
273
- // todo: create other extensions
274
- if (options?.ocflSpecText) {
275
-
276
- }
277
- return this;
278
- }
279
-
280
- /**
281
- * Allow async iteration over all OCFL objects in this storage.
282
- */
283
- [Symbol.asyncIterator]() {
284
- let store = this.#store;
285
- let workspace = this.#workspace;
286
- let config = this.#objectConfig;
287
- let root = this.root;
288
- let stack = [this.#store.opendir(this.root)];
289
- return {
290
- [Symbol.asyncIterator]() { return this; },
291
- async next() {
292
- let dirp;
293
- while ((dirp = stack.pop())) {
294
- let dir = await dirp;
295
- let dirent = await dir.read();
296
- if (!dirent) {
297
- await dir.close();
298
- continue;
299
- }
300
- stack.push(dirp);
301
- if (!dirent.isDirectory()) continue;
302
- let basePath = path.join(dir.path, dirent.name);
303
- let nv;
304
- try {
305
- nv = await findNamasteVersion(store, NAMASTE_PREFIX_OBJECT, basePath);
306
- } catch (err) {
307
- }
308
- if (nv) {
309
- //ocfl object exists
310
- // inventory exists
311
- let object = new OcflObject({
312
- root: basePath,
313
- workspace: workspace ? path.join(workspace, path.relative(root, basePath)) : undefined,
314
- ocflVersion: /** @type {OcflVersion} */(nv),
315
- ...config
316
- }, store);
317
- //await object.load();
318
- return { done: false, value: object };
319
- } else {
320
- //ocfl object does not exist, process subdir
321
- stack.push(store.opendir(basePath));
322
- }
323
-
324
- }
325
- return { done: true, value: null };
326
- }
327
- // return() {
328
- // return { done: true };
329
- // }
330
- };
331
- }
332
-
333
- }
334
-
335
- module.exports = {
336
- OcflStorage,
337
- OcflStorageImpl
338
- };
package/lib/store.js DELETED
@@ -1,191 +0,0 @@
1
- const path = require('path');
2
- const { parallelize, joinTypedArray } = require('./utils');
3
-
4
- const emptyOptions = {};
5
-
6
- /**
7
- * Abstract class to provide common APIs to access and modify the actual data store backend
8
- * such as local file system and cloud storage
9
- */
10
- class OcflStore {
11
- /** @type {Map<Object, OcflStore>} */
12
- static instances;
13
-
14
- /**
15
- *
16
- * @param {Object} [options]
17
- */
18
- static getInstance(options = emptyOptions) {
19
- if (!this.instances) return new this(options);
20
- let store = this.instances.get(options);
21
- if (!store) {
22
- store = new this(options);
23
- this.instances.set(options, store);
24
- }
25
- return store;
26
- }
27
-
28
- constructor(options) { }
29
-
30
- /**
31
- * Get file information.
32
- * @param {string} filePath
33
- * @return {Promise<import('fs').Stats>}
34
- */
35
- async stat(filePath) { throw new Error('Not Implemented'); }
36
-
37
- /**
38
- * Check if file exists
39
- * @param {string} filePath
40
- */
41
- async exists(filePath) {
42
- try {
43
- await this.stat(filePath);
44
- return true;
45
- } catch (error) {
46
- return false;
47
- }
48
- }
49
-
50
- /**
51
- * Create a readable stream to get the content of a file
52
- * @param {string} filePath - Absolute path
53
- * @param {*} options
54
- * @return {Promise<import('fs').ReadStream>}
55
- * @deprecated Use {@link createReadable()} instead
56
- */
57
- async createReadStream(filePath, options) { throw new Error('Not Implemented'); }
58
-
59
- /**
60
- * Create a stream that writes data to {@link relPath}.
61
- * @param {string} relPath
62
- * @param {*} options
63
- * @return {Promise<import('fs').WriteStream>}
64
- * @deprecated Use {@link createWritable()} instead
65
- */
66
- async createWriteStream(relPath, options) { throw new Error('Not Implemented'); }
67
-
68
- /**
69
- * Create a ReadableStream to get the content of a file
70
- * @param {string} filePath - Absolute path
71
- * @param {*} options
72
- * @return {Promise<ReadableStream>}
73
- */
74
- async createReadable(filePath, options) { throw new Error('Not Implemented'); }
75
-
76
- /**
77
- * Create a WritableStream that writes data to {@link relPath}.
78
- * @param {string} relPath
79
- * @param {*} options
80
- * @return {Promise<WritableStream>}
81
- */
82
- async createWritable(relPath, options) { throw new Error('Not Implemented'); }
83
-
84
- /**
85
- * Provide a common interface to read a file inside an object.
86
- * A concrete subclass MAY implement this method to provide read access to its underlying storage backend.
87
- * The default implementation uses the {@linkcode OcflStore#createReadable} method.
88
- * @param {string} filePath
89
- * @param {*} [options]
90
- */
91
- async readFile(filePath, options) {
92
- const rs = await this.createReadable(filePath, options);
93
- let buffer = (typeof options === 'string' || options.encoding) ? '' : new Uint8Array(new ArrayBuffer(0, { maxByteLength: 16 * 1024 }));
94
- for await (const chunk of rs) {
95
- if (typeof chunk === 'string') {
96
- if (typeof buffer !== 'string') buffer = new TextDecoder().decode(buffer);
97
- buffer += chunk;
98
- } else {
99
- if (typeof buffer === 'string') buffer = new TextEncoder().encode(buffer);
100
- // @ts-ignore
101
- buffer = joinTypedArray(buffer, chunk);
102
- }
103
- }
104
- return buffer;
105
- }
106
-
107
- /** @typedef {string|Buffer|Uint8Array|DataView|AsyncIterable|Iterable|ReadableStream} WriteFileData */
108
- /**
109
- * Provide a common interface to write a file inside an object.
110
- * A concrete subclass MAY implement this method to provide write access to its underlying storage backend.
111
- * The default implementation uses the {@link OcflStore.createWriteStream} method.
112
- * @param {string} filePath - Absolute path to the file.
113
- * @param {WriteFileData} data - The data to be written to the file.
114
- * @param {Object|string} options
115
- */
116
- async writeFile(filePath, data, options) {
117
- await this.mkdir(path.dirname(filePath));
118
- const target = await this.createWritable(filePath, options);
119
- if (data instanceof ReadableStream) {
120
- await data.pipeTo(target);
121
- } else {
122
- const w = target.getWriter();
123
- await w.write(data);
124
- await w.close();
125
- }
126
- }
127
-
128
- /**
129
- * Copy file from `source` to `target`.
130
- * By default, target is overwritten if it already exists.
131
- * @param {string} source - source filename to copy
132
- * @param {string} target - destination filename of the copy operation
133
- */
134
- async copyFile(source, target) {
135
- await this.writeFile(target, await this.createReadable(source));
136
- }
137
-
138
- /**
139
- * Open a directory
140
- * @param {string} filePath
141
- * @param {*} options
142
- * @return {Promise<import('fs').Dir> }
143
- */
144
- async opendir(filePath, options) { throw new Error('Not Implemented'); }
145
-
146
- /**
147
- * Read a directory
148
- * @param {string} filePath
149
- * @param {*} options
150
- * @return {Promise<string[]> }
151
- */
152
- async readdir(filePath, options) { throw new Error('Not Implemented'); }
153
-
154
- /**
155
- * List all files contained in a directory including the metadata such as size and last modified date.
156
- * The returned file.path is a relative path to the dirPath
157
- * @param {string} dirPath
158
- * @param {object} [options]
159
- * @param {BufferEncoding} [options.encoding]
160
- * @param {number} [options.bufferSize]
161
- * @param {boolean} [options.recursive]
162
- * @return {Promise<AsyncIterableIterator<{name: string, path: string, size: number, lastModified: Date}>> }
163
- */
164
- async list(dirPath, { encoding='utf8', bufferSize=32, recursive=false} = {}) { throw new Error('Not Implemented'); }
165
-
166
- /**
167
- * Recursively create a directory if the storage backend supports it, otherwise do nothing
168
- * @param {string} filePath - The directory path
169
- * @param {*} [options] - Options to be passed to the underlying method
170
- * @return {Promise<string>} - The first directory path created
171
- */
172
- async mkdir(filePath, options) { throw new Error('Not Implemented'); }
173
-
174
- /**
175
- * Rename or move a file or directory
176
- * @param {string} source
177
- * @param {string} target
178
- */
179
- async move(source, target) { throw new Error('Not Implemented'); }
180
-
181
- /**
182
- * Remove a file or directory recursively
183
- * @param {*} filePath
184
- */
185
- async remove(filePath) { throw new Error('Not Implemented'); }
186
-
187
- }
188
-
189
- module.exports = {
190
- OcflStore
191
- };