@bgord/bun 0.22.1 → 0.23.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/dist/file-hash-noop.adapter.d.ts +10 -0
- package/dist/file-hash-noop.adapter.d.ts.map +1 -0
- package/dist/file-hash-noop.adapter.js +7 -0
- package/dist/file-hash-noop.adapter.js.map +1 -0
- package/dist/file-hash-sha256-bun.adapter.d.ts +10 -0
- package/dist/file-hash-sha256-bun.adapter.d.ts.map +1 -0
- package/dist/file-hash-sha256-bun.adapter.js +15 -0
- package/dist/file-hash-sha256-bun.adapter.js.map +1 -0
- package/dist/file-hash.port.d.ts +10 -0
- package/dist/file-hash.port.d.ts.map +1 -0
- package/dist/file-hash.port.js +2 -0
- package/dist/file-hash.port.js.map +1 -0
- package/dist/image-alpha-noop.adapter.d.ts +1 -1
- package/dist/image-alpha-sharp.adapter.d.ts +1 -1
- package/dist/image-blur-noop.adapter.d.ts +1 -1
- package/dist/image-blur-sharp.adapter.d.ts +1 -1
- package/dist/image-compressor-noop.adapter.d.ts +1 -1
- package/dist/image-compressor-sharp.adapter.d.ts +1 -1
- package/dist/image-exif-clear-noop.adapter.d.ts +1 -1
- package/dist/image-exif-clear-sharp.adapter.d.ts +1 -1
- package/dist/image-formatter-sharp.adapter.d.ts +1 -1
- package/dist/image-info.port.d.ts +1 -2
- package/dist/image-info.port.d.ts.map +1 -1
- package/dist/image-resizer-noop.adapter.d.ts +1 -1
- package/dist/image-resizer-sharp.adapter.d.ts +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/remote-file-storage-disk.adapter.d.ts +20 -0
- package/dist/remote-file-storage-disk.adapter.d.ts.map +1 -0
- package/dist/remote-file-storage-disk.adapter.js +54 -0
- package/dist/remote-file-storage-disk.adapter.js.map +1 -0
- package/dist/remote-file-storage-noop.adapter.d.ts +18 -0
- package/dist/remote-file-storage-noop.adapter.d.ts.map +1 -0
- package/dist/remote-file-storage-noop.adapter.js +52 -0
- package/dist/remote-file-storage-noop.adapter.js.map +1 -0
- package/dist/remote-file-storage.port.d.ts +20 -0
- package/dist/remote-file-storage.port.d.ts.map +1 -0
- package/dist/remote-file-storage.port.js +2 -0
- package/dist/remote-file-storage.port.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/readme.md +6 -0
- package/src/file-hash-noop.adapter.ts +8 -0
- package/src/file-hash-sha256-bun.adapter.ts +18 -0
- package/src/file-hash.port.ts +7 -0
- package/src/image-info.port.ts +6 -1
- package/src/index.ts +6 -0
- package/src/remote-file-storage-disk.adapter.ts +74 -0
- package/src/remote-file-storage-noop.adapter.ts +65 -0
- package/src/remote-file-storage.port.ts +19 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bgord/bun",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Bartosz Gordon",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@axiomhq/winston": "1.3.1",
|
|
41
|
-
"@bgord/tools": "0.12.
|
|
41
|
+
"@bgord/tools": "0.12.18",
|
|
42
42
|
"@hono/ua-blocker": "0.1.8",
|
|
43
43
|
"better-auth": "1.3.7",
|
|
44
44
|
"check-disk-space": "3.4.0",
|
package/readme.md
CHANGED
|
@@ -56,6 +56,9 @@ src/
|
|
|
56
56
|
├── event.types.ts
|
|
57
57
|
├── file-draft-zip.service.ts
|
|
58
58
|
├── file-draft.service.ts
|
|
59
|
+
├── file-hash-noop.adapter.ts
|
|
60
|
+
├── file-hash-sha256-bun.adapter.ts
|
|
61
|
+
├── file-hash.port.ts
|
|
59
62
|
├── file-uploader.middleware.ts
|
|
60
63
|
├── graceful-shutdown.service.ts
|
|
61
64
|
├── gzip.service.ts
|
|
@@ -159,6 +162,9 @@ src/
|
|
|
159
162
|
├── prerequisites.service.ts
|
|
160
163
|
├── rate-limit-store-node-cache.adapter.ts
|
|
161
164
|
├── rate-limit-store.port.ts
|
|
165
|
+
├── remote-file-storage-disk.adapter.ts
|
|
166
|
+
├── remote-file-storage-noop.adapter.ts
|
|
167
|
+
├── remote-file-storage.port.ts
|
|
162
168
|
├── safe-parse-body.service.ts
|
|
163
169
|
├── setup.service.ts
|
|
164
170
|
├── shield-api-key.middleware.ts
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as tools from "@bgord/tools";
|
|
2
|
+
import type { FileHashPort } from "./file-hash.port";
|
|
3
|
+
|
|
4
|
+
export class FileHashNoopAdapter implements FileHashPort {
|
|
5
|
+
async hash(_path: tools.FilePathAbsolute | tools.FilePathRelative) {
|
|
6
|
+
return { etag: "noop", size: tools.Size.fromBytes(0), lastModified: tools.Timestamp.parse(1000) };
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as tools from "@bgord/tools";
|
|
2
|
+
import type { FileHashPort } from "./file-hash.port";
|
|
3
|
+
|
|
4
|
+
export class FileHashSha256BunAdapter implements FileHashPort {
|
|
5
|
+
async hash(path: tools.FilePathAbsolute | tools.FilePathRelative) {
|
|
6
|
+
const file = Bun.file(path.get());
|
|
7
|
+
|
|
8
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
9
|
+
const digest = await crypto.subtle.digest("SHA-256", arrayBuffer);
|
|
10
|
+
const etag = Buffer.from(digest).toString("hex");
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
etag,
|
|
14
|
+
size: tools.Size.fromBytes(arrayBuffer.byteLength),
|
|
15
|
+
lastModified: tools.Timestamp.parse(file.lastModified),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type * as tools from "@bgord/tools";
|
|
2
|
+
|
|
3
|
+
export type FileHashResult = { etag: string; size: tools.Size; lastModified: tools.TimestampType };
|
|
4
|
+
|
|
5
|
+
export interface FileHashPort {
|
|
6
|
+
hash(path: tools.FilePathAbsolute | tools.FilePathRelative): Promise<FileHashResult>;
|
|
7
|
+
}
|
package/src/image-info.port.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type * as tools from "@bgord/tools";
|
|
2
2
|
|
|
3
|
-
type ImageInfoType = {
|
|
3
|
+
export type ImageInfoType = {
|
|
4
|
+
height: tools.HeightType;
|
|
5
|
+
width: tools.WidthType;
|
|
6
|
+
mime: tools.Mime;
|
|
7
|
+
size: tools.Size;
|
|
8
|
+
};
|
|
4
9
|
|
|
5
10
|
export interface ImageInfoPort {
|
|
6
11
|
inspect(filePath: tools.FilePathRelative | tools.FilePathAbsolute): Promise<ImageInfoType>;
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,9 @@ export * from "./event-store-like.types";
|
|
|
29
29
|
export * from "./event-stream.vo";
|
|
30
30
|
export * from "./file-draft.service";
|
|
31
31
|
export * from "./file-draft-zip.service";
|
|
32
|
+
export * from "./file-hash.port";
|
|
33
|
+
export * from "./file-hash-noop.adapter";
|
|
34
|
+
export * from "./file-hash-sha256-bun.adapter";
|
|
32
35
|
export * from "./file-uploader.middleware";
|
|
33
36
|
export * from "./graceful-shutdown.service";
|
|
34
37
|
export * from "./gzip.service";
|
|
@@ -83,6 +86,9 @@ export * from "./prerequisites/index";
|
|
|
83
86
|
export * from "./prerequisites.service";
|
|
84
87
|
export * from "./rate-limit-store.port";
|
|
85
88
|
export * from "./rate-limit-store-node-cache.adapter";
|
|
89
|
+
export * from "./remote-file-storage.port";
|
|
90
|
+
export * from "./remote-file-storage-disk.adapter";
|
|
91
|
+
export * from "./remote-file-storage-noop.adapter";
|
|
86
92
|
export * from "./safe-parse-body.service";
|
|
87
93
|
export * from "./setup.service";
|
|
88
94
|
export * from "./shield-api-key.middleware";
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import * as tools from "@bgord/tools";
|
|
3
|
+
import type { FileHashPort } from "./file-hash.port";
|
|
4
|
+
import type {
|
|
5
|
+
RemoteFileStoragePort,
|
|
6
|
+
RemoteHeadResult,
|
|
7
|
+
RemotePutFromPathInput,
|
|
8
|
+
RemotePutFromPathResult,
|
|
9
|
+
} from "./remote-file-storage.port";
|
|
10
|
+
|
|
11
|
+
type RemoteFileStorageDiskConfig = {
|
|
12
|
+
root: tools.DirectoryPathAbsoluteType;
|
|
13
|
+
hasher: FileHashPort;
|
|
14
|
+
publicBaseUrl?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export class RemoteFileStorageDiskAdapter implements RemoteFileStoragePort {
|
|
18
|
+
constructor(private readonly config: RemoteFileStorageDiskConfig) {}
|
|
19
|
+
|
|
20
|
+
private resolveKeyToAbsoluteFilePath(key: tools.ObjectKeyType): tools.FilePathAbsolute {
|
|
21
|
+
const parts = key.split("/");
|
|
22
|
+
const filename = tools.Filename.fromString(parts.pop()!);
|
|
23
|
+
|
|
24
|
+
const directory = tools.DirectoryPathAbsoluteSchema.parse(`${this.config.root}/${parts.join("/")}`);
|
|
25
|
+
|
|
26
|
+
return tools.FilePathAbsolute.fromPartsSafe(directory, filename);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
publicUrl(key: tools.ObjectKeyType): string {
|
|
30
|
+
if (!this.config.publicBaseUrl) return `/${key}`;
|
|
31
|
+
return `${this.config.publicBaseUrl}/${key}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async putFromPath(input: RemotePutFromPathInput): Promise<RemotePutFromPathResult> {
|
|
35
|
+
const final = this.resolveKeyToAbsoluteFilePath(input.key);
|
|
36
|
+
const temporary = final.withFilename(final.getFilename().withSuffix("-part"));
|
|
37
|
+
|
|
38
|
+
await fs.mkdir(final.getDirectory(), { recursive: true });
|
|
39
|
+
|
|
40
|
+
const source = Bun.file(input.path.get());
|
|
41
|
+
await Bun.write(temporary.get(), source);
|
|
42
|
+
await fs.rename(temporary.get(), final.get());
|
|
43
|
+
|
|
44
|
+
return this.config.hasher.hash(final);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async head(key: tools.ObjectKeyType): Promise<RemoteHeadResult> {
|
|
48
|
+
const path = this.resolveKeyToAbsoluteFilePath(key);
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
return { exists: true, ...(await this.config.hasher.hash(path)) };
|
|
52
|
+
} catch {
|
|
53
|
+
return { exists: false };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async getStream(key: tools.ObjectKeyType): Promise<ReadableStream | null> {
|
|
58
|
+
const path = this.resolveKeyToAbsoluteFilePath(key);
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
return Bun.file(path.get()).stream();
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async delete(key: tools.ObjectKeyType): Promise<void> {
|
|
68
|
+
const path = this.resolveKeyToAbsoluteFilePath(key);
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
await fs.unlink(path.get());
|
|
72
|
+
} catch (error) {}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as tools from "@bgord/tools";
|
|
2
|
+
import type { LoggerPort } from "./logger.port";
|
|
3
|
+
import type {
|
|
4
|
+
RemoteFileStoragePort,
|
|
5
|
+
RemoteHeadResult,
|
|
6
|
+
RemotePutFromPathInput,
|
|
7
|
+
RemotePutFromPathResult,
|
|
8
|
+
} from "./remote-file-storage.port";
|
|
9
|
+
|
|
10
|
+
type RemoteFileStorageNoopConfig = { logger: LoggerPort; publicBaseUrl?: string };
|
|
11
|
+
|
|
12
|
+
export class RemoteFileStorageNoopAdapter implements RemoteFileStoragePort {
|
|
13
|
+
constructor(private readonly config: RemoteFileStorageNoopConfig) {}
|
|
14
|
+
|
|
15
|
+
publicUrl(key: tools.ObjectKeyType): string {
|
|
16
|
+
if (!this.config.publicBaseUrl) return `/${key}`;
|
|
17
|
+
return `${this.config.publicBaseUrl}/${key}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async putFromPath(input: RemotePutFromPathInput): Promise<RemotePutFromPathResult> {
|
|
21
|
+
this.config.logger.info({
|
|
22
|
+
message: "[NOOP] RemoteFileStorageNoopAdapter putFromPath",
|
|
23
|
+
component: "infra",
|
|
24
|
+
operation: "RemoteFileStorageNoopAdapter.putFromPath",
|
|
25
|
+
metadata: { input },
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
etag: "noop",
|
|
30
|
+
size: tools.Size.fromBytes(0),
|
|
31
|
+
lastModified: tools.Timestamp.parse(Date.now()),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async head(key: tools.ObjectKeyType): Promise<RemoteHeadResult> {
|
|
36
|
+
this.config.logger.info({
|
|
37
|
+
message: "[NOOP] RemoteFileStorageNoopAdapter head",
|
|
38
|
+
component: "infra",
|
|
39
|
+
operation: "RemoteFileStorageNoopAdapter.head",
|
|
40
|
+
metadata: { key },
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return { exists: false };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async getStream(key: tools.ObjectKeyType): Promise<ReadableStream | null> {
|
|
47
|
+
this.config.logger.info({
|
|
48
|
+
message: "[NOOP] RemoteFileStorageNoopAdapter getStream",
|
|
49
|
+
component: "infra",
|
|
50
|
+
operation: "RemoteFileStorageNoopAdapter.getStream",
|
|
51
|
+
metadata: { key },
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async delete(key: tools.ObjectKeyType): Promise<void> {
|
|
58
|
+
this.config.logger.info({
|
|
59
|
+
message: "[NOOP] RemoteFileStorageNoopAdapter delete",
|
|
60
|
+
component: "infra",
|
|
61
|
+
operation: "RemoteFileStorageNoopAdapter.delete",
|
|
62
|
+
metadata: { key },
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type * as tools from "@bgord/tools";
|
|
2
|
+
import type { FileHashResult } from "./file-hash.port";
|
|
3
|
+
|
|
4
|
+
export type RemotePutFromPathInput = {
|
|
5
|
+
key: tools.ObjectKeyType;
|
|
6
|
+
path: tools.FilePathRelative | tools.FilePathAbsolute;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type RemotePutFromPathResult = FileHashResult;
|
|
10
|
+
|
|
11
|
+
export type RemoteHeadResult = { exists: false } | ({ exists: true } & FileHashResult);
|
|
12
|
+
|
|
13
|
+
export interface RemoteFileStoragePort {
|
|
14
|
+
putFromPath(input: RemotePutFromPathInput): Promise<RemotePutFromPathResult>;
|
|
15
|
+
head(key: tools.ObjectKeyType): Promise<RemoteHeadResult>;
|
|
16
|
+
getStream(key: tools.ObjectKeyType): Promise<ReadableStream | null>;
|
|
17
|
+
delete(key: tools.ObjectKeyType): Promise<void>;
|
|
18
|
+
publicUrl(key: tools.ObjectKeyType): string;
|
|
19
|
+
}
|