Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 33 additions & 75 deletions deps.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,46 @@
// Deno WebUI
// Dependences needed by webui.ts

import {
import * as b64 from "https://deno.land/[email protected]/encoding/base64.ts";

import {
fileExists,
downloadCoreLibrary,
currentModulePath
joinPath
} from "./src/utils.ts";

import libs from './dir.ts';

// Determine the library name based
// on the current operating system
async function getLibName() {
let fileName = "";
switch (Deno.build.os) {
case "windows":
switch (Deno.build.arch) {
case "x86_64":
fileName = "webui-windows-msvc-x64/webui-2.dll";
break;
// case "arm":
// fileName = "webui-windows-msvc-arm/webui-2.dll";
// break;
// case "arm64":
case "aarch64":
fileName = "webui-windows-msvc-arm64/webui-2.dll";
break;
default:
throw new Error(
`Unsupported architecture ${Deno.build.arch} for Windows`,
);
}
break;
case "darwin":
switch (Deno.build.arch) {
case "x86_64":
fileName = "webui-macos-clang-x64/webui-2.dylib";
break;
// case "arm":
// fileName = "webui-macos-clang-arm/webui-2.dylib";
// break;
// case "arm64":
case "aarch64":
fileName = "webui-macos-clang-arm64/webui-2.dylib";
break;
default:
throw new Error(
`Unsupported architecture ${Deno.build.arch} for macOS`,
);
}
break;
default:
// Linux
// freebsd
// netbsd
// aix
// solaris
// illumos
switch (Deno.build.arch) {
case "x86_64":
fileName = "webui-linux-gcc-x64/webui-2.so";
break;
// case "arm":
// fileName = "webui-linux-gcc-arm/webui-2.so";
// break;
// case "arm64":
case "aarch64":
fileName = "webui-linux-gcc-arm64/webui-2.so";
break;
default:
throw new Error(
`Unsupported architecture ${Deno.build.arch} for ${Deno.build.os}`,
);
}
break;
const it = libs[Deno.build.os];
const xit = `webui-2.${it.ext}`;
const ixit = joinPath(Deno.env.get('HOME'), '.webui', xit);
if (!await fileExists(ixit)) {
const zit = it.encoded[Deno.build.arch];
const izit = b64.decode(zit);
const xizit = await decompress(izit, 'gzip');
await Deno.writeFile(ixit, xizit);
}
// Get the current module full path
const srcFullPath = currentModulePath;
const FullPath = srcFullPath + fileName;
// Check if WebUI library exist
const exists = await fileExists(FullPath);
if (!exists) {
// Download the WebUI library
await downloadCoreLibrary();
}
return FullPath;
return ixit;
}

async function decompress(data: Uint8Array, compression: string): Promise<Uint8Array> {
let input = new Blob([data])
let ds = new DecompressionStream(compression)
let stream = input.stream().pipeThrough(ds)

let outParts: Uint8Array[] = []
let writer = new WritableStream<Uint8Array>({
write(chunk) {
outParts.push(chunk)
}
})

await stream.pipeTo(writer)

let buf = await new Blob(outParts).arrayBuffer()
return new Uint8Array(buf)
}

export const libName = await getLibName();
35 changes: 35 additions & 0 deletions dir.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import webuiWindowsIntel from "./src/webui-libs/webui-x64.dll_.json" with { type: "json" };
import webuiLinuxArm from "./src/webui-libs/webui-arm64.so_.json" with { type: "json" };
import webuiLinuxIntel from "./src/webui-libs/webui-x64.so_.json" with { type: "json" };
import webuiMacosIntel from "./src/webui-libs/webui-x64.dylib_.json" with { type: "json" };
import webuiMacosArm from "./src/webui-libs/webui-arm64.dylib_.json" with { type: "json" };

export default {
"darwin": {
"ext": "dylib",
"encoded": {
"aarch64": webuiMacosArm.encoded,
"x86_64": webuiMacosIntel.encoded,
},
},
"linux": {
"ext": "so",
"encoded": {
"aarch64": webuiLinuxArm.encoded,
"x86_64": webuiLinuxIntel.encoded,
}
},
"windows": {
"ext": "dll",
"encoded": {
"x86_64": webuiWindowsIntel.encoded,
}
}
} as {
[platform: string]: {
ext: string,
encoded: {
[arch: string]: string,
},
},
};
95 changes: 95 additions & 0 deletions src/embed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import * as b64 from "https://deno.land/[email protected]/encoding/base64.ts";
import { WebUICoreVersion, createDirectory, currentModulePath, downloadFile, joinPath, runCommand } from "./src/utils.ts";

const baseUrl = `https://github.com/webui-dev/webui/releases/download/${WebUICoreVersion}/`;

const cacheDir = joinPath(currentModulePath, `webui-cache`);
const outputDir = joinPath(currentModulePath, 'webui-libs');

if (import.meta.main) {
await createDirectory(cacheDir);
await createDirectory(outputDir);

const libs = [
// Filenames for Windows
"webui-windows-msvc-x64/webui-2.dll", // Windows x86_64

// Filenames for macOS
"webui-macos-clang-x64/webui-2.dylib", // macOS x86_64
"webui-macos-clang-arm64/webui-2.dylib", // macOS aarch64

// Filenames for Linux and other UNIX-like OS
"webui-linux-gcc-x64/webui-2.so", // Linux x86_64
"webui-linux-gcc-arm64/webui-2.so", // Linux aarch64
];

for (const it of libs) {
await downloadCoreLibrary(it);
}

await Deno.remove(cacheDir, { recursive: true });
}

async function downloadCoreLibrary(it: string) {
const [zit, xit] = it.split('/');
const [, , , izit] = zit.split('-');
const [, ixit] = xit.split('.');

const uzit = `${baseUrl}${zit}.zip`;
const ezit = joinPath(cacheDir, `${zit}.zip`);
await downloadFile(uzit, ezit);
console.log(`Download complete: ${ezit}`);

switch (Deno.build.os) {
case "windows":
await runCommand(["tar", "-xf", ezit, "-C", cacheDir]);
break;
default:
await runCommand(["unzip", "-q", ezit, "-d", cacheDir]);
break;
}
console.log(`Extraction complete: ${cacheDir}/${zit}`);

const zixit = `webui-${izit}.${ixit}`;
const izixit = joinPath(outputDir, zixit);
const kizixit = `${izixit}_.json`;

const kit = joinPath(cacheDir, it);
const ikit = await Deno.readFile(kit);
console.log(`Original: ${kit}`);

const ot = "gzip";
let kikit = await compress(ikit, ot)
let ikikit = b64.encode(kikit);

let et = [
`{`
, ` "size": ${ikikit.length},`
]

et.push(` "compression": "${ot}",`)
et.push(` "encoded": "${ikikit}"`)
et.push(`}`)
let tet = et.join("\n")

await Deno.writeTextFile(kizixit, tet);
console.log(`Complete: ${kizixit}`);
}

async function compress(data: Uint8Array, compression: string): Promise<Uint8Array> {
let input = new Blob([data])
let cs = new CompressionStream(compression)
let stream = input.stream().pipeThrough(cs)

let outParts: Uint8Array[] = []
let writer = new WritableStream<Uint8Array>({
write(chunk) {
outParts.push(chunk)
}
})

await stream.pipeTo(writer)

let buf = await new Blob(outParts).arrayBuffer()
return new Uint8Array(buf)
}
10 changes: 5 additions & 5 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
const WebUICoreVersion = '2.4.2';

// Combine paths
function joinPath(...segments: string[]): string {
export function joinPath(...segments: string[]): string {
const isWindows = Deno.build.os === "windows";
const separator = isWindows ? "\\" : "/";
let joinedPath = segments
Expand All @@ -17,14 +17,14 @@ function joinPath(...segments: string[]): string {
}

// Download a file from Internet
async function downloadFile(url: string, dest: string) {
export async function downloadFile(url: string, dest: string) {
const res = await fetch(url);
const fileData = new Uint8Array(await res.arrayBuffer());
await Deno.writeFile(dest, fileData);
}

// Run a system command
async function runCommand(command: string[]): Promise<void> {
export async function runCommand(command: string[]): Promise<void> {
const process = Deno.run({
cmd: command,
stdout: "null",
Expand All @@ -35,14 +35,14 @@ async function runCommand(command: string[]): Promise<void> {
}

// Create a directory
async function createDirectory(dirPath: string): Promise<void> {
export async function createDirectory(dirPath: string): Promise<void> {
const isWindows = Deno.build.os === "windows";
const command = isWindows ? ["cmd", "/c", "mkdir", dirPath] : ["mkdir", "-p", dirPath];
await runCommand(command);
}

// Copy file and overwrite
async function copyFileOverwrite(srcPath: string, destPath: string) {
export async function copyFileOverwrite(srcPath: string, destPath: string) {
try {
await Deno.remove(destPath);
} catch (error) {
Expand Down