@ocfl/ocfl 0.4.0 → 1.0.0-beta.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.
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 +83 -0
  16. package/dist/extension.d.ts.map +1 -0
  17. package/dist/extension.js +170 -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 +395 -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 +206 -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 +456 -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
@@ -0,0 +1,94 @@
1
+ import { OcflObject } from './object.ts';
2
+ import type { OcflStore } from './store.ts';
3
+ import type { OcflStorageConfig, OcflVersion } from './types.ts';
4
+ /**
5
+ * An abstraction to represent the OCFL Storage Root, which is
6
+ * a base directory used to store OCFL Objects, identified by a [NAMASTE] file “0=ocfl_1.1”.
7
+ */
8
+ declare class OcflStorage {
9
+ ocflVersion: OcflVersion;
10
+ /**
11
+ * Get the storage root
12
+ */
13
+ get root(): string;
14
+ /**
15
+ * Construct the path of the object root relative to the storage root
16
+ * The path is mapped from the object identifier using the algorithm defined in the chosen
17
+ * storage layout extension (specified in {@link OcflStorageConfig}).
18
+ * @param id - Identifier of the object
19
+ */
20
+ objectRoot(_id: string): string;
21
+ /**
22
+ * Absolute path to the object root
23
+ * @param id - Identifier of the object
24
+ */
25
+ objectRootAbs(id: string): string;
26
+ /**
27
+ * Get an existing object in the Storage or create a new one.
28
+ * @param opt - A unique identifier for the OCFL Object, should be a URI
29
+ */
30
+ object(_opt: string | {
31
+ id?: string | undefined;
32
+ root?: string | undefined;
33
+ }): OcflObject;
34
+ /**
35
+ * Check if the storage has already the object with the given id.
36
+ */
37
+ has(id: string): Promise<boolean>;
38
+ /**
39
+ * Create the storage root in the underlying storage backend
40
+ * @param options - Additional options for creating storage root
41
+ */
42
+ create(_options?: {
43
+ ocflSpecText?: boolean | undefined;
44
+ }): Promise<OcflStorage>;
45
+ /**
46
+ * Check namaste, retrieve storage layout extension, and read its config file.
47
+ */
48
+ load(): Promise<OcflStorage>;
49
+ /**
50
+ * Check if the storage root path points to an existing file or non-empty directory in the underlying backend store.
51
+ * The existing directory may or may not be a valid OCFL Storage.
52
+ */
53
+ exists(): Promise<boolean>;
54
+ [Symbol.asyncIterator](): AsyncIterableIterator<OcflObject>;
55
+ /**
56
+ * Return a new AsyncIterator that contains all the OCFL objects in this Storage.
57
+ */
58
+ objects(): AsyncIterableIterator<OcflObject>;
59
+ delete(id: string): Promise<void>;
60
+ purge(id: string): Promise<void>;
61
+ remove(_id: string): Promise<void>;
62
+ }
63
+ /**
64
+ * General implementation of {@link OcflStorage} that can uses different datastore backends.
65
+ * This class provides common functionalities for the subclasses and
66
+ * at the same provide encapsulation emulating private and protected methods.
67
+ */
68
+ declare class OcflStorageImpl extends OcflStorage {
69
+ #private;
70
+ constructor(config: OcflStorageConfig, store: OcflStore);
71
+ get root(): string;
72
+ objectRoot(id: string): string;
73
+ /**
74
+ * The root param is a relative path to the storage root.
75
+ */
76
+ object(opt: string | {
77
+ id?: string | undefined;
78
+ root?: string | undefined;
79
+ }): OcflObject;
80
+ exists(): Promise<boolean>;
81
+ load(): Promise<this>;
82
+ /**
83
+ * @param options - Additional options for creating storage root
84
+ */
85
+ create(options?: {
86
+ ocflSpecText?: boolean | undefined;
87
+ }): Promise<this>;
88
+ /**
89
+ * Allow async iteration over all OCFL objects in this storage.
90
+ */
91
+ [Symbol.asyncIterator](): AsyncIterableIterator<OcflObject>;
92
+ }
93
+ export { OcflStorage, OcflStorageImpl };
94
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAUzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAyC,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAExG;;;GAGG;AAEH,cAAM,WAAW;IACf,WAAW,EAAE,WAAW,CAAgB;IAExC;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;OAKG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9B;IAED;;;OAGG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,UAEvB;IAED;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAAG,UAAU,CAExF;IAED;;OAEG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,oBAEnB;IAED;;;OAGG;IACG,MAAM,CAAC,QAAQ,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAEpF;IAED;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC,CAEjC;IAED;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAE/B;IAED,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,UAAU,CAAC,CAE1D;IAED;;OAEG;IACH,OAAO,IAAI,qBAAqB,CAAC,UAAU,CAAC,CAK3C;IAEK,MAAM,CAAC,EAAE,EAAE,MAAM,iBAEtB;IAEK,KAAK,CAAC,EAAE,EAAE,MAAM,iBAErB;IAEK,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvC;CACF;AAED;;;;GAIG;AACH,cAAM,eAAgB,SAAQ,WAAW;;IAOvC,YAAY,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAsBtD;IAaD,IAAI,IAAI,WAEP;IAED,UAAU,CAAC,EAAE,EAAE,MAAM,UAKpB;IAED;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,cAuB1E;IAEK,MAAM,qBAEX;IAEK,IAAI,kBAkCT;IAED;;OAEG;IACG,MAAM,CAAC,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;KAAE,iBAmC5D;IAED;;OAEG;IACH,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,UAAU,CAAC,CAoD1D;CACF;AAED,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,302 @@
1
+ //@todo add default layout
2
+ import path from 'node:path';
3
+ import { OcflConstants } from './constants.js';
4
+ import { NotImplementedError } from './error.js';
5
+ import { createByName, OcflStorageLayout } from './extension.js';
6
+ import { HashedNTupleStorageLayout } from './extensions/0004-hashed-n-tuple-storage-layout.js';
7
+ import { OcflObject } from './object.js';
8
+ import { findNamasteVersion, isDirEmpty } from './utils.js';
9
+ import { createError } from './validation.js';
10
+ const { OCFL_VERSION, OCFL_LAYOUT, EXTENSIONS_DIR, EXTENSION_CONFIG, NAMASTE_PREFIX_STORAGE, NAMASTE_PREFIX_OBJECT, NAMASTE_T } = OcflConstants;
11
+ import { OcflDigest } from './digest.js';
12
+ const DEFAULT_LAYOUT = HashedNTupleStorageLayout;
13
+ /**
14
+ * An abstraction to represent the OCFL Storage Root, which is
15
+ * a base directory used to store OCFL Objects, identified by a [NAMASTE] file “0=ocfl_1.1”.
16
+ */
17
+ class OcflStorage {
18
+ ocflVersion = OCFL_VERSION;
19
+ /**
20
+ * Get the storage root
21
+ */
22
+ get root() {
23
+ throw new NotImplementedError();
24
+ }
25
+ /**
26
+ * Construct the path of the object root relative to the storage root
27
+ * The path is mapped from the object identifier using the algorithm defined in the chosen
28
+ * storage layout extension (specified in {@link OcflStorageConfig}).
29
+ * @param id - Identifier of the object
30
+ */
31
+ objectRoot(_id) {
32
+ throw new NotImplementedError();
33
+ }
34
+ /**
35
+ * Absolute path to the object root
36
+ * @param id - Identifier of the object
37
+ */
38
+ objectRootAbs(id) {
39
+ return path.join(this.root, this.objectRoot(id));
40
+ }
41
+ /**
42
+ * Get an existing object in the Storage or create a new one.
43
+ * @param opt - A unique identifier for the OCFL Object, should be a URI
44
+ */
45
+ object(_opt) {
46
+ throw new NotImplementedError();
47
+ }
48
+ /**
49
+ * Check if the storage has already the object with the given id.
50
+ */
51
+ async has(id) {
52
+ return this.object(id).exists();
53
+ }
54
+ /**
55
+ * Create the storage root in the underlying storage backend
56
+ * @param options - Additional options for creating storage root
57
+ */
58
+ async create(_options) {
59
+ throw new NotImplementedError();
60
+ }
61
+ /**
62
+ * Check namaste, retrieve storage layout extension, and read its config file.
63
+ */
64
+ async load() {
65
+ throw new NotImplementedError();
66
+ }
67
+ /**
68
+ * Check if the storage root path points to an existing file or non-empty directory in the underlying backend store.
69
+ * The existing directory may or may not be a valid OCFL Storage.
70
+ */
71
+ async exists() {
72
+ throw new NotImplementedError();
73
+ }
74
+ [Symbol.asyncIterator]() {
75
+ throw new NotImplementedError();
76
+ }
77
+ /**
78
+ * Return a new AsyncIterator that contains all the OCFL objects in this Storage.
79
+ */
80
+ objects() {
81
+ return this[Symbol.asyncIterator]();
82
+ // const objects = [];
83
+ // for await (const o of this) objects.push(o);
84
+ // return objects;
85
+ }
86
+ async delete(id) {
87
+ return this.remove(id);
88
+ }
89
+ async purge(id) {
90
+ return this.remove(id);
91
+ }
92
+ async remove(_id) {
93
+ throw new NotImplementedError();
94
+ }
95
+ }
96
+ /**
97
+ * General implementation of {@link OcflStorage} that can uses different datastore backends.
98
+ * This class provides common functionalities for the subclasses and
99
+ * at the same provide encapsulation emulating private and protected methods.
100
+ */
101
+ class OcflStorageImpl extends OcflStorage {
102
+ #root;
103
+ #workspace;
104
+ #layout;
105
+ #store;
106
+ #objectConfig;
107
+ constructor(config, store) {
108
+ super();
109
+ if (!store) {
110
+ throw new TypeError('[OcflStorage] store is required.');
111
+ }
112
+ if (!config.root) {
113
+ throw new TypeError('[OcflStorage] config.root is required.');
114
+ }
115
+ this.#store = store;
116
+ const { root, workspace, layout, ocflVersion, ...objectConfig } = config;
117
+ this.#root = path.resolve(root);
118
+ this.#workspace = workspace ? path.resolve(workspace) : path.join(this.#root, 'extensions/workspace');
119
+ if (this.#workspace?.startsWith(this.#root + path.sep) && !this.#workspace.startsWith(`${this.#root + path.sep}extensions${path.sep}`)) {
120
+ throw new Error('[OcflStorage] config.workspace cannot be the same as or a subpath of config.root');
121
+ }
122
+ if (layout) {
123
+ this.#layout = layout instanceof OcflStorageLayout ? layout : this.#createLayout(layout);
124
+ }
125
+ if (ocflVersion) {
126
+ this.ocflVersion = ocflVersion;
127
+ }
128
+ this.#objectConfig = objectConfig;
129
+ }
130
+ #createLayout(option) {
131
+ const name = typeof option === 'string' ? option : option?.extensionName;
132
+ const config = typeof option === 'object' ? option : undefined;
133
+ if (name) {
134
+ return createByName(OcflStorageLayout, 'Layout', name, config);
135
+ }
136
+ // else if (useDefault) {
137
+ // return DEFAULT_LAYOUT.create(config);
138
+ // }
139
+ }
140
+ get root() {
141
+ return this.#root;
142
+ }
143
+ objectRoot(id) {
144
+ if (!this.#layout) {
145
+ throw new Error('[OcflStorage] No layout defined');
146
+ }
147
+ return this.#layout.map(id);
148
+ }
149
+ /**
150
+ * The root param is a relative path to the storage root.
151
+ */
152
+ object(opt) {
153
+ let id;
154
+ let root;
155
+ if (typeof opt === 'string') {
156
+ id = opt;
157
+ }
158
+ else {
159
+ ({ id, root } = opt);
160
+ }
161
+ const relObjectRoot = root || (id && this.objectRoot(id));
162
+ if (!relObjectRoot) {
163
+ throw new TypeError('[OcflStorage] object id or root is required.');
164
+ }
165
+ return new OcflObject({
166
+ id,
167
+ root: path.join(this.root, relObjectRoot),
168
+ // @todo:use extension workspace if not defined
169
+ workspace: this.#workspace ? path.join(this.#workspace, relObjectRoot) : undefined,
170
+ ocflVersion: this.ocflVersion,
171
+ ...this.#objectConfig,
172
+ }, this.#store);
173
+ }
174
+ async exists() {
175
+ return !(await isDirEmpty(this.#store, this.root));
176
+ }
177
+ async load() {
178
+ const prefix = NAMASTE_PREFIX_STORAGE;
179
+ const [ocflVersion, layout] = (await Promise.allSettled([findNamasteVersion(this.#store, prefix, this.root), this.#store.readFile(path.join(this.root, OCFL_LAYOUT), 'utf8')])).map((r) => (r.status === 'fulfilled' ? r.value : undefined));
180
+ if (ocflVersion === '') {
181
+ throw createError('E080', this.root);
182
+ }
183
+ if (!ocflVersion) {
184
+ throw createError('E069', this.root);
185
+ }
186
+ let layoutName;
187
+ let layoutConfig;
188
+ // load layout
189
+ try {
190
+ if (layout) {
191
+ layoutName = JSON.parse(layout).extension;
192
+ }
193
+ }
194
+ catch (_error) { }
195
+ // load ext config if exists
196
+ if (layoutName) {
197
+ try {
198
+ const cfgstr = await this.#store.readFile(path.join(this.root, EXTENSIONS_DIR, layoutName, EXTENSION_CONFIG), 'utf8');
199
+ layoutConfig = JSON.parse(cfgstr);
200
+ }
201
+ catch (_error) { }
202
+ }
203
+ this.#layout = this.#createLayout(layoutConfig || layoutName);
204
+ const layoutDigestAlgorithm = this.#layout?.get('digestAlgorithm');
205
+ if (layoutDigestAlgorithm) {
206
+ await OcflDigest.initSync(layoutDigestAlgorithm);
207
+ }
208
+ //@todo: load storage level extensions
209
+ return this;
210
+ }
211
+ /**
212
+ * @param options - Additional options for creating storage root
213
+ */
214
+ async create(options) {
215
+ if (await this.exists()) {
216
+ //cannot create, storage root already exists .
217
+ throw new Error('[OcflStorage] Cannot create storage root in a non-empty directory');
218
+ }
219
+ else {
220
+ await this.#store.mkdir(this.root);
221
+ }
222
+ // create namaste
223
+ const prefix = NAMASTE_PREFIX_STORAGE;
224
+ const filenamePrefix = NAMASTE_T + prefix;
225
+ const filePath = path.join(this.root, filenamePrefix + this.ocflVersion);
226
+ await this.#store.writeFile(filePath, `${prefix + this.ocflVersion}\n`, 'utf8');
227
+ // create layout
228
+ if (!this.#layout) {
229
+ this.#layout = new DEFAULT_LAYOUT();
230
+ }
231
+ const layoutDigestAlgorithm = this.#layout.get('digestAlgorithm');
232
+ if (layoutDigestAlgorithm) {
233
+ await OcflDigest.initSync(layoutDigestAlgorithm);
234
+ }
235
+ const layout = { extension: this.#layout.name, description: this.#layout.description };
236
+ await this.#store.writeFile(path.join(this.root, OCFL_LAYOUT), JSON.stringify(layout, null, 2), 'utf8');
237
+ if (this.#layout.config) {
238
+ await this.#store.writeFile(path.join(this.root, EXTENSIONS_DIR, this.#layout.name, EXTENSION_CONFIG), JSON.stringify(this.#layout.config, null, 2), 'utf8');
239
+ }
240
+ // todo: create other extensions
241
+ if (options?.ocflSpecText) {
242
+ }
243
+ return this;
244
+ }
245
+ /**
246
+ * Allow async iteration over all OCFL objects in this storage.
247
+ */
248
+ [Symbol.asyncIterator]() {
249
+ const store = this.#store;
250
+ const workspace = this.#workspace;
251
+ const config = this.#objectConfig;
252
+ const root = this.root;
253
+ const stack = [this.#store.opendir(this.root)];
254
+ return {
255
+ [Symbol.asyncIterator]() {
256
+ return this;
257
+ },
258
+ async next() {
259
+ for (let dirp = stack.pop(); dirp; dirp = stack.pop()) {
260
+ const dir = await dirp;
261
+ const dirent = await dir.read();
262
+ if (!dirent) {
263
+ await dir.close();
264
+ continue;
265
+ }
266
+ stack.push(dirp);
267
+ if (!dirent.isDirectory()) {
268
+ continue;
269
+ }
270
+ const basePath = path.join(dir.path, dirent.name);
271
+ let nv;
272
+ try {
273
+ nv = await findNamasteVersion(store, NAMASTE_PREFIX_OBJECT, basePath);
274
+ }
275
+ catch (_err) { }
276
+ if (nv) {
277
+ //ocfl object exists
278
+ // inventory exists
279
+ const object = new OcflObject({
280
+ root: basePath,
281
+ workspace: workspace ? path.join(workspace, path.relative(root, basePath)) : undefined,
282
+ ocflVersion: nv,
283
+ ...config,
284
+ }, store);
285
+ //await object.load();
286
+ return { done: false, value: object };
287
+ }
288
+ else {
289
+ //ocfl object does not exist, process subdir
290
+ stack.push(store.opendir(basePath));
291
+ }
292
+ }
293
+ return { done: true, value: null };
294
+ },
295
+ // return() {
296
+ // return { done: true };
297
+ // }
298
+ };
299
+ }
300
+ }
301
+ export { OcflStorage, OcflStorageImpl };
302
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ import type { Dir, ReadStream, Stats, WriteStream } from 'node:fs';
2
+ type Encoding = BufferEncoding | {
3
+ encoding: BufferEncoding;
4
+ };
5
+ export type WriteFileData = string | Uint8Array | DataView | ArrayBuffer | ReadableStream;
6
+ export interface ListedFile {
7
+ name: string;
8
+ path: string;
9
+ size: number;
10
+ lastModified: Date;
11
+ }
12
+ export interface ListOptions {
13
+ encoding?: BufferEncoding;
14
+ bufferSize?: number;
15
+ recursive?: boolean;
16
+ }
17
+ /**
18
+ * Abstract class to provide common APIs to access and modify the actual data store backend
19
+ * such as local file system and cloud storage
20
+ */
21
+ declare class OcflStore {
22
+ static instances: Map<object, OcflStore>;
23
+ static getInstance<T extends OcflStore>(this: new (options?: object) => T, options?: object): T;
24
+ constructor(_options?: object);
25
+ /**
26
+ * Get file information.
27
+ */
28
+ stat(_filePath: string): Promise<Stats>;
29
+ /**
30
+ * Check if file exists
31
+ */
32
+ exists(filePath: string): Promise<boolean>;
33
+ /**
34
+ * Create a readable stream to get the content of a file
35
+ * @deprecated Use {@link OcflStore.createReadable} instead
36
+ */
37
+ createReadStream(_filePath: string, _options?: unknown): Promise<ReadStream>;
38
+ /**
39
+ * Create a stream that writes data to `filePath`.
40
+ * @deprecated Use {@link OcflStore.createWritable} instead
41
+ */
42
+ createWriteStream(_filePath: string, _options?: unknown): Promise<WriteStream>;
43
+ /**
44
+ * Create a ReadableStream to get the content of a file
45
+ * @param filePath - Absolute path
46
+ */
47
+ createReadable(_filePath: string, _options?: unknown): Promise<ReadableStream>;
48
+ /**
49
+ * Create a WritableStream that writes data to `filePath`.
50
+ */
51
+ createWritable(_filePath: string, _options?: unknown): Promise<WritableStream>;
52
+ /**
53
+ * Provide a common interface to read a file inside an object.
54
+ * A concrete subclass MAY implement this method to provide read access to its underlying storage backend.
55
+ * The default implementation uses the {@linkcode OcflStore#createReadable} method.
56
+ */
57
+ readFile(filePath: string, options: Encoding): Promise<string>;
58
+ readFile(filePath: string, options?: unknown): Promise<Uint8Array>;
59
+ /**
60
+ * Provide a common interface to write a file inside an object.
61
+ * A concrete subclass MAY implement this method to provide write access to its underlying storage backend.
62
+ * The default implementation uses the {@link OcflStore.createWritable} method.
63
+ * @param filePath - Absolute path to the file.
64
+ * @param data - The data to be written to the file.
65
+ */
66
+ writeFile(filePath: string, data: WriteFileData, options?: object | string): Promise<void>;
67
+ /**
68
+ * Copy file from `source` to `target`.
69
+ * By default, target is overwritten if it already exists.
70
+ */
71
+ copyFile(source: string, target: string): Promise<void>;
72
+ /**
73
+ * Open a directory
74
+ */
75
+ opendir(_filePath: string, _options?: unknown): Promise<Dir>;
76
+ /**
77
+ * Read a directory
78
+ */
79
+ readdir(_filePath: string, _options?: unknown): Promise<string[]>;
80
+ /**
81
+ * List all files contained in a directory including the metadata such as size and last modified date.
82
+ * The returned file.path is a relative path to the dirPath
83
+ */
84
+ list(_dirPath: string, _options?: ListOptions): Promise<AsyncIterableIterator<ListedFile>>;
85
+ /**
86
+ * Recursively create a directory if the storage backend supports it, otherwise do nothing
87
+ * @returns The first directory path created
88
+ */
89
+ mkdir(_filePath: string, _options?: unknown): Promise<string | undefined>;
90
+ /**
91
+ * Rename or move a file or directory
92
+ */
93
+ move(_source: string, _target: string): Promise<void>;
94
+ /**
95
+ * Remove a file or directory recursively
96
+ */
97
+ remove(_filePath: string): Promise<void>;
98
+ }
99
+ export { OcflStore };
100
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/dist/store.js ADDED
@@ -0,0 +1,157 @@
1
+ import path from 'node:path';
2
+ import { joinTypedArray } from './utils.js';
3
+ const emptyOptions = {};
4
+ /**
5
+ * Abstract class to provide common APIs to access and modify the actual data store backend
6
+ * such as local file system and cloud storage
7
+ */
8
+ class OcflStore {
9
+ static instances;
10
+ static getInstance(options = emptyOptions) {
11
+ // biome-ignore lint/complexity/noThisInStatic: reads the subclass's own instances map
12
+ const instances = this.instances;
13
+ if (!instances) {
14
+ return new this(options);
15
+ }
16
+ let store = instances.get(options);
17
+ if (!store) {
18
+ store = new this(options);
19
+ instances.set(options, store);
20
+ }
21
+ return store;
22
+ }
23
+ // biome-ignore lint/complexity/noUselessConstructor: documents the constructor signature subclasses receive from getInstance()
24
+ constructor(_options) { }
25
+ /**
26
+ * Get file information.
27
+ */
28
+ async stat(_filePath) {
29
+ throw new Error('Not Implemented');
30
+ }
31
+ /**
32
+ * Check if file exists
33
+ */
34
+ async exists(filePath) {
35
+ try {
36
+ await this.stat(filePath);
37
+ return true;
38
+ }
39
+ catch {
40
+ return false;
41
+ }
42
+ }
43
+ /**
44
+ * Create a readable stream to get the content of a file
45
+ * @deprecated Use {@link OcflStore.createReadable} instead
46
+ */
47
+ async createReadStream(_filePath, _options) {
48
+ throw new Error('Not Implemented');
49
+ }
50
+ /**
51
+ * Create a stream that writes data to `filePath`.
52
+ * @deprecated Use {@link OcflStore.createWritable} instead
53
+ */
54
+ async createWriteStream(_filePath, _options) {
55
+ throw new Error('Not Implemented');
56
+ }
57
+ /**
58
+ * Create a ReadableStream to get the content of a file
59
+ * @param filePath - Absolute path
60
+ */
61
+ async createReadable(_filePath, _options) {
62
+ throw new Error('Not Implemented');
63
+ }
64
+ /**
65
+ * Create a WritableStream that writes data to `filePath`.
66
+ */
67
+ async createWritable(_filePath, _options) {
68
+ throw new Error('Not Implemented');
69
+ }
70
+ async readFile(filePath, options) {
71
+ const rs = await this.createReadable(filePath, options);
72
+ let buffer = typeof options === 'string' || options?.encoding
73
+ ? ''
74
+ : new Uint8Array(new ArrayBuffer(0, { maxByteLength: 16 * 1024 }));
75
+ for await (const chunk of rs) {
76
+ if (typeof chunk === 'string') {
77
+ if (typeof buffer !== 'string') {
78
+ buffer = new TextDecoder().decode(buffer);
79
+ }
80
+ buffer += chunk;
81
+ }
82
+ else {
83
+ if (typeof buffer === 'string') {
84
+ buffer = new TextEncoder().encode(buffer);
85
+ }
86
+ buffer = joinTypedArray(buffer, chunk);
87
+ }
88
+ }
89
+ return buffer;
90
+ }
91
+ /**
92
+ * Provide a common interface to write a file inside an object.
93
+ * A concrete subclass MAY implement this method to provide write access to its underlying storage backend.
94
+ * The default implementation uses the {@link OcflStore.createWritable} method.
95
+ * @param filePath - Absolute path to the file.
96
+ * @param data - The data to be written to the file.
97
+ */
98
+ async writeFile(filePath, data, options) {
99
+ await this.mkdir(path.dirname(filePath));
100
+ const target = await this.createWritable(filePath, options);
101
+ if (data instanceof ReadableStream) {
102
+ await data.pipeTo(target);
103
+ }
104
+ else {
105
+ const w = target.getWriter();
106
+ await w.write(data);
107
+ await w.close();
108
+ }
109
+ }
110
+ /**
111
+ * Copy file from `source` to `target`.
112
+ * By default, target is overwritten if it already exists.
113
+ */
114
+ async copyFile(source, target) {
115
+ await this.writeFile(target, await this.createReadable(source));
116
+ }
117
+ /**
118
+ * Open a directory
119
+ */
120
+ async opendir(_filePath, _options) {
121
+ throw new Error('Not Implemented');
122
+ }
123
+ /**
124
+ * Read a directory
125
+ */
126
+ async readdir(_filePath, _options) {
127
+ throw new Error('Not Implemented');
128
+ }
129
+ /**
130
+ * List all files contained in a directory including the metadata such as size and last modified date.
131
+ * The returned file.path is a relative path to the dirPath
132
+ */
133
+ async list(_dirPath, _options) {
134
+ throw new Error('Not Implemented');
135
+ }
136
+ /**
137
+ * Recursively create a directory if the storage backend supports it, otherwise do nothing
138
+ * @returns The first directory path created
139
+ */
140
+ async mkdir(_filePath, _options) {
141
+ throw new Error('Not Implemented');
142
+ }
143
+ /**
144
+ * Rename or move a file or directory
145
+ */
146
+ async move(_source, _target) {
147
+ throw new Error('Not Implemented');
148
+ }
149
+ /**
150
+ * Remove a file or directory recursively
151
+ */
152
+ async remove(_filePath) {
153
+ throw new Error('Not Implemented');
154
+ }
155
+ }
156
+ export { OcflStore };
157
+ //# sourceMappingURL=store.js.map