///| JS host bridge for Hub exports (shares globalThis.__bitGitJsState with src/lib).
///|
priv struct HubJsHostFs {
host_id : Int
}
///|
fn hub_make_host_fs(host_id : Int) -> HubJsHostFs {
{ host_id, }
}
// --- extern "js" FFI (same host state as src/lib) ---
///|
extern "js" fn hub_js_host_last_error() -> String =
#| () => globalThis.__bitGitJsLastError ?? ""
///|
extern "js" fn hub_js_host_write_file(
host_id : Int,
path : String,
content : Array[Byte],
) -> String? =
#| (hostId, path, content) => {
#| const state = globalThis.__bitGitJsState ??= { nextHostId: 1, hosts: new Map() };
#| const host = state.hosts.get(hostId);
#| if (!host) return `host ${hostId} not found`;
#| try { host.writeFile(path, Uint8Array.from(content ?? [])); return undefined; }
#| catch (e) { return String(e?.message ?? e); }
#| }
///|
extern "js" fn hub_js_host_write_string(
host_id : Int,
path : String,
content : String,
) -> String? =
#| (hostId, path, content) => {
#| const state = globalThis.__bitGitJsState ??= { nextHostId: 1, hosts: new Map() };
#| const host = state.hosts.get(hostId);
#| if (!host) return `host ${hostId} not found`;
#| try { host.writeString(path, content); return undefined; }
#| catch (e) { return String(e?.message ?? e); }
#| }
///|
extern "js" fn hub_js_host_mkdir_p(host_id : Int, path : String) -> String? =
#| (hostId, path) => {
#| const state = globalThis.__bitGitJsState ??= { nextHostId: 1, hosts: new Map() };
#| const host = state.hosts.get(hostId);
#| if (!host) return `host ${hostId} not found`;
#| try { host.mkdirP(path); return undefined; }
#| catch (e) { return String(e?.message ?? e); }
#| }
///|
extern "js" fn hub_js_host_read_file(
host_id : Int,
path : String,
) -> Array[Byte]? =
#| (hostId, path) => {
#| const state = globalThis.__bitGitJsState ??= { nextHostId: 1, hosts: new Map() };
#| const host = state.hosts.get(hostId);
#| if (!host) { globalThis.__bitGitJsLastError = `host ${hostId} not found`; return { $tag: 0 }; }
#| try {
#| const v = host.readFile(path);
#| if (v instanceof Uint8Array) return { $tag: 1, _0: Array.from(v) };
#| if (v instanceof ArrayBuffer) return { $tag: 1, _0: Array.from(new Uint8Array(v)) };
#| if (Array.isArray(v)) return { $tag: 1, _0: v.map(x => Number(x) & 0xff) };
#| if (typeof v === 'string') return { $tag: 1, _0: Array.from(new TextEncoder().encode(v)) };
#| globalThis.__bitGitJsLastError = 'readFile must return Uint8Array/ArrayBuffer/Array/string';
#| return { $tag: 0 };
#| } catch (e) { globalThis.__bitGitJsLastError = String(e?.message ?? e); return { $tag: 0 }; }
#| }
///|
extern "js" fn hub_js_host_readdir(
host_id : Int,
path : String,
) -> Array[String]? =
#| (hostId, path) => {
#| const state = globalThis.__bitGitJsState ??= { nextHostId: 1, hosts: new Map() };
#| const host = state.hosts.get(hostId);
#| if (!host) { globalThis.__bitGitJsLastError = `host ${hostId} not found`; return { $tag: 0 }; }
#| try {
#| const entries = host.readdir(path);
#| return { $tag: 1, _0: Array.from(entries) };
#| } catch (e) { globalThis.__bitGitJsLastError = String(e?.message ?? e); return { $tag: 0 }; }
#| }
///|
extern "js" fn hub_js_host_is_dir(host_id : Int, path : String) -> Bool =
#| (hostId, path) => {
#| const state = globalThis.__bitGitJsState ??= { nextHostId: 1, hosts: new Map() };
#| const host = state.hosts.get(hostId);
#| return host?.isDir?.(path) ?? false;
#| }
///|
extern "js" fn hub_js_host_is_file(host_id : Int, path : String) -> Bool =
#| (hostId, path) => {
#| const state = globalThis.__bitGitJsState ??= { nextHostId: 1, hosts: new Map() };
#| const host = state.hosts.get(hostId);
#| return host?.isFile?.(path) ?? false;
#| }
///|
extern "js" fn hub_js_host_mtime(host_id : Int, path : String) -> Array[Int]? =
#| (hostId, path) => {
#| const state = globalThis.__bitGitJsState ??= { nextHostId: 1, hosts: new Map() };
#| const host = state.hosts.get(hostId);
#| if (!host) {
#| globalThis.__bitGitJsLastError = `host ${hostId} not found`;
#| return { $tag: 0 };
#| }
#| if (typeof host.mtime !== 'function') {
#| globalThis.__bitGitJsLastError = 'host.mtime(path) is required';
#| return { $tag: 0 };
#| }
#| try {
#| const value = host.mtime(path);
#| if (!Array.isArray(value) || value.length !== 2) {
#| globalThis.__bitGitJsLastError = 'host.mtime(path) must return [seconds, nanoseconds]';
#| return { $tag: 0 };
#| }
#| const seconds = Number(value[0]);
#| const nanoseconds = Number(value[1]);
#| if (!Number.isInteger(seconds) || !Number.isInteger(nanoseconds)) {
#| globalThis.__bitGitJsLastError = 'host.mtime(path) must return integer seconds and nanoseconds';
#| return { $tag: 0 };
#| }
#| return { $tag: 1, _0: [seconds, nanoseconds] };
#| } catch (error) {
#| globalThis.__bitGitJsLastError = String(error?.message ?? error);
#| return { $tag: 0 };
#| }
#| }
// --- Trait implementations ---
///|
fn bytes_from_array(arr : Array[Byte]) -> Bytes {
Bytes::from_iter(arr.iter())
}
///|
impl @bit.FileSystem for HubJsHostFs with fn mkdir_p(self, path) {
match hub_js_host_mkdir_p(self.host_id, path) {
Some(e) => raise @bit.GitError::IoError(e)
None => ()
}
}
///|
impl @bit.FileSystem for HubJsHostFs with fn write_file(self, path, content) {
let arr = Array::new(capacity=content.length())
for i in 0.. raise @bit.GitError::IoError(e)
None => ()
}
}
///|
impl @bit.FileSystem for HubJsHostFs with fn write_string(self, path, content) {
match hub_js_host_write_string(self.host_id, path, content) {
Some(e) => raise @bit.GitError::IoError(e)
None => ()
}
}
///|
impl @bit.FileSystem for HubJsHostFs with fn remove_file(_self, _path) {
// Not needed for hub reads
}
///|
impl @bit.FileSystem for HubJsHostFs with fn remove_dir(_self, _path) {
// Not needed for hub reads
}
///|
impl @bit.RepoFileSystem for HubJsHostFs with fn read_file(self, path) {
match hub_js_host_read_file(self.host_id, path) {
Some(arr) => bytes_from_array(arr)
None => raise @bit.GitError::IoError(hub_js_host_last_error())
}
}
///|
impl @bit.RepoFileSystem for HubJsHostFs with fn readdir(self, path) {
match hub_js_host_readdir(self.host_id, path) {
Some(arr) => arr
None => raise @bit.GitError::IoError(hub_js_host_last_error())
}
}
///|
impl @bit.RepoFileSystem for HubJsHostFs with fn is_dir(self, path) {
hub_js_host_is_dir(self.host_id, path)
}
///|
impl @bit.RepoFileSystem for HubJsHostFs with fn is_file(self, path) {
hub_js_host_is_file(self.host_id, path)
}
///|
impl @bit.RepoFileSystem for HubJsHostFs with fn mtime(self, path) {
match hub_js_host_mtime(self.host_id, path) {
Some(value) => (value[0], value[1])
None => raise @bit.GitError::IoError(hub_js_host_last_error())
}
}