(
path: string,
data: Uint8Array | ArrayBuffer,
mimeType = "application/octet-stream"
)
| 609 | } |
| 610 | |
| 611 | async writeFileBytes( |
| 612 | path: string, |
| 613 | data: Uint8Array | ArrayBuffer, |
| 614 | mimeType = "application/octet-stream" |
| 615 | ): Promise<void> { |
| 616 | await this.ensureInit(); |
| 617 | const normalized = await this.resolveSymlink(normalizePath(path)); |
| 618 | if (normalized === "/") |
| 619 | throw new Error("EISDIR: cannot write to root directory"); |
| 620 | |
| 621 | const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data; |
| 622 | const size = bytes.byteLength; |
| 623 | const parentPath = getParent(normalized); |
| 624 | const name = getBasename(normalized); |
| 625 | const now = Math.floor(Date.now() / 1000); |
| 626 | const T = this.tableName; |
| 627 | |
| 628 | await this.ensureParentDir(parentPath); |
| 629 | |
| 630 | const existing = ( |
| 631 | await this.sql.query<{ |
| 632 | storage_backend: string; |
| 633 | r2_key: string | null; |
| 634 | }>(`SELECT storage_backend, r2_key FROM ${T} WHERE path = ?`, normalized) |
| 635 | )[0]; |
| 636 | |
| 637 | const r2 = this.getR2(); |
| 638 | |
| 639 | if (size >= this.threshold && r2) { |
| 640 | const key = this.r2Key(normalized); |
| 641 | if (existing?.storage_backend === "r2" && existing.r2_key !== key) { |
| 642 | await r2.delete(existing.r2_key!); |
| 643 | } |
| 644 | await r2.put(key, bytes, { |
| 645 | httpMetadata: { contentType: mimeType } |
| 646 | }); |
| 647 | try { |
| 648 | await this.sql.run( |
| 649 | `INSERT INTO ${T} |
| 650 | (path, parent_path, name, type, mime_type, size, |
| 651 | storage_backend, r2_key, content_encoding, content, created_at, modified_at) |
| 652 | VALUES (?, ?, ?, 'file', ?, ?, 'r2', ?, 'base64', NULL, ?, ?) |
| 653 | ON CONFLICT(path) DO UPDATE SET |
| 654 | mime_type = excluded.mime_type, |
| 655 | size = excluded.size, |
| 656 | storage_backend = 'r2', |
| 657 | r2_key = excluded.r2_key, |
| 658 | content_encoding = 'base64', |
| 659 | content = NULL, |
| 660 | modified_at = excluded.modified_at`, |
| 661 | normalized, |
| 662 | parentPath, |
| 663 | name, |
| 664 | mimeType, |
| 665 | size, |
| 666 | key, |
| 667 | now, |
| 668 | now |
no test coverage detected