2023-01-08 11:24:12 +00:00
|
|
|
import {
|
|
|
|
FileData,
|
|
|
|
FileEncoding,
|
|
|
|
SpacePrimitives,
|
|
|
|
} from "../../common/spaces/space_primitives.ts";
|
|
|
|
import type { FileMeta } from "../../common/types.ts";
|
|
|
|
import {
|
|
|
|
base64Decode,
|
|
|
|
base64Encode,
|
|
|
|
} from "../../plugos/asset_bundle/base64.ts";
|
|
|
|
import type { Plug } from "../../plugos/plug.ts";
|
|
|
|
import { Directory, Encoding, Filesystem } from "../deps.ts";
|
|
|
|
import { mime } from "../../plugos/deps.ts";
|
|
|
|
|
|
|
|
export class CapacitorSpacePrimitives implements SpacePrimitives {
|
2023-01-13 14:41:29 +00:00
|
|
|
constructor(
|
|
|
|
readonly source: Directory,
|
|
|
|
readonly root: string,
|
|
|
|
) {
|
2023-01-08 11:24:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async fetchFileList(): Promise<FileMeta[]> {
|
|
|
|
const allFiles: FileMeta[] = [];
|
|
|
|
const directory = this.source;
|
|
|
|
const root = this.root;
|
|
|
|
|
|
|
|
async function readAllFiles(dir: string) {
|
|
|
|
const files = await Filesystem.readdir({
|
|
|
|
path: `${root}/${dir}`,
|
|
|
|
directory,
|
|
|
|
});
|
|
|
|
for (const file of files.files) {
|
|
|
|
if (file.type === "file") {
|
2023-01-13 14:41:29 +00:00
|
|
|
const name = `${dir}/${file.name}`.substring(1);
|
2023-01-08 11:24:12 +00:00
|
|
|
allFiles.push({
|
2023-01-13 14:41:29 +00:00
|
|
|
name: name,
|
2023-01-08 11:24:12 +00:00
|
|
|
lastModified: file.mtime,
|
|
|
|
perm: "rw",
|
|
|
|
contentType: mime.getType(file.name) || "application/octet-stream",
|
|
|
|
size: file.size,
|
|
|
|
});
|
|
|
|
} else { // Directory
|
|
|
|
await readAllFiles(`${dir}/${file.name}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
await readAllFiles("");
|
|
|
|
return allFiles;
|
|
|
|
}
|
|
|
|
async readFile(
|
|
|
|
name: string,
|
|
|
|
encoding: FileEncoding,
|
|
|
|
): Promise<{ data: FileData; meta: FileMeta }> {
|
|
|
|
let data: FileData | undefined;
|
|
|
|
try {
|
|
|
|
switch (encoding) {
|
2023-01-13 14:41:29 +00:00
|
|
|
case "utf8":
|
2023-01-08 11:24:12 +00:00
|
|
|
data = (await Filesystem.readFile({
|
|
|
|
path: this.root + name,
|
|
|
|
directory: this.source,
|
|
|
|
encoding: Encoding.UTF8,
|
|
|
|
})).data;
|
|
|
|
break;
|
|
|
|
case "arraybuffer": {
|
|
|
|
const b64Data = (await Filesystem.readFile({
|
|
|
|
path: this.root + name,
|
|
|
|
directory: this.source,
|
|
|
|
})).data;
|
|
|
|
data = base64Decode(b64Data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "dataurl": {
|
|
|
|
const b64Data = (await Filesystem.readFile({
|
|
|
|
path: this.root + name,
|
|
|
|
directory: this.source,
|
|
|
|
})).data;
|
|
|
|
data = `data:${
|
|
|
|
mime.getType(name) || "application/octet-stream"
|
|
|
|
};base64,${b64Data}`;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {
|
2023-01-08 14:29:34 +00:00
|
|
|
data: data!,
|
2023-01-08 11:24:12 +00:00
|
|
|
meta: await this.getFileMeta(name),
|
|
|
|
};
|
2023-01-08 14:29:34 +00:00
|
|
|
} catch {
|
2023-01-08 11:24:12 +00:00
|
|
|
throw new Error(`Page not found`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
async getFileMeta(name: string): Promise<FileMeta> {
|
|
|
|
try {
|
|
|
|
const statResult = await Filesystem.stat({
|
|
|
|
path: this.root + name,
|
|
|
|
directory: this.source,
|
|
|
|
});
|
|
|
|
return {
|
|
|
|
name,
|
|
|
|
contentType: mime.getType(name) || "application/octet-stream",
|
|
|
|
lastModified: statResult.mtime,
|
|
|
|
perm: "rw",
|
|
|
|
size: statResult.size,
|
|
|
|
};
|
|
|
|
} catch (e: any) {
|
|
|
|
console.error("Error getting file meta", e.message);
|
|
|
|
throw new Error(`Page not found`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
async writeFile(
|
|
|
|
name: string,
|
|
|
|
encoding: FileEncoding,
|
|
|
|
data: FileData,
|
|
|
|
): Promise<FileMeta> {
|
|
|
|
switch (encoding) {
|
2023-01-13 14:41:29 +00:00
|
|
|
case "utf8":
|
2023-01-08 11:24:12 +00:00
|
|
|
await Filesystem.writeFile({
|
|
|
|
path: this.root + name,
|
|
|
|
directory: this.source,
|
|
|
|
encoding: Encoding.UTF8,
|
|
|
|
data: data as string,
|
|
|
|
recursive: true,
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
case "arraybuffer":
|
|
|
|
await Filesystem.writeFile({
|
|
|
|
path: this.root + name,
|
|
|
|
directory: this.source,
|
|
|
|
data: base64Encode(new Uint8Array(data as ArrayBuffer)),
|
|
|
|
recursive: true,
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
case "dataurl":
|
|
|
|
await Filesystem.writeFile({
|
|
|
|
path: this.root + name,
|
|
|
|
directory: this.source,
|
|
|
|
data: (data as string).split(";base64,")[1],
|
|
|
|
recursive: true,
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return this.getFileMeta(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
async deleteFile(name: string): Promise<void> {
|
|
|
|
await Filesystem.deleteFile({
|
|
|
|
path: this.root + name,
|
|
|
|
directory: this.source,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
proxySyscall(plug: Plug<any>, name: string, args: any[]): Promise<any> {
|
|
|
|
return plug.syscall(name, args);
|
|
|
|
}
|
|
|
|
invokeFunction(
|
|
|
|
plug: Plug<any>,
|
|
|
|
_env: string,
|
|
|
|
name: string,
|
|
|
|
args: any[],
|
|
|
|
): Promise<any> {
|
|
|
|
return plug.invoke(name, args);
|
|
|
|
}
|
|
|
|
}
|