fs-object-storage 1.0.0 → 1.0.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.
- package/README.md +23 -23
- package/docs/technical/api-reference.md +312 -0
- package/docs/technical/architecture.md +179 -0
- package/docs/technical/usage-examples.md +394 -0
- package/package.json +1 -1
- package/quick-test.js +9 -8
- package/samples/{fs-minio-test.js → fs-object-storage-test.js} +20 -24
- package/src/index.d.ts +4 -4
- package/src/index.js +4 -4
- package/src/lib/ErrorHandler.js +1 -1
- package/src/lib/{FsMinioClient.js → ObjectStorage.js} +4 -4
- package/src/lib/PathConverter.js +97 -32
- package/test-package.json +1 -1
- package/unit-tests.js +5 -5
package/src/lib/PathConverter.js
CHANGED
|
@@ -27,12 +27,21 @@ class PathConverter {
|
|
|
27
27
|
*/
|
|
28
28
|
pathToMinIO(filePath) {
|
|
29
29
|
// Normalize path and remove leading slash
|
|
30
|
-
|
|
30
|
+
let normalizedPath = path.posix.normalize(filePath).replace(/^\/+/, '');
|
|
31
|
+
|
|
32
|
+
// �o�P�b�g�����擪�Ɋ܂܂�Ă���ꍇ�͏���
|
|
33
|
+
if (normalizedPath.startsWith(this.bucket + '/')) {
|
|
34
|
+
normalizedPath = normalizedPath.substring(this.bucket.length + 1);
|
|
35
|
+
} else if (normalizedPath === this.bucket) {
|
|
36
|
+
normalizedPath = '';
|
|
37
|
+
}
|
|
31
38
|
|
|
32
39
|
// Combine prefix and path
|
|
33
|
-
let key
|
|
40
|
+
let key;
|
|
34
41
|
if (this.prefix) {
|
|
35
42
|
key = this.prefix + this.separator + normalizedPath;
|
|
43
|
+
} else {
|
|
44
|
+
key = normalizedPath;
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
// Ensure we don't have double separators
|
|
@@ -51,19 +60,18 @@ class PathConverter {
|
|
|
51
60
|
* @returns {string} Filesystem path
|
|
52
61
|
*/
|
|
53
62
|
minIOToPath(bucket, key) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
// bucket��key���������Đ�p�X��Ԃ�
|
|
64
|
+
let filePath = '';
|
|
65
|
+
if (bucket && key) {
|
|
66
|
+
filePath = '/' + bucket + '/' + key.replace(/^\/+/, '');
|
|
67
|
+
} else if (bucket) {
|
|
68
|
+
filePath = '/' + bucket;
|
|
69
|
+
} else if (key) {
|
|
70
|
+
filePath = '/' + key.replace(/^\/+/, '');
|
|
71
|
+
} else {
|
|
72
|
+
filePath = '/';
|
|
59
73
|
}
|
|
60
|
-
|
|
61
|
-
// Ensure leading slash for absolute path
|
|
62
|
-
if (!filePath.startsWith('/')) {
|
|
63
|
-
filePath = '/' + filePath;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return path.posix.normalize(filePath);
|
|
74
|
+
return PathConverter.normalizePath(filePath);
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
/**
|
|
@@ -136,34 +144,83 @@ class PathConverter {
|
|
|
136
144
|
}
|
|
137
145
|
|
|
138
146
|
/**
|
|
139
|
-
*
|
|
140
|
-
* @param {
|
|
141
|
-
* @returns {string
|
|
147
|
+
* Split a path into bucket and key
|
|
148
|
+
* @param {string} filePath - Path like '/bucket/path/to/file.txt'
|
|
149
|
+
* @returns {{bucket: string, key: string}}
|
|
142
150
|
*/
|
|
143
|
-
|
|
144
|
-
|
|
151
|
+
static splitPath(filePath) {
|
|
152
|
+
const normalized = PathConverter.normalizePath(filePath);
|
|
153
|
+
if (normalized === '/') return { bucket: '', key: '' };
|
|
154
|
+
const parts = normalized.slice(1).split('/');
|
|
155
|
+
const bucket = parts.shift() || '';
|
|
156
|
+
const key = parts.join('/') || '';
|
|
157
|
+
return { bucket, key };
|
|
145
158
|
}
|
|
146
159
|
|
|
147
160
|
/**
|
|
148
|
-
*
|
|
149
|
-
* @param {string}
|
|
150
|
-
* @
|
|
161
|
+
* Join bucket and key into a path
|
|
162
|
+
* @param {string} bucket
|
|
163
|
+
* @param {string} key
|
|
164
|
+
* @returns {string}
|
|
165
|
+
*/
|
|
166
|
+
static joinPath(bucket, key) {
|
|
167
|
+
let pathStr = '';
|
|
168
|
+
if (bucket && key) {
|
|
169
|
+
pathStr = '/' + bucket + '/' + key.replace(/^\/+/, '');
|
|
170
|
+
} else if (bucket) {
|
|
171
|
+
pathStr = '/' + bucket;
|
|
172
|
+
} else if (key) {
|
|
173
|
+
pathStr = '/' + key.replace(/^\/+/, '');
|
|
174
|
+
} else {
|
|
175
|
+
pathStr = '/';
|
|
176
|
+
}
|
|
177
|
+
// ���K�����ė]���ȃX���b�V��������
|
|
178
|
+
return PathConverter.normalizePath(pathStr);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Normalize a path (remove duplicate slashes, ensure leading slash, remove trailing slash except root)
|
|
183
|
+
* @param {string} filePath
|
|
184
|
+
* @returns {string}
|
|
151
185
|
*/
|
|
152
|
-
|
|
153
|
-
|
|
186
|
+
static normalizePath(filePath) {
|
|
187
|
+
if (!filePath) return '/';
|
|
188
|
+
let norm = path.posix.normalize(filePath).replace(/\/+/g, '/');
|
|
189
|
+
if (!norm.startsWith('/')) norm = '/' + norm;
|
|
190
|
+
if (norm.length > 1 && norm.endsWith('/')) norm = norm.slice(0, -1);
|
|
191
|
+
return norm;
|
|
154
192
|
}
|
|
155
193
|
|
|
156
194
|
/**
|
|
157
|
-
*
|
|
158
|
-
* @param {string}
|
|
159
|
-
* @
|
|
160
|
-
* @returns {string} Absolute path
|
|
195
|
+
* Check if path is directory (trailing slash or root)
|
|
196
|
+
* @param {string} filePath
|
|
197
|
+
* @returns {boolean}
|
|
161
198
|
*/
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
199
|
+
static isDirectory(filePath) {
|
|
200
|
+
const norm = PathConverter.normalizePath(filePath);
|
|
201
|
+
return norm === '/' || filePath.endsWith('/');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Get parent path (static)
|
|
206
|
+
* @param {string} filePath
|
|
207
|
+
* @returns {string}
|
|
208
|
+
*/
|
|
209
|
+
static getParentPath(filePath) {
|
|
210
|
+
const norm = PathConverter.normalizePath(filePath);
|
|
211
|
+
const parent = path.posix.dirname(norm);
|
|
212
|
+
return parent === '.' ? '/' : parent;
|
|
165
213
|
}
|
|
166
|
-
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get basename (static)
|
|
217
|
+
* @param {string} filePath
|
|
218
|
+
* @returns {string}
|
|
219
|
+
*/
|
|
220
|
+
static getBasename(filePath) {
|
|
221
|
+
const norm = PathConverter.normalizePath(filePath);
|
|
222
|
+
if (norm === '/') return '';
|
|
223
|
+
return path.posix.basename(norm);
|
|
167
224
|
}
|
|
168
225
|
|
|
169
226
|
/**
|
|
@@ -204,6 +261,14 @@ class PathConverter {
|
|
|
204
261
|
getPrefix() {
|
|
205
262
|
return this.prefix;
|
|
206
263
|
}
|
|
264
|
+
|
|
265
|
+
// --- static���[�e�B���e�B���C���X�^���X������Ăׂ�悤���b�v ---
|
|
266
|
+
normalizePath(filePath) {
|
|
267
|
+
return PathConverter.normalizePath(filePath);
|
|
268
|
+
}
|
|
269
|
+
getBasename(filePath) {
|
|
270
|
+
return PathConverter.getBasename(filePath);
|
|
271
|
+
}
|
|
207
272
|
}
|
|
208
273
|
|
|
209
274
|
export default PathConverter;
|
package/test-package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"scripts": {
|
|
4
4
|
"test": "node --test tests/unit/*.test.js",
|
|
5
5
|
"test:watch": "node --test --watch tests/unit/*.test.js",
|
|
6
|
-
"test:integration": "node samples/fs-
|
|
6
|
+
"test:integration": "node samples/fs-object-storage-test.js",
|
|
7
7
|
"test:all": "npm run test && npm run test:integration"
|
|
8
8
|
}
|
|
9
9
|
}
|
package/unit-tests.js
CHANGED
|
@@ -26,7 +26,7 @@ test('ErrorHandler - convert AccessDenied to EACCES', () => {
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
test('ErrorHandler - create filesystem error', () => {
|
|
29
|
-
const error = ErrorHandler.
|
|
29
|
+
const error = ErrorHandler.createFileSystemError('ENOENT', '/test/file.txt', 'open');
|
|
30
30
|
assert.strictEqual(error.code, 'ENOENT');
|
|
31
31
|
assert.strictEqual(error.errno, -2);
|
|
32
32
|
assert.strictEqual(error.path, '/test/file.txt');
|
|
@@ -39,16 +39,16 @@ const pc = new PathConverter({ bucket: 'bucket' });
|
|
|
39
39
|
test('PathConverter - split path correctly', () => {
|
|
40
40
|
const result = pc.pathToMinIO('/bucket/path/to/file.txt');
|
|
41
41
|
assert.strictEqual(result.bucket, 'bucket');
|
|
42
|
-
assert.strictEqual(result.key, '
|
|
42
|
+
assert.strictEqual(result.key, 'path/to/file.txt');
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
test('PathConverter - join path correctly', () => {
|
|
46
|
-
const result = pc.
|
|
46
|
+
const result = pc.minIOToPath('bucket', 'path/to/file.txt');
|
|
47
47
|
assert.strictEqual(result, '/bucket/path/to/file.txt');
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
test('PathConverter - normalize path', () => {
|
|
51
|
-
const result = pc.
|
|
51
|
+
const result = pc.normalizePath('/bucket//path///to/file.txt');
|
|
52
52
|
assert.strictEqual(result, '/bucket/path/to/file.txt');
|
|
53
53
|
});
|
|
54
54
|
|
|
@@ -58,7 +58,7 @@ test('PathConverter - get parent path', () => {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
test('PathConverter - get basename', () => {
|
|
61
|
-
const result = pc.
|
|
61
|
+
const result = pc.getBasename('/bucket/path/to/file.txt');
|
|
62
62
|
assert.strictEqual(result, 'file.txt');
|
|
63
63
|
});
|
|
64
64
|
|