FS API encoding support

This commit is contained in:
Zef Hemel
2022-09-05 16:15:01 +02:00
parent 9415624b93
commit 0ed956feda
18 changed files with 190 additions and 88 deletions
@@ -9,7 +9,11 @@ import {
} from "fs/promises";
import * as path from "path";
import { AttachmentMeta, PageMeta } from "../types";
import { SpacePrimitives } from "./space_primitives";
import {
AttachmentData,
AttachmentEncoding,
SpacePrimitives,
} from "./space_primitives";
import { Plug } from "@plugos/plugos/plug";
import { realpathSync } from "fs";
import mime from "mime-types";
@@ -199,20 +203,27 @@ export class DiskSpacePrimitives implements SpacePrimitives {
}
async readAttachment(
name: string
): Promise<{ buffer: ArrayBuffer; meta: AttachmentMeta }> {
name: string,
encoding: AttachmentEncoding
): Promise<{ data: AttachmentData; meta: AttachmentMeta }> {
const localPath = this.attachmentNameToPath(name);
let fileBuffer = await readFile(localPath);
let fileBuffer = await readFile(localPath, {
encoding: encoding === "dataurl" ? "base64" : null,
});
try {
const s = await stat(localPath);
let contentType = mime.lookup(name) || "application/octet-stream";
return {
buffer: fileBuffer.buffer,
data:
encoding === "dataurl"
? `data:${contentType};base64,${fileBuffer}`
: (fileBuffer as Buffer).buffer,
meta: {
name: name,
lastModified: s.mtime.getTime(),
size: s.size,
contentType: mime.lookup(name) || "application/octet-stream",
contentType: contentType,
perm: "rw",
},
};
@@ -241,7 +252,7 @@ export class DiskSpacePrimitives implements SpacePrimitives {
async writeAttachment(
name: string,
blob: ArrayBuffer,
data: AttachmentData,
selfUpdate?: boolean,
lastModified?: number
): Promise<AttachmentMeta> {
@@ -251,7 +262,11 @@ export class DiskSpacePrimitives implements SpacePrimitives {
await mkdir(path.dirname(localPath), { recursive: true });
// Actually write the file
await writeFile(localPath, Buffer.from(blob));
if (typeof data === "string") {
await writeFile(localPath, data.split(",")[1], { encoding: "base64" });
} else {
await writeFile(localPath, Buffer.from(data));
}
if (lastModified) {
let d = new Date(lastModified);
@@ -3,7 +3,11 @@ import { Plug } from "@plugos/plugos/plug";
import { AttachmentMeta, PageMeta } from "../types";
import { plugPrefix, trashPrefix } from "./constants";
import { SpacePrimitives } from "./space_primitives";
import {
AttachmentData,
AttachmentEncoding,
SpacePrimitives,
} from "./space_primitives";
export class EventedSpacePrimitives implements SpacePrimitives {
constructor(private wrapped: SpacePrimitives, private eventHook: EventHook) {}
@@ -75,9 +79,10 @@ export class EventedSpacePrimitives implements SpacePrimitives {
}
readAttachment(
name: string
): Promise<{ buffer: ArrayBuffer; meta: AttachmentMeta }> {
return this.wrapped.readAttachment(name);
name: string,
encoding: AttachmentEncoding
): Promise<{ data: AttachmentData; meta: AttachmentMeta }> {
return this.wrapped.readAttachment(name, encoding);
}
getAttachmentMeta(name: string): Promise<AttachmentMeta> {
@@ -1,6 +1,10 @@
import { AttachmentMeta, PageMeta } from "../types";
import { Plug } from "@plugos/plugos/plug";
import { SpacePrimitives } from "./space_primitives";
import {
AttachmentData,
AttachmentEncoding,
SpacePrimitives,
} from "./space_primitives";
export class HttpSpacePrimitives implements SpacePrimitives {
fsUrl: string;
@@ -145,8 +149,9 @@ export class HttpSpacePrimitives implements SpacePrimitives {
}
async readAttachment(
name: string
): Promise<{ buffer: ArrayBuffer; meta: AttachmentMeta }> {
name: string,
encoding: AttachmentEncoding
): Promise<{ data: AttachmentData; meta: AttachmentMeta }> {
let res = await this.authenticatedFetch(`${this.fsaUrl}/${name}`, {
method: "GET",
});
@@ -155,25 +160,29 @@ export class HttpSpacePrimitives implements SpacePrimitives {
}
let blob = await res.blob();
return {
buffer: await blob.arrayBuffer(),
data:
encoding === "arraybuffer"
? await blob.arrayBuffer()
: arrayBufferToDataUrl(await blob.arrayBuffer()),
meta: this.responseToAttachmentMeta(name, res),
};
}
async writeAttachment(
name: string,
buffer: ArrayBuffer,
data: AttachmentData,
selfUpdate?: boolean,
lastModified?: number
): Promise<AttachmentMeta> {
// TODO: lastModified ignored for now
if (typeof data === "string") {
data = dataUrlToArrayBuffer(data);
}
let res = await this.authenticatedFetch(`${this.fsaUrl}/${name}`, {
method: "PUT",
body: buffer,
body: data,
headers: {
"Last-Modified": lastModified ? "" + lastModified : undefined,
"Content-type": "application/octet-stream",
"Content-length": "" + buffer.byteLength,
},
});
const newMeta = this.responseToAttachmentMeta(name, res);
@@ -268,3 +277,23 @@ export class HttpSpacePrimitives implements SpacePrimitives {
};
}
}
function dataUrlToArrayBuffer(dataUrl: string): ArrayBuffer {
var binary_string = window.atob(dataUrl.split(",")[1]);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
function arrayBufferToDataUrl(buffer: ArrayBuffer): string {
var binary = "";
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return `data:application/octet-stream,${window.btoa(binary)}`;
}
@@ -1,4 +1,8 @@
import { SpacePrimitives } from "./space_primitives";
import {
AttachmentData,
AttachmentEncoding,
SpacePrimitives,
} from "./space_primitives";
import { AttachmentMeta, PageMeta } from "../types";
import Dexie, { Table } from "dexie";
import { Plug } from "@plugos/plugos/plug";
@@ -26,8 +30,9 @@ export class IndexedDBSpacePrimitives implements SpacePrimitives {
throw new Error("Method not implemented.");
}
readAttachment(
name: string
): Promise<{ buffer: ArrayBuffer; meta: AttachmentMeta }> {
name: string,
encoding: AttachmentEncoding
): Promise<{ data: AttachmentData; meta: AttachmentMeta }> {
throw new Error("Method not implemented.");
}
getAttachmentMeta(name: string): Promise<AttachmentMeta> {
+11 -6
View File
@@ -1,4 +1,8 @@
import { SpacePrimitives } from "./space_primitives";
import {
AttachmentData,
AttachmentEncoding,
SpacePrimitives,
} from "./space_primitives";
import { AttachmentMeta, PageMeta } from "../types";
import { EventEmitter } from "@plugos/plugos/event";
import { Plug } from "@plugos/plugos/plug";
@@ -225,20 +229,21 @@ export class Space
return this.space.fetchAttachmentList();
}
readAttachment(
name: string
): Promise<{ buffer: ArrayBuffer; meta: AttachmentMeta }> {
return this.space.readAttachment(name);
name: string,
encoding: AttachmentEncoding
): Promise<{ data: AttachmentData; meta: AttachmentMeta }> {
return this.space.readAttachment(name, encoding);
}
getAttachmentMeta(name: string): Promise<AttachmentMeta> {
return this.space.getAttachmentMeta(name);
}
writeAttachment(
name: string,
blob: ArrayBuffer,
data: AttachmentData,
selfUpdate?: boolean | undefined,
lastModified?: number | undefined
): Promise<AttachmentMeta> {
return this.space.writeAttachment(name, blob, selfUpdate, lastModified);
return this.space.writeAttachment(name, data, selfUpdate, lastModified);
}
deleteAttachment(name: string): Promise<void> {
return this.space.deleteAttachment(name);
+6 -3
View File
@@ -1,6 +1,8 @@
import { Plug } from "@plugos/plugos/plug";
import { AttachmentMeta, PageMeta } from "../types";
export type AttachmentEncoding = "arraybuffer" | "dataurl";
export type AttachmentData = ArrayBuffer | string;
export interface SpacePrimitives {
// Pages
fetchPageList(): Promise<{ pages: Set<PageMeta>; nowTimestamp: number }>;
@@ -20,12 +22,13 @@ export interface SpacePrimitives {
nowTimestamp: number;
}>;
readAttachment(
name: string
): Promise<{ buffer: ArrayBuffer; meta: AttachmentMeta }>;
name: string,
encoding: AttachmentEncoding
): Promise<{ data: AttachmentData; meta: AttachmentMeta }>;
getAttachmentMeta(name: string): Promise<AttachmentMeta>;
writeAttachment(
name: string,
blob: ArrayBuffer,
data: AttachmentData,
selfUpdate?: boolean,
lastModified?: number
): Promise<AttachmentMeta>;