import * as fs from "fs/promises" import * as oet from "./oldEmbassyTypes" import { Volume } from "../../../Models/Volume" import * as child_process from "child_process" import { promisify } from "util" import { util, Utils } from "@start9labs/start-sdk" import { Manifest } from "./matchManifest" import { HostSystemStartOs } from "../../HostSystemStartOs" import "isomorphic-fetch" const { createUtils } = util const execFile = promisify(child_process.execFile) export class PolyfillEffects implements oet.Effects { private utils: Utils constructor( readonly effects: HostSystemStartOs, private manifest: Manifest, ) { this.utils = createUtils(effects as any) } async writeFile(input: { path: string volumeId: string toWrite: string }): Promise { await fs.writeFile( new Volume(input.volumeId, input.path).path, input.toWrite, ) } async readFile(input: { volumeId: string; path: string }): Promise { return ( await fs.readFile(new Volume(input.volumeId, input.path).path) ).toString() } async metadata(input: { volumeId: string path: string }): Promise { const stats = await fs.stat(new Volume(input.volumeId, input.path).path) return { fileType: stats.isFile() ? "file" : "directory", gid: stats.gid, uid: stats.uid, mode: stats.mode, isDir: stats.isDirectory(), isFile: stats.isFile(), isSymlink: stats.isSymbolicLink(), len: stats.size, readonly: (stats.mode & 0o200) > 0, } } async createDir(input: { volumeId: string; path: string }): Promise { const path = new Volume(input.volumeId, input.path).path await fs.mkdir(path, { recursive: true }) return path } async readDir(input: { volumeId: string; path: string }): Promise { return fs.readdir(new Volume(input.volumeId, input.path).path) } async removeDir(input: { volumeId: string; path: string }): Promise { const path = new Volume(input.volumeId, input.path).path await fs.rmdir(new Volume(input.volumeId, input.path).path, { recursive: true, }) return path } removeFile(input: { volumeId: string; path: string }): Promise { return fs.rm(new Volume(input.volumeId, input.path).path) } async writeJsonFile(input: { volumeId: string path: string toWrite: Record }): Promise { await fs.writeFile( new Volume(input.volumeId, input.path).path, JSON.stringify(input.toWrite), ) } async readJsonFile(input: { volumeId: string path: string }): Promise> { return JSON.parse( ( await fs.readFile(new Volume(input.volumeId, input.path).path) ).toString(), ) } runCommand({ command, args, timeoutMillis, }: { command: string args?: string[] | undefined timeoutMillis?: number | undefined }): Promise> { return this.utils .runCommand(this.manifest.main.image, [command, ...(args || [])], {}) .then((x) => ({ stderr: x.stderr.toString(), stdout: x.stdout.toString(), })) .then((x) => (!!x.stderr ? { error: x.stderr } : { result: x.stdout })) } runDaemon(input: { command: string; args?: string[] | undefined }): { wait(): Promise> term(): Promise } { throw new Error("Method not implemented.") } chown(input: { volumeId: string; path: string; uid: string }): Promise { throw new Error("Method not implemented.") } chmod(input: { volumeId: string path: string mode: string }): Promise { throw new Error("Method not implemented.") } sleep(timeMs: number): Promise { return new Promise((resolve) => setTimeout(resolve, timeMs)) } trace(whatToPrint: string): void { console.trace(whatToPrint) } warn(whatToPrint: string): void { console.warn(whatToPrint) } error(whatToPrint: string): void { console.error(whatToPrint) } debug(whatToPrint: string): void { console.debug(whatToPrint) } info(whatToPrint: string): void { console.log(false) } is_sandboxed(): boolean { return false } exists(input: { volumeId: string; path: string }): Promise { return this.metadata(input) .then(() => true) .catch(() => false) } bindLocal(options: { internalPort: number name: string externalPort: number }): Promise { throw new Error("Method not implemented.") } bindTor(options: { internalPort: number name: string externalPort: number }): Promise { throw new Error("Method not implemented.") } async fetch( url: string, options?: | { method?: | "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "PATCH" | undefined headers?: Record | undefined body?: string | undefined } | undefined, ): Promise<{ method: string ok: boolean status: number headers: Record body?: string | null | undefined text(): Promise json(): Promise }> { const fetched = await fetch(url, options) return { method: fetched.type, ok: fetched.ok, status: fetched.status, headers: Object.fromEntries(fetched.headers.entries()), body: await fetched.text(), text: () => fetched.text(), json: () => fetched.json(), } } runRsync(options: { srcVolume: string dstVolume: string srcPath: string dstPath: string options: oet.BackupOptions }): { id: () => Promise wait: () => Promise progress: () => Promise } { throw new Error("Method not implemented.") } }