@ocfl/ocfl 0.3.0 → 0.4.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/lib/file.js CHANGED
@@ -9,6 +9,14 @@
9
9
  * @property {Object.<string, string>} [fixity] - Fixity information of the file.
10
10
  */
11
11
 
12
+ /**
13
+ * @typedef {Object} FileStat
14
+ * @property {number} [size] - Size of the file in bytes.
15
+ * @property {Date} [atime] - Last access time of the file.
16
+ * @property {Date} [mtime] - Last modified time of the file.
17
+ * @property {Date} [ctime] - Creation time of the file.
18
+ */
19
+
12
20
  /**
13
21
  * Represent a file in an OCFL object
14
22
  */
@@ -122,6 +130,16 @@ class OcflObjectFile {
122
130
  async stream(options) {
123
131
  return this.#ocflObject.createReadable(await this.#resolveContentPath(), options);
124
132
  }
133
+
134
+ /**
135
+ * Get the file stat info
136
+ * @param {*} [options] Options to be passed to underlying data store specific implementation
137
+ * @return {Promise<FileStat>}
138
+ */
139
+ async stat(options) {
140
+ return this.#ocflObject.stat(await this.#resolveContentPath());
141
+ }
142
+
125
143
  }
126
144
 
127
145
  module.exports = {
package/lib/object.js CHANGED
@@ -190,7 +190,7 @@ class OcflObject {
190
190
  * @param {*} inventory
191
191
  * @param {*} version
192
192
  */
193
- _setInventory(inventory, version='latest') {
193
+ _setInventory(inventory, version = 'latest') {
194
194
  //this._inventory['latest'] = this._inventory[inventory.head] = inventory;
195
195
  this._inventory[version] = inventory;
196
196
  if (version === 'latest') this._inventory[inventory.head] = inventory;
@@ -347,25 +347,65 @@ class OcflObject {
347
347
  }
348
348
 
349
349
  /**
350
- * Get a file by either the [logical path and version], digest, or content path.
350
+ * Return a file representation by the content path and version,
351
+ * @param { string } contentPath
352
+ * @param { string } [version='latest']
353
+ */
354
+ async fileByContentPath(contentPath, version) {
355
+ const inv = await this.getInventory();
356
+ const fr = inv?.getFileByContentPath(contentPath, version);
357
+ if (fr) return new OcflObjectFile(this, fr);
358
+ };
359
+
360
+ /**
361
+ * Return a file representation by the digest and version,
362
+ * @param { string } digest
363
+ * @param { string } [version='latest']
364
+ */
365
+ async fileByDigest(digest, version) {
366
+ const inv = await this.getInventory();
367
+ const fr = inv?.getFileByDigest(digest, version);
368
+ if (fr) return new OcflObjectFile(this, fr);
369
+ };
370
+
371
+ /**
372
+ * Return a file representation by the logical path and version,
373
+ * @param { string } logicalPath
374
+ * @param { string } [version='latest']
375
+ */
376
+ async fileByLogicalPath(logicalPath, version) {
377
+ const inv = await this.getInventory();
378
+ const fr = inv?.getFile(logicalPath, version);
379
+ if (fr) return new OcflObjectFile(this, fr);
380
+ };
381
+
382
+ /**
383
+ * Return a file representation by either the [logical path and version], digest, or content path.
384
+ * The returned file object can be used to retrieve the content of a file either as string, buffer, or stream.
385
+ * If the object inventory file is not loaded, this file object will not include the full file metadata information.
351
386
  * If version is omitted, it defaults to the last version.
352
387
  * @param { LogicalPath | FileRefLogical | FileRefDigest | FileRefContent } opt A choice of logical path (eg: 'test') and version (eg: 'v1'),
353
388
  * digest of the file content, or content path (eg: 'v1/content/test')
354
389
  * @param {string} [version='latest'] The object version name, eg: 'v1', 'v2'. Default to 'latest'. Only used if opt is a LogicalPath.
355
- * @returns {OcflObjectFile}
390
+ * @param {string} [lazy] If true, always return a file instance even if the object inventory file is not loaded.
356
391
  */
357
- getFile(opt, version) {
392
+ getFile(opt, version, lazy) {
358
393
  const inv = this.inventory;
359
394
  /** @type {any} */
360
- let file = typeof opt === 'string' ? { logicalPath: opt, version: version } : { ...opt };
361
- if (file.logicalPath) {
362
- file = inv?.getFile(file.logicalPath, file.version);
363
- } else if (file.digest) {
364
- file = inv?.getFileByDigest(file.digest, file.version);
365
- } else if (file.contentPath) {
366
- file = inv?.getFileByContentPath(file.contentPath, file.version);
395
+ const file = typeof opt === 'string' ? { logicalPath: opt, version: version } : { ...opt };
396
+ if (inv) {
397
+ let fr;
398
+ if (file.logicalPath) {
399
+ fr = inv?.getFile(file.logicalPath, file.version);
400
+ } else if (file.digest) {
401
+ fr = inv?.getFileByDigest(file.digest, file.version);
402
+ } else if (file.contentPath) {
403
+ fr = inv?.getFileByContentPath(file.contentPath, file.version);
404
+ }
405
+ if (fr) return new OcflObjectFile(this, fr);
406
+ } else if (lazy) {
407
+ return new OcflObjectFile(this, file);
367
408
  }
368
- if (file) return new OcflObjectFile(this, file);
369
409
  };
370
410
 
371
411
  /**
@@ -407,6 +447,14 @@ class OcflObject {
407
447
  return this.#store.readFile(path.join(this.root, relPath), options);
408
448
  };
409
449
 
450
+ /**
451
+ * Get the file metadata such as size and modification time.
452
+ * @param {string} relPath - The file path relative to the object root.
453
+ */
454
+ async stat(relPath) {
455
+ return this.#store.stat(path.join(this.root, relPath));
456
+ };
457
+
410
458
  toString() { return `OcflObject { root: ${this.root}, id: ${this.id} }`; }
411
459
 
412
460
  toJSON() { return { root: this.root, id: this.id }; }
package/lib/utils.js CHANGED
@@ -1,8 +1,7 @@
1
1
  //@ts-check
2
2
  'use strict';
3
3
 
4
- const path = require('path');
5
- const validation = require('./validation.js');
4
+ //const validation = require('./validation.js');
6
5
  const { OCFL_VERSIONS, NAMASTE_T } = require('./constants').OcflConstants;
7
6
 
8
7
 
@@ -58,7 +57,7 @@ async function isDirEmpty(store, dirPath) {
58
57
  * @param {string} rootPath
59
58
  */
60
59
  async function findNamasteVersion(store, prefix, rootPath) {
61
- let namastePath = path.join(rootPath, NAMASTE_T + prefix);
60
+ let namastePath = rootPath + '/' + NAMASTE_T + prefix;
62
61
  let version;
63
62
  try {
64
63
  version = await Promise.any(OCFL_VERSIONS.map(async (v) =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ocfl/ocfl",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Oxford Common File Layout (OCFL) JS library",
5
5
  "main": "index.js",
6
6
  "exports": {
@@ -15,6 +15,7 @@
15
15
  },
16
16
  "scripts": {
17
17
  "test": "mocha",
18
+ "build": "tsc",
18
19
  "build-docs": "typedoc --plugin typedoc-plugin-missing-exports"
19
20
  },
20
21
  "keywords": [
@@ -39,10 +40,10 @@
39
40
  },
40
41
  "devDependencies": {
41
42
  "@types/mocha": "^10.0.10",
42
- "@types/node": "^24",
43
+ "@types/node": "^24.12.2",
43
44
  "memfs": "^4.50.0",
44
45
  "mocha": "^11.7.5",
45
- "typedoc": "^0.28.15",
46
+ "typedoc": "^0.28.19",
46
47
  "typedoc-plugin-missing-exports": "^4.1.2"
47
48
  },
48
49
  "mocha": {
@@ -57,9 +58,6 @@
57
58
  "url": "https://github.com/Language-Research-Technology/ocfl-js/issues"
58
59
  },
59
60
  "homepage": "https://github.com/Language-Research-Technology/ocfl-js#readme",
60
- "engines": {
61
- "node": ">=18.0.0"
62
- },
63
61
  "directories": {
64
62
  "lib": "lib",
65
63
  "test": "test"
@@ -69,5 +67,8 @@
69
67
  "index.mjs",
70
68
  "lib",
71
69
  "resources"
72
- ]
70
+ ],
71
+ "engines": {
72
+ "node": ">=18.0.0"
73
+ }
73
74
  }