@heilgar/file-storage-adapter-fs 1.0.1 → 1.0.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/README.md +31 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# File Storage Adapter FS
|
|
2
|
+
|
|
3
|
+
Filesystem implementation of the file storage adapter.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @heilgar/file-storage-adapter-fs
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { FsAdapter } from '@heilgar/file-storage-adapter-fs';
|
|
15
|
+
|
|
16
|
+
const adapter = new FsAdapter({
|
|
17
|
+
rootDir: '/tmp/storage',
|
|
18
|
+
basePath: 'uploads',
|
|
19
|
+
baseUrl: 'https://files.example.com',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const metadata = await adapter.upload('images/logo.png', Buffer.from('...'));
|
|
23
|
+
const file = await adapter.download('images/logo.png');
|
|
24
|
+
const list = await adapter.list({ prefix: 'images' });
|
|
25
|
+
const url = await adapter.getSignedUrl('images/logo.png', { expiresIn: 3600 });
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Notes
|
|
29
|
+
|
|
30
|
+
- `basePath` (optional) prefixes keys.
|
|
31
|
+
- `baseUrl` (optional) enables `getSignedUrl` as a public URL.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { BaseAdapter, DownloadOptions, FileMetadata, FileObject, FileStorageAdapterConfig, ListOptions, ListResult, SignedUrlOptions, UploadOptions } from '@heilgar/file-storage-adapter-core';
|
|
1
|
+
import { BaseAdapter, type DownloadOptions, type FileMetadata, type FileObject, type FileStorageAdapterConfig, type ListOptions, type ListResult, type SignedUrlOptions, type UploadOptions } from '@heilgar/file-storage-adapter-core';
|
|
2
2
|
export interface FsAdapterConfig extends FileStorageAdapterConfig {
|
|
3
3
|
rootDir: string;
|
|
4
4
|
baseUrl?: string;
|
|
5
5
|
}
|
|
6
6
|
export declare class FsAdapter extends BaseAdapter {
|
|
7
|
+
private static readonly DEFAULT_LIST_LIMIT;
|
|
8
|
+
private static readonly METADATA_FILE_EXTENSION;
|
|
7
9
|
private rootDir;
|
|
8
10
|
private baseUrl?;
|
|
9
11
|
constructor(config: FsAdapterConfig);
|
|
@@ -16,6 +18,11 @@ export declare class FsAdapter extends BaseAdapter {
|
|
|
16
18
|
delete(key: string): Promise<boolean>;
|
|
17
19
|
exists(key: string): Promise<boolean>;
|
|
18
20
|
list(options?: ListOptions): Promise<ListResult>;
|
|
21
|
+
private getSearchDirectory;
|
|
22
|
+
private collectFiles;
|
|
23
|
+
private walkDirectory;
|
|
24
|
+
private isDataFile;
|
|
25
|
+
private getFileMetadataForListing;
|
|
19
26
|
getSignedUrl(key: string, options: SignedUrlOptions): Promise<string>;
|
|
20
27
|
getSignedUrlUpload(key: string, options: SignedUrlOptions): Promise<{
|
|
21
28
|
url: string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,EACX,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,wBAAwB,EAC7B,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,oCAAoC,CAAC;AAG5C,MAAM,WAAW,eAAgB,SAAQ,wBAAwB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,SAAU,SAAQ,WAAW;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAQ;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAgB;IAE/D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAC,CAAS;gBAEb,MAAM,EAAE,eAAe;IAOnC,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,eAAe;YAIT,SAAS;IAKjB,MAAM,CACV,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,cAAc,GAAG,IAAI,EAC3C,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC;IA4BlB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IAgDrE,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAwBtD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAuBrC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUrC,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC;IAY1D,OAAO,CAAC,kBAAkB;YAMZ,YAAY;YAMZ,aAAa;IAwB3B,OAAO,CAAC,UAAU;YAIJ,yBAAyB;IAMjC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IASrE,kBAAkB,CACtB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IAIvD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAwBtE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAK7E"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createReadStream, promises as fs } from 'node:fs';
|
|
1
|
+
import { createReadStream, createWriteStream, promises as fs } from 'node:fs';
|
|
3
2
|
import { dirname, join, relative } from 'node:path';
|
|
3
|
+
import { pipeline } from 'node:stream/promises';
|
|
4
|
+
import { BaseAdapter, } from '@heilgar/file-storage-adapter-core';
|
|
4
5
|
import { lookup } from 'mime-types';
|
|
5
6
|
export class FsAdapter extends BaseAdapter {
|
|
6
7
|
constructor(config) {
|
|
@@ -13,7 +14,7 @@ export class FsAdapter extends BaseAdapter {
|
|
|
13
14
|
return join(this.rootDir, fullKey);
|
|
14
15
|
}
|
|
15
16
|
getMetadataPath(key) {
|
|
16
|
-
return `${this.getFilePath(key)}.
|
|
17
|
+
return `${this.getFilePath(key)}${FsAdapter.METADATA_FILE_EXTENSION}`;
|
|
17
18
|
}
|
|
18
19
|
async ensureDir(filePath) {
|
|
19
20
|
const dir = dirname(filePath);
|
|
@@ -22,15 +23,23 @@ export class FsAdapter extends BaseAdapter {
|
|
|
22
23
|
async upload(key, file, options) {
|
|
23
24
|
const filePath = this.getFilePath(key);
|
|
24
25
|
await this.ensureDir(filePath);
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
if (Buffer.isBuffer(file)) {
|
|
27
|
+
await fs.writeFile(filePath, file);
|
|
28
|
+
}
|
|
29
|
+
else if ('stream' in file && typeof file.stream === 'function') {
|
|
30
|
+
const buffer = await this.toBuffer(file);
|
|
31
|
+
await fs.writeFile(filePath, buffer);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
await pipeline(file, createWriteStream(filePath));
|
|
35
|
+
}
|
|
27
36
|
const stat = await fs.stat(filePath);
|
|
28
37
|
const metadata = {
|
|
29
|
-
name:
|
|
38
|
+
name: this.extractFileName(key),
|
|
30
39
|
mimeType: options?.contentType || lookup(key) || 'application/octet-stream',
|
|
31
|
-
|
|
40
|
+
sizeInBytes: stat.size,
|
|
32
41
|
uploadedAt: new Date(),
|
|
33
|
-
|
|
42
|
+
customMetadata: options?.metadata,
|
|
34
43
|
};
|
|
35
44
|
const metadataPath = this.getMetadataPath(key);
|
|
36
45
|
await fs.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
@@ -40,13 +49,18 @@ export class FsAdapter extends BaseAdapter {
|
|
|
40
49
|
const filePath = this.getFilePath(key);
|
|
41
50
|
const metadataPath = this.getMetadataPath(key);
|
|
42
51
|
let content;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
try {
|
|
53
|
+
if (options?.range) {
|
|
54
|
+
const { startByte, endByte } = options.range;
|
|
55
|
+
const stream = createReadStream(filePath, { start: startByte, end: endByte });
|
|
56
|
+
content = await this.toBuffer(stream);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
content = await fs.readFile(filePath);
|
|
60
|
+
}
|
|
47
61
|
}
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
catch (error) {
|
|
63
|
+
throw new Error(`Failed to read file at key "${key}": ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
50
64
|
}
|
|
51
65
|
let metadata;
|
|
52
66
|
try {
|
|
@@ -54,15 +68,20 @@ export class FsAdapter extends BaseAdapter {
|
|
|
54
68
|
metadata = JSON.parse(metaContent);
|
|
55
69
|
metadata.uploadedAt = new Date(metadata.uploadedAt);
|
|
56
70
|
}
|
|
57
|
-
catch {
|
|
58
|
-
// Fallback if metadata doesn't exist
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
catch (metadataError) {
|
|
72
|
+
// Fallback to file stats if metadata doesn't exist
|
|
73
|
+
try {
|
|
74
|
+
const stats = await fs.stat(filePath);
|
|
75
|
+
metadata = {
|
|
76
|
+
name: this.extractFileName(key),
|
|
77
|
+
mimeType: lookup(key) || 'application/octet-stream',
|
|
78
|
+
sizeInBytes: stats.size,
|
|
79
|
+
uploadedAt: stats.mtime,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
catch (statsError) {
|
|
83
|
+
throw new Error(`Failed to retrieve metadata for file at key "${key}": ${statsError instanceof Error ? statsError.message : 'Unknown error'}`);
|
|
84
|
+
}
|
|
66
85
|
}
|
|
67
86
|
return {
|
|
68
87
|
...metadata,
|
|
@@ -83,9 +102,9 @@ export class FsAdapter extends BaseAdapter {
|
|
|
83
102
|
const filePath = this.getFilePath(key);
|
|
84
103
|
const stats = await fs.stat(filePath);
|
|
85
104
|
return {
|
|
86
|
-
name:
|
|
105
|
+
name: this.extractFileName(key),
|
|
87
106
|
mimeType: lookup(key) || 'application/octet-stream',
|
|
88
|
-
|
|
107
|
+
sizeInBytes: stats.size,
|
|
89
108
|
uploadedAt: stats.mtime,
|
|
90
109
|
};
|
|
91
110
|
}
|
|
@@ -99,10 +118,19 @@ export class FsAdapter extends BaseAdapter {
|
|
|
99
118
|
const filePath = this.getFilePath(key);
|
|
100
119
|
const metadataPath = this.getMetadataPath(key);
|
|
101
120
|
await fs.unlink(filePath);
|
|
102
|
-
|
|
121
|
+
// Try to delete metadata file, but don't fail if it doesn't exist
|
|
122
|
+
try {
|
|
123
|
+
await fs.unlink(metadataPath);
|
|
124
|
+
}
|
|
125
|
+
catch (metadataError) {
|
|
126
|
+
// Metadata file may not exist, which is acceptable
|
|
127
|
+
// Log for debugging if needed: console.debug(`Metadata file not found for key "${key}"`);
|
|
128
|
+
}
|
|
103
129
|
return true;
|
|
104
130
|
}
|
|
105
|
-
catch {
|
|
131
|
+
catch (error) {
|
|
132
|
+
// File doesn't exist or permission denied
|
|
133
|
+
// Consider logging: console.debug(`Failed to delete file at key "${key}": ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
106
134
|
return false;
|
|
107
135
|
}
|
|
108
136
|
}
|
|
@@ -117,40 +145,54 @@ export class FsAdapter extends BaseAdapter {
|
|
|
117
145
|
}
|
|
118
146
|
}
|
|
119
147
|
async list(options = {}) {
|
|
120
|
-
const { prefix = '', limit =
|
|
121
|
-
const
|
|
122
|
-
const
|
|
148
|
+
const { prefix = '', limit = FsAdapter.DEFAULT_LIST_LIMIT } = options;
|
|
149
|
+
const searchDir = this.getSearchDirectory(prefix);
|
|
150
|
+
const files = await this.collectFiles(searchDir, limit);
|
|
151
|
+
return {
|
|
152
|
+
files,
|
|
153
|
+
hasMore: limit > 0 && files.length >= limit,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
getSearchDirectory(prefix) {
|
|
157
|
+
return prefix
|
|
123
158
|
? join(this.rootDir, this.getFullKey(prefix))
|
|
124
159
|
: join(this.rootDir, this.config.basePath || '');
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
160
|
+
}
|
|
161
|
+
async collectFiles(directory, limit) {
|
|
162
|
+
const files = [];
|
|
163
|
+
await this.walkDirectory(directory, files, limit);
|
|
164
|
+
return files;
|
|
165
|
+
}
|
|
166
|
+
async walkDirectory(dir, files, limit) {
|
|
167
|
+
try {
|
|
168
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
if (files.length >= limit)
|
|
171
|
+
break;
|
|
172
|
+
const fullPath = join(dir, entry.name);
|
|
173
|
+
if (entry.isDirectory()) {
|
|
174
|
+
await this.walkDirectory(fullPath, files, limit);
|
|
175
|
+
}
|
|
176
|
+
else if (this.isDataFile(entry.name)) {
|
|
177
|
+
const metadata = await this.getFileMetadataForListing(fullPath);
|
|
178
|
+
if (metadata) {
|
|
179
|
+
files.push(metadata);
|
|
142
180
|
}
|
|
143
181
|
}
|
|
144
182
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
// Directory doesn't exist or not accessible
|
|
186
|
+
// Consider logging: console.debug(`Failed to read directory "${dir}": ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
isDataFile(fileName) {
|
|
190
|
+
return !fileName.endsWith(FsAdapter.METADATA_FILE_EXTENSION);
|
|
191
|
+
}
|
|
192
|
+
async getFileMetadataForListing(fullPath) {
|
|
193
|
+
const relativePath = relative(this.rootDir, fullPath);
|
|
194
|
+
const key = this.stripBasePath(relativePath);
|
|
195
|
+
return this.getMetadata(key);
|
|
154
196
|
}
|
|
155
197
|
async getSignedUrl(key, options) {
|
|
156
198
|
// Filesystem doesn't support signed URLs, return public URL if baseUrl is set
|
|
@@ -189,4 +231,6 @@ export class FsAdapter extends BaseAdapter {
|
|
|
189
231
|
return metadata;
|
|
190
232
|
}
|
|
191
233
|
}
|
|
234
|
+
FsAdapter.DEFAULT_LIST_LIMIT = 1000;
|
|
235
|
+
FsAdapter.METADATA_FILE_EXTENSION = '.meta.json';
|
|
192
236
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|