@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.
- package/LICENSE +674 -0
- package/README.md +24 -9
- package/dist/constants.d.ts +15 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +14 -0
- package/dist/constants.js.map +1 -0
- package/dist/digest.d.ts +58 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +204 -0
- package/dist/digest.js.map +1 -0
- package/dist/error.d.ts +5 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +9 -0
- package/dist/error.js.map +1 -0
- package/dist/extension.d.ts +82 -0
- package/dist/extension.d.ts.map +1 -0
- package/dist/extension.js +169 -0
- package/dist/extension.js.map +1 -0
- package/dist/extensions/0002-flat-direct-storage-layout.d.ts +12 -0
- package/dist/extensions/0002-flat-direct-storage-layout.d.ts.map +1 -0
- package/dist/extensions/0002-flat-direct-storage-layout.js +34 -0
- package/dist/extensions/0002-flat-direct-storage-layout.js.map +1 -0
- package/dist/extensions/0003-hash-and-id-n-tuple-storage-layout.d.ts +15 -0
- package/dist/extensions/0003-hash-and-id-n-tuple-storage-layout.d.ts.map +1 -0
- package/dist/extensions/0003-hash-and-id-n-tuple-storage-layout.js +49 -0
- package/dist/extensions/0003-hash-and-id-n-tuple-storage-layout.js.map +1 -0
- package/dist/extensions/0004-hashed-n-tuple-storage-layout.d.ts +17 -0
- package/dist/extensions/0004-hashed-n-tuple-storage-layout.d.ts.map +1 -0
- package/dist/extensions/0004-hashed-n-tuple-storage-layout.js +54 -0
- package/dist/extensions/0004-hashed-n-tuple-storage-layout.js.map +1 -0
- package/dist/extensions/0006-flat-omit-prefix-storage-layout.d.ts +6 -0
- package/dist/extensions/0006-flat-omit-prefix-storage-layout.d.ts.map +1 -0
- package/dist/extensions/0006-flat-omit-prefix-storage-layout.js +8 -0
- package/dist/extensions/0006-flat-omit-prefix-storage-layout.js.map +1 -0
- package/dist/extensions/0007-n-tuple-omit-prefix-storage-layout.d.ts +6 -0
- package/dist/extensions/0007-n-tuple-omit-prefix-storage-layout.d.ts.map +1 -0
- package/dist/extensions/0007-n-tuple-omit-prefix-storage-layout.js +8 -0
- package/dist/extensions/0007-n-tuple-omit-prefix-storage-layout.js.map +1 -0
- package/dist/extensions/0009-digest-algorithms.d.ts +9 -0
- package/dist/extensions/0009-digest-algorithms.d.ts.map +1 -0
- package/dist/extensions/0009-digest-algorithms.js +11 -0
- package/dist/extensions/0009-digest-algorithms.js.map +1 -0
- package/dist/extensions/000N-path-direct-storage-layout.d.ts +16 -0
- package/dist/extensions/000N-path-direct-storage-layout.d.ts.map +1 -0
- package/dist/extensions/000N-path-direct-storage-layout.js +46 -0
- package/dist/extensions/000N-path-direct-storage-layout.js.map +1 -0
- package/dist/extensions/index.d.ts +23 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +8 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/file.d.ts +87 -0
- package/dist/file.d.ts.map +1 -0
- package/dist/file.js +118 -0
- package/dist/file.js.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/inventory.d.ts +155 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +591 -0
- package/dist/inventory.js.map +1 -0
- package/dist/object.d.ts +188 -0
- package/dist/object.d.ts.map +1 -0
- package/dist/object.js +425 -0
- package/dist/object.js.map +1 -0
- package/dist/storage.d.ts +94 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +302 -0
- package/dist/storage.js.map +1 -0
- package/dist/store.d.ts +100 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +157 -0
- package/dist/store.js.map +1 -0
- package/dist/transaction.d.ts +155 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +394 -0
- package/dist/transaction.js.map +1 -0
- package/dist/types.d.ts +107 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +24 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +85 -0
- package/dist/utils.js.map +1 -0
- package/dist/validation.d.ts +32 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +31 -0
- package/dist/validation.js.map +1 -0
- package/package.json +31 -51
- package/src/constants.ts +16 -0
- package/src/digest.ts +258 -0
- package/src/error.ts +9 -0
- package/src/extension.ts +204 -0
- package/{lib/extensions/0002-flat-direct-storage-layout.js → src/extensions/0002-flat-direct-storage-layout.ts} +15 -22
- package/src/extensions/0003-hash-and-id-n-tuple-storage-layout.ts +56 -0
- package/src/extensions/0004-hashed-n-tuple-storage-layout.ts +59 -0
- package/src/extensions/0006-flat-omit-prefix-storage-layout.ts +9 -0
- package/src/extensions/0007-n-tuple-omit-prefix-storage-layout.ts +9 -0
- package/src/extensions/0009-digest-algorithms.ts +12 -0
- package/src/extensions/000N-path-direct-storage-layout.ts +51 -0
- package/src/extensions/index.ts +24 -0
- package/src/file.ts +161 -0
- package/src/index.ts +92 -0
- package/src/inventory.ts +634 -0
- package/src/object.ts +473 -0
- package/src/storage.ts +342 -0
- package/src/store.ts +199 -0
- package/src/transaction.ts +455 -0
- package/{lib/types.d.ts → src/types.ts} +28 -74
- package/src/utils.ts +94 -0
- package/src/validation.ts +46 -0
- package/index.js +0 -129
- package/index.mjs +0 -18
- package/lib/constants.js +0 -24
- package/lib/digest.js +0 -307
- package/lib/enum.js +0 -90
- package/lib/error.js +0 -19
- package/lib/extension.js +0 -194
- package/lib/extensions/0003-hash-and-id-n-tuple-storage-layout.js +0 -60
- package/lib/extensions/0004-hashed-n-tuple-storage-layout.js +0 -63
- package/lib/extensions/0005-mutable-head.js +0 -0
- package/lib/extensions/0006-flat-omit-prefix-storage-layout.js +0 -7
- package/lib/extensions/0007-n-tuple-omit-prefix-storage-layout.js +0 -7
- package/lib/extensions/0008-schema-registry.js +0 -0
- package/lib/extensions/0009-digest-algorithms.js +0 -18
- package/lib/extensions/000N-path-direct-storage-layout.js +0 -61
- package/lib/extensions/index.js +0 -13
- package/lib/file.js +0 -147
- package/lib/index.js +0 -13
- package/lib/inventory.js +0 -564
- package/lib/object.js +0 -499
- package/lib/storage.js +0 -338
- package/lib/store.js +0 -191
- package/lib/transaction.js +0 -448
- package/lib/utils.js +0 -122
- package/lib/validation.js +0 -174
package/lib/enum.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enumeration tool for working with a set of options
|
|
3
|
-
* @module enumeration
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// const COLOR = (c => {
|
|
7
|
-
// let r = /** @type {{[key in (typeof c)[number]]: string}} */({});
|
|
8
|
-
// return r;
|
|
9
|
-
// })(/** @type {const} */(['red', 'green', 'blue']));
|
|
10
|
-
// COLOR.blue
|
|
11
|
-
const constantsSymbol = Symbol('constants');
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Create enumeration type by passing the list of constants as arguments of string
|
|
15
|
-
* @template {readonly string[]} const T
|
|
16
|
-
* @param {T} constants
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
function enumeration(constants) {
|
|
20
|
-
class Enum {
|
|
21
|
-
/** @type {string} */
|
|
22
|
-
#name;
|
|
23
|
-
/** @type {number} */
|
|
24
|
-
#ordinal;
|
|
25
|
-
constructor(name, ordinal) {
|
|
26
|
-
this.#name = name;
|
|
27
|
-
this.#ordinal = ordinal;
|
|
28
|
-
//Object.defineProperty(this, 'name', { writable: false, enumerable: true, value: name });
|
|
29
|
-
//Object.defineProperty(this, 'ordinal', { writable: false, enumerable: true, value: ordinal });
|
|
30
|
-
}
|
|
31
|
-
get name() { return this.#name }
|
|
32
|
-
get ordinal() { return this.#ordinal }
|
|
33
|
-
toString() {
|
|
34
|
-
return this.name;
|
|
35
|
-
}
|
|
36
|
-
/** @returns {Iterator<string>} */
|
|
37
|
-
static [Symbol.iterator]() {
|
|
38
|
-
return this[constantsSymbol][Symbol.iterator]();
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/** @typedef { typeof Enum & {[key in T[number]]: Enum} } EnumType */
|
|
42
|
-
let count = 0;
|
|
43
|
-
for (let c of constants) {
|
|
44
|
-
Object.defineProperty(Enum, c, {
|
|
45
|
-
value: Object.freeze(new Enum(c, count++)),
|
|
46
|
-
writable: false,
|
|
47
|
-
enumerable: true
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
Object.defineProperty(Enum, constantsSymbol, {
|
|
51
|
-
value: constants,
|
|
52
|
-
writable: false,
|
|
53
|
-
enumerable: false
|
|
54
|
-
});
|
|
55
|
-
return /** @type {EnumType} */(Object.freeze(Enum));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Return an existing constant that represents the specified value
|
|
60
|
-
* @type {{<T extends abstract new() => any>(type: T, value: any): InstanceType<T>}}
|
|
61
|
-
*/
|
|
62
|
-
enumeration.of = function (type, value) {
|
|
63
|
-
if (value instanceof type && type[value.name]) return value;
|
|
64
|
-
else if (typeof value === 'string') {
|
|
65
|
-
return type[/**@type {string}*/(value)] || (() => {
|
|
66
|
-
for (let name in type) {
|
|
67
|
-
if (name.toUpperCase() === value.toUpperCase()) return type[name];
|
|
68
|
-
}
|
|
69
|
-
})();
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Return an existing constant based on the index
|
|
75
|
-
* @template T
|
|
76
|
-
* @param {new() => T} type
|
|
77
|
-
* @param {number} index
|
|
78
|
-
* @return {T}
|
|
79
|
-
*/
|
|
80
|
-
enumeration.at = function (type, index) {
|
|
81
|
-
return type[type[constantsSymbol][index]];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
enumeration.size = function (type) {
|
|
85
|
-
return type[constantsSymbol].length;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
exports.enumeration = enumeration;
|
|
89
|
-
exports.default = { ...enumeration };
|
|
90
|
-
//export default { ...enumeration };
|
package/lib/error.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
class ValidationError extends Error {
|
|
2
|
-
constructor(message) {
|
|
3
|
-
super(message);
|
|
4
|
-
this.name = 'ValidationError';
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
class NotImplementedError extends Error {
|
|
9
|
-
constructor(methodName) {
|
|
10
|
-
let msg = methodName ? 'Method ' + methodName + ' has not been implemented' : '';
|
|
11
|
-
super(msg);
|
|
12
|
-
this.name = 'NotImplementedError';
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = {
|
|
17
|
-
ValidationError,
|
|
18
|
-
NotImplementedError
|
|
19
|
-
};
|
package/lib/extension.js
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
const { NotImplementedError } = require("./error");
|
|
2
|
-
|
|
3
|
-
/** Index by Registered extension name */
|
|
4
|
-
const extensionByName = {};
|
|
5
|
-
/** Index by extension class name */
|
|
6
|
-
const extensionByClassName = {};
|
|
7
|
-
|
|
8
|
-
const storageLayout = {};
|
|
9
|
-
|
|
10
|
-
// class OcflExtensionConfig {
|
|
11
|
-
// /** User defined config */
|
|
12
|
-
// definedConfig;
|
|
13
|
-
// constructor(config) {
|
|
14
|
-
// this.definedConfig = config;
|
|
15
|
-
// }
|
|
16
|
-
|
|
17
|
-
// }
|
|
18
|
-
/** @typedef {import('../index.js').StorageLayout} StorageLayout */
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @template {{}} C
|
|
22
|
-
*/
|
|
23
|
-
class OcflExtension {
|
|
24
|
-
static #object = {};
|
|
25
|
-
static #storage = {};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Get an object-level extension
|
|
29
|
-
* @param {string} name - A registered extension name
|
|
30
|
-
*/
|
|
31
|
-
static object(name) {
|
|
32
|
-
return this.#object[name];
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Get an storage-level extension
|
|
36
|
-
* @param {string} name - A registered extension name
|
|
37
|
-
*/
|
|
38
|
-
static storage(name) {
|
|
39
|
-
return this.#storage[name];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** List all registered extension classes */
|
|
43
|
-
static get classes() {
|
|
44
|
-
return Object.values(extensionByName);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Find a registered extension with the specified name
|
|
49
|
-
* @param {string} name - extension class name or registered extension name
|
|
50
|
-
* @return {typeof OcflExtension} - the extension class
|
|
51
|
-
*/
|
|
52
|
-
static class(name) {
|
|
53
|
-
return extensionByName[name] || extensionByClassName[name];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Register an extension
|
|
58
|
-
* @param {typeof OcflExtension} extensionClass
|
|
59
|
-
*/
|
|
60
|
-
static register(extensionClass = this) {
|
|
61
|
-
let name = extensionClass.NAME;
|
|
62
|
-
extensionByName[name] = extensionClass;
|
|
63
|
-
extensionByClassName[extensionClass.name] = extensionClass;
|
|
64
|
-
// if (extensionClass.forObject) {
|
|
65
|
-
// if (this.#object[name]) throw new Error(`Extension ${name} already registered.`);
|
|
66
|
-
// this.#object[name] = extensionClass;
|
|
67
|
-
// }
|
|
68
|
-
// if (extensionClass.forStorage) {
|
|
69
|
-
// if (this.#storage[name]) throw new Error(`Extension ${name} already registered.`);
|
|
70
|
-
// this.#storage[name] = extensionClass;
|
|
71
|
-
// }
|
|
72
|
-
extensionClass.setup(require('./index.js'));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Create an instance of the extension
|
|
77
|
-
* @type {<T extends typeof OcflExtension>(this: T, config?: OcflExtensionConfig) => InstanceType<T>}
|
|
78
|
-
*/
|
|
79
|
-
static create = function (config) {
|
|
80
|
-
// @ts-ignore
|
|
81
|
-
if (!config?.extensionName || this.NAME === config.extensionName) return new this(config);
|
|
82
|
-
// @ts-ignore
|
|
83
|
-
return OcflExtension.class(config.extensionName).create(config);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
static get forObject() { return false; }
|
|
87
|
-
static get forStorage() { return false; }
|
|
88
|
-
static get NAME() { return '0000-example-extension' }
|
|
89
|
-
static get DESCRIPTION() { return 'Example extension' }
|
|
90
|
-
static async setup(ocfl) { };
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
* @param {OcflExtensionConfig} [config]
|
|
95
|
-
* @param {C} [defaultConfig]
|
|
96
|
-
*/
|
|
97
|
-
constructor(config, defaultConfig) {
|
|
98
|
-
/** @type {C} */
|
|
99
|
-
this.parameters = typeof defaultConfig === 'object' ? Object.create(/**@type{object}*/(defaultConfig)) : {};
|
|
100
|
-
if (typeof config === 'object') {
|
|
101
|
-
for (let k in config) {
|
|
102
|
-
if (k in defaultConfig) this.parameters[k] = config[k];
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** Return all the parameters in which the value has been set to non-default value */
|
|
108
|
-
get config() {
|
|
109
|
-
let paramNames = Object.keys(this.parameters);
|
|
110
|
-
if (paramNames.length > 0) {
|
|
111
|
-
return paramNames.reduce( (params, name) => (params[name] = this.parameters[name], params), {extensionName: this.name});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
get p() { return this.parameters; }
|
|
116
|
-
|
|
117
|
-
/** Extension registered name */
|
|
118
|
-
get name() { return /** @type {typeof OcflExtension}*/(this.constructor).NAME }
|
|
119
|
-
get description() { return /** @type {typeof OcflExtension}*/(this.constructor).DESCRIPTION }
|
|
120
|
-
get minOcflVersion() { return "1.0" }
|
|
121
|
-
get version() { return "1.0" }
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Get the specified parameter value
|
|
125
|
-
* @param {string} param - The extension parameter name
|
|
126
|
-
* @return {*}
|
|
127
|
-
*/
|
|
128
|
-
get(param) { return this.parameters[param]; }
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Set the specified parameter value
|
|
132
|
-
* @param {string} param - The extension parameter name
|
|
133
|
-
* @param {*} value - The extension parameter value
|
|
134
|
-
*/
|
|
135
|
-
set(param, value) { if (param in this.parameters) this.parameters[param] = value; }
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* @template {{}} C
|
|
141
|
-
* @extends {OcflExtension<C>}
|
|
142
|
-
*/
|
|
143
|
-
class OcflStorageLayout extends OcflExtension {
|
|
144
|
-
|
|
145
|
-
static get layout() {
|
|
146
|
-
return /** @type StorageLayout */(storageLayout);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
*
|
|
151
|
-
* @param {string} name
|
|
152
|
-
* @return {typeof OcflStorageLayout}
|
|
153
|
-
*/
|
|
154
|
-
static class(name) {
|
|
155
|
-
let c = super.class(name);
|
|
156
|
-
if (c && c.prototype instanceof OcflStorageLayout) return /** @type {typeof OcflStorageLayout} */(c);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
static get classes() {
|
|
160
|
-
return Object.values(storageLayout);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Register a storage layout extension
|
|
165
|
-
* @param {typeof OcflStorageLayout} extensionClass
|
|
166
|
-
*/
|
|
167
|
-
static register(extensionClass = this) {
|
|
168
|
-
super.register(extensionClass);
|
|
169
|
-
storageLayout[extensionClass.name] = extensionClass;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
static get forStorage() { return true; }
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
*
|
|
176
|
-
* @param {OcflExtensionConfig} [config]
|
|
177
|
-
* @param {C} [defaultConfig]
|
|
178
|
-
*/
|
|
179
|
-
constructor(config, defaultConfig) { super(config, defaultConfig); }
|
|
180
|
-
|
|
181
|
-
async validate() {}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Map an object identifier to a path
|
|
185
|
-
* @param {string} id - The identifier of the OCFL Object
|
|
186
|
-
* @return {string}
|
|
187
|
-
*/
|
|
188
|
-
map(id) { throw new NotImplementedError(); }
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
module.exports = {
|
|
192
|
-
OcflExtension,
|
|
193
|
-
OcflStorageLayout
|
|
194
|
-
};
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
const { OcflStorageLayout } = require("../extension");
|
|
2
|
-
const { OcflDigest } = require("../digest");
|
|
3
|
-
const { enumeration } = require("../enum");
|
|
4
|
-
const path = require("path");
|
|
5
|
-
|
|
6
|
-
function encodeIdentifier(id) {
|
|
7
|
-
return encodeURIComponent(id).toLowerCase().replace(/\./g, '%2e');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const DefaultConfig = {
|
|
11
|
-
extensionName: '0003-hash-and-id-n-tuple-storage-layout',
|
|
12
|
-
digestAlgorithm: 'sha256',
|
|
13
|
-
tupleSize: 3,
|
|
14
|
-
numberOfTuples: 3,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @extends {OcflStorageLayout<typeof DefaultConfig>}
|
|
19
|
-
*/
|
|
20
|
-
class HashAndIdNTupleStorageLayout extends OcflStorageLayout {
|
|
21
|
-
static get NAME() { return DefaultConfig.extensionName }
|
|
22
|
-
static get DESCRIPTION() {
|
|
23
|
-
return "OCFL object identifiers are hashed and encoded as lowercase hex strings." +
|
|
24
|
-
" These digests are then divided into N n-tuple segments," +
|
|
25
|
-
" which are used to create nested paths under the OCFL storage root." +
|
|
26
|
-
" Finally, the OCFL object identifier is percent-encoded to create a directory name for the OCFL object root.";
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {Partial<typeof DefaultConfig>} [config]
|
|
31
|
-
*/
|
|
32
|
-
constructor(config) {
|
|
33
|
-
super(config, DefaultConfig);
|
|
34
|
-
let c = this.parameters;
|
|
35
|
-
const algo = enumeration.of(OcflDigest.FIXITY, c.digestAlgorithm)?.name;
|
|
36
|
-
if (!algo) throw new Error('Invalid digestAlgorithm');
|
|
37
|
-
let digestLength = OcflDigest.getHexDigestLength(algo);
|
|
38
|
-
let p = c.numberOfTuples * c.tupleSize
|
|
39
|
-
if (p > digestLength) throw new Error('Product of numberOfTuples and tupleSize is greater than the number of characters in the hex encoded digest.');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @param {string} id
|
|
44
|
-
* @return {string}
|
|
45
|
-
*/
|
|
46
|
-
map(id) {
|
|
47
|
-
let digest = OcflDigest.digestSync(this.parameters.digestAlgorithm, id);
|
|
48
|
-
let segments = [];
|
|
49
|
-
let s = this.parameters.tupleSize;
|
|
50
|
-
let n = this.parameters.numberOfTuples;
|
|
51
|
-
let i;
|
|
52
|
-
for (i = 0; i < n; ++i) {
|
|
53
|
-
segments.push(digest.slice(s * i, s * i + s));
|
|
54
|
-
}
|
|
55
|
-
segments.push(encodeIdentifier(id));
|
|
56
|
-
return segments.join(path.sep);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
module.exports = { HashAndIdNTupleStorageLayout };
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
const { OcflStorageLayout } = require("../extension");
|
|
2
|
-
const { OcflDigest } = require("../digest");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const { enumeration } = require("../enum");
|
|
5
|
-
|
|
6
|
-
const DefaultConfig = {
|
|
7
|
-
extensionName: '0004-hashed-n-tuple-storage-layout',
|
|
8
|
-
digestAlgorithm: 'sha256',
|
|
9
|
-
tupleSize: 3,
|
|
10
|
-
numberOfTuples: 3,
|
|
11
|
-
shortObjectRoot: false
|
|
12
|
-
};
|
|
13
|
-
/** @typedef {Partial<typeof DefaultConfig>} HashedNTupleStorageLayoutConfig */
|
|
14
|
-
/**
|
|
15
|
-
* @extends {OcflStorageLayout<typeof DefaultConfig>}
|
|
16
|
-
*/
|
|
17
|
-
class HashedNTupleStorageLayout extends OcflStorageLayout {
|
|
18
|
-
static get NAME() { return DefaultConfig.extensionName; }
|
|
19
|
-
static get DESCRIPTION() {
|
|
20
|
-
return "OCFL object identifiers are hashed and encoded as lowercase hex strings." +
|
|
21
|
-
" These digests are then divided into N n-tuple segments," +
|
|
22
|
-
" which are used to create nested paths under the OCFL storage root.";
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
* @param {HashedNTupleStorageLayoutConfig} [config]
|
|
28
|
-
*/
|
|
29
|
-
constructor(config) {
|
|
30
|
-
super(config, DefaultConfig);
|
|
31
|
-
let c = this.parameters;
|
|
32
|
-
const algo = enumeration.of(OcflDigest.FIXITY, c.digestAlgorithm)?.name;
|
|
33
|
-
if (!algo) throw new Error('Invalid digestAlgorithm');
|
|
34
|
-
let digestLength = OcflDigest.getHexDigestLength(algo);
|
|
35
|
-
let p = c.numberOfTuples * c.tupleSize
|
|
36
|
-
if (p > digestLength) throw new Error('Product of numberOfTuples and tupleSize is greater than the number of characters in the hex encoded digest.');
|
|
37
|
-
else if (p === digestLength && c.shortObjectRoot) throw new Error('shortObjectRoot cannot be set to true');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param {string} id
|
|
42
|
-
* @return {string}
|
|
43
|
-
*/
|
|
44
|
-
map(id) {
|
|
45
|
-
let digest = OcflDigest.digestSync(this.parameters.digestAlgorithm, id);
|
|
46
|
-
let segments = [];
|
|
47
|
-
let s = this.parameters.tupleSize;
|
|
48
|
-
let n = this.parameters.numberOfTuples;
|
|
49
|
-
let i;
|
|
50
|
-
for (i = 0; i < n; ++i) {
|
|
51
|
-
segments.push(digest.slice(s * i, s * i + s));
|
|
52
|
-
}
|
|
53
|
-
if (this.parameters.shortObjectRoot) {
|
|
54
|
-
segments.push(digest.slice(s * i));
|
|
55
|
-
} else {
|
|
56
|
-
segments.push(digest);
|
|
57
|
-
}
|
|
58
|
-
return segments.join(path.sep);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
module.exports = { HashedNTupleStorageLayout };
|
|
File without changes
|
|
File without changes
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
|
|
3
|
-
const {OcflExtension} = require("../extension");
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Notes: this implementation does nothing because the 0009 extension is implemented directly in the OcflDigest class.
|
|
7
|
-
*/
|
|
8
|
-
class DigestAlgorithm extends OcflExtension {
|
|
9
|
-
static get NAME() { return '0009-digest-algorithms' }
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* @param {import('ocfl')} ocfl
|
|
14
|
-
*/
|
|
15
|
-
static async setup(ocfl) {}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
module.exports = { DigestAlgorithm };
|
|
@@ -1,61 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module.exports = {
|
|
3
|
-
...require('./0009-digest-algorithms'),
|
|
4
|
-
...require('./0002-flat-direct-storage-layout'),
|
|
5
|
-
...require('./0003-hash-and-id-n-tuple-storage-layout'),
|
|
6
|
-
...require('./0004-hashed-n-tuple-storage-layout'),
|
|
7
|
-
// ...require('./0005-mutable-head'),
|
|
8
|
-
...require('./0006-flat-omit-prefix-storage-layout'),
|
|
9
|
-
...require('./0007-n-tuple-omit-prefix-storage-layout'),
|
|
10
|
-
...require('./000N-path-direct-storage-layout')
|
|
11
|
-
//...require('./0008-schema-registry')
|
|
12
|
-
};
|
|
13
|
-
//const { DigestAlgorithm } = require('./0001-digest-algorithms.js');
|
package/lib/file.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {Object} FileRef
|
|
3
|
-
* @property {string} [contentPath] - Actual path to the file location relative to the ocfl object root.
|
|
4
|
-
* @property {string} [logicalPath] - A path that represents a file’s location in the logical state of an object.
|
|
5
|
-
* @property {string} [digest] - An algorithmic characterization of the contents of a file conforming to a standard digest algorithm.
|
|
6
|
-
* @property {string} [version] - Version of the OCFL object.
|
|
7
|
-
* @property {string} [lastModified] - Last modified date of the file.
|
|
8
|
-
* @property {string} [size] - Size of the file in bytes.
|
|
9
|
-
* @property {Object.<string, string>} [fixity] - Fixity information of the file.
|
|
10
|
-
*/
|
|
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
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Represent a file in an OCFL object
|
|
22
|
-
*/
|
|
23
|
-
class OcflObjectFile {
|
|
24
|
-
#ocflObject;
|
|
25
|
-
#lastModified;
|
|
26
|
-
#size;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
*
|
|
30
|
-
* @param {import('./object').OcflObject} ocflObject
|
|
31
|
-
* @param {FileRef} fileRef
|
|
32
|
-
*/
|
|
33
|
-
constructor(ocflObject, fileRef) {
|
|
34
|
-
this.#ocflObject = ocflObject;
|
|
35
|
-
// for (const key in ['logicalPath', 'version', 'digest', 'contentPath']) {
|
|
36
|
-
// if (fileRef[key]) this[key] = fileRef[key];
|
|
37
|
-
// }
|
|
38
|
-
if (fileRef.logicalPath) this.logicalPath = fileRef.logicalPath;
|
|
39
|
-
if (fileRef.contentPath) this.contentPath = fileRef.contentPath;
|
|
40
|
-
if (fileRef.digest) this.digest = fileRef.digest;
|
|
41
|
-
if (fileRef.version) this.version = fileRef.version;
|
|
42
|
-
if (fileRef.lastModified != null) this.#lastModified = fileRef.lastModified;
|
|
43
|
-
if (fileRef.size != null) this.#size = fileRef.size;
|
|
44
|
-
if (fileRef.fixity != null) this.fixity = fileRef.fixity;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Resolve contentPath given either the `logicalPath` and `version`, `digest`, or `contentPath`.
|
|
49
|
-
*/
|
|
50
|
-
async #resolveContentPath() {
|
|
51
|
-
let contentPath = this.contentPath;
|
|
52
|
-
if (!contentPath) {
|
|
53
|
-
let inv = await this.#ocflObject.getInventory();
|
|
54
|
-
if (!inv) throw new Error(`OCFL Object "${this.#ocflObject.id}" does not exist`);
|
|
55
|
-
let version = !this.version || this.version === 'latest' ? inv.head : this.version;
|
|
56
|
-
let digest = this.digest || inv.getDigest(this.logicalPath, version);
|
|
57
|
-
contentPath = inv.getContentPath(digest);
|
|
58
|
-
if (!contentPath) throw new Error(`Cannot find content "${this.toString()}" in the OCFL Object "${this.#ocflObject.id}" version "${this.version || 'latest'}"`);
|
|
59
|
-
}
|
|
60
|
-
return contentPath;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Returns the last modified time of the file, in millisecond since the UNIX epoch (January 1st, 1970 at Midnight).
|
|
65
|
-
*/
|
|
66
|
-
get lastModified() { return this.#lastModified }
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Returns the file size in bytes.
|
|
70
|
-
*/
|
|
71
|
-
get size() { return this.#size }
|
|
72
|
-
|
|
73
|
-
toString() {
|
|
74
|
-
let props = [];
|
|
75
|
-
for (const key in ['logicalPath', 'version', 'digest', 'contentPath']) {
|
|
76
|
-
if (this[key]) props.push(key + ": '" + this[key] + "'");
|
|
77
|
-
}
|
|
78
|
-
return `{ ${props.join(', ')} }`;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Get the file content as a buffer
|
|
83
|
-
* @param {*} [options] Options to be passed to underlying data store specific implementation
|
|
84
|
-
|
|
85
|
-
* @return {Promise<Buffer>}
|
|
86
|
-
*/
|
|
87
|
-
async buffer(options) {
|
|
88
|
-
return this.#ocflObject.readFile(await this.#resolveContentPath(), options);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @deprecated Use {@link buffer()}
|
|
93
|
-
*/
|
|
94
|
-
async asBuffer(options) {
|
|
95
|
-
return this.buffer(options);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Get the file content as a string
|
|
100
|
-
* @param {BufferEncoding} [encoding='utf8'] String encoding, default to utf8
|
|
101
|
-
* @return {Promise<string>}
|
|
102
|
-
*/
|
|
103
|
-
async text(encoding = 'utf8') {
|
|
104
|
-
// @ts-ignore
|
|
105
|
-
return this.buffer(encoding);
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* @deprecated Use {@link text()}
|
|
109
|
-
*/
|
|
110
|
-
async asString(encoding = 'utf8') {
|
|
111
|
-
// @ts-ignore
|
|
112
|
-
return this.text(encoding);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Get the file content as a NodeJS stream
|
|
117
|
-
* @param {*} [options] Options to be passed to underlying data store specific implementation
|
|
118
|
-
* @return {Promise<ReadableStream>}
|
|
119
|
-
* @deprecated Use {@link stream()}
|
|
120
|
-
*/
|
|
121
|
-
async asStream(options) {
|
|
122
|
-
return this.#ocflObject.createReadable(await this.#resolveContentPath(), options);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Get the file content as a ES Streams standard ReadableStream
|
|
127
|
-
* @param {*} [options] Options to be passed to underlying data store specific implementation
|
|
128
|
-
* @return {Promise<ReadableStream>}
|
|
129
|
-
*/
|
|
130
|
-
async stream(options) {
|
|
131
|
-
return this.#ocflObject.createReadable(await this.#resolveContentPath(), options);
|
|
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
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
module.exports = {
|
|
146
|
-
OcflObjectFile
|
|
147
|
-
};
|