mirror of
https://github.com/ChiChou/entdb.git
synced 2026-09-30 16:19:36 +02:00
Fix base path and restore wasm engine
This commit is contained in:
1 parent
32c2b01062
commit
7690ba766e
4 files changed
+107
-71
No files matched your search
@@ -1,7 +1,11 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
|
const basePath = process.env.NEXT_PUBLIC_BASE_PATH || "";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
output: "export",
|
output: "export",
|
||||||
|
basePath,
|
||||||
|
assetPrefix: basePath || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
+8
-16
@@ -1,31 +1,23 @@
|
|||||||
import type { Engine } from "./types";
|
import type { Engine } from "./types";
|
||||||
import { WASMEngine } from "./wasm";
|
import { WASMEngine } from "./wasm";
|
||||||
|
import { checkWASMSupport as checkSQLiteWASMSupport } from "./wasm";
|
||||||
import { KVEngine } from "./kv";
|
import { KVEngine } from "./kv";
|
||||||
|
|
||||||
let wasmSupported: boolean | null = null;
|
let wasmSupported: boolean | null = null;
|
||||||
|
const wasmDisabled = process.env.NEXT_PUBLIC_USE_WASM === "0";
|
||||||
|
|
||||||
async function checkWASMSupport(): Promise<boolean> {
|
async function checkWASMSupport(): Promise<boolean> {
|
||||||
if (wasmSupported !== null) return wasmSupported;
|
if (wasmSupported !== null) return wasmSupported;
|
||||||
|
|
||||||
try {
|
wasmSupported = await checkSQLiteWASMSupport();
|
||||||
if (typeof WebAssembly === "undefined") {
|
return wasmSupported;
|
||||||
wasmSupported = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await WebAssembly.instantiate(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
|
|
||||||
|
|
||||||
await import("@sqlite.org/sqlite-wasm");
|
|
||||||
|
|
||||||
wasmSupported = true;
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
wasmSupported = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createEngine(group: string): Promise<Engine> {
|
export async function createEngine(group: string): Promise<Engine> {
|
||||||
|
if (wasmDisabled) {
|
||||||
|
return new KVEngine(group);
|
||||||
|
}
|
||||||
|
|
||||||
const supported = await checkWASMSupport();
|
const supported = await checkWASMSupport();
|
||||||
if (supported) {
|
if (supported) {
|
||||||
return new WASMEngine();
|
return new WASMEngine();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Engine } from "./types";
|
import type { Engine } from "./types";
|
||||||
import type { OS } from "@/lib/types";
|
import type { OS } from "@/lib/types";
|
||||||
import { addBasePath, dataBaseURL } from "@/lib/env";
|
import { dataBaseURL } from "@/lib/env";
|
||||||
import { fetchText, fetchLines } from "@/lib/client";
|
import { fetchText, fetchLines } from "@/lib/client";
|
||||||
|
|
||||||
interface KVRecord {
|
interface KVRecord {
|
||||||
@@ -55,14 +55,14 @@ export class KVEngine implements Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async listOS(): Promise<OS[]> {
|
async listOS(): Promise<OS[]> {
|
||||||
const list = await fetchText(addBasePath(`${this.#baseURL}/list.json`));
|
const list = await fetchText(`${this.#baseURL}/list.json`);
|
||||||
return JSON.parse(list);
|
return JSON.parse(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPaths(build: string): Promise<string[]> {
|
async getPaths(build: string): Promise<string[]> {
|
||||||
const os = await this.findOS(build);
|
const os = await this.findOS(build);
|
||||||
const tag = `${os.version}_${build}`;
|
const tag = `${os.version}_${build}`;
|
||||||
return fetchLines(addBasePath(`${this.#baseURL}/${tag}/paths.txt`));
|
return fetchLines(`${this.#baseURL}/${tag}/paths.txt`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBinaryXML(build: string, path: string): Promise<string> {
|
async getBinaryXML(build: string, path: string): Promise<string> {
|
||||||
|
|||||||
+92
-52
@@ -2,40 +2,80 @@ import type { Engine } from "./types";
|
|||||||
import type { OS } from "@/lib/types";
|
import type { OS } from "@/lib/types";
|
||||||
import { dataBaseURL } from "@/lib/env";
|
import { dataBaseURL } from "@/lib/env";
|
||||||
|
|
||||||
|
type SQLite3Database = {
|
||||||
|
exec: (options: {
|
||||||
|
sql: string;
|
||||||
|
bind?: unknown[];
|
||||||
|
rowMode: "array";
|
||||||
|
returnValue: "resultRows";
|
||||||
|
}) => unknown[][];
|
||||||
|
close: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
type SQLite3API = {
|
type SQLite3API = {
|
||||||
Database: new (data: ArrayLike<number | bigint>) => {
|
oo1: {
|
||||||
exec: (
|
DB: new (filename?: string, flags?: string, vfs?: string) => SQLite3Database;
|
||||||
sql: string,
|
};
|
||||||
bind?: unknown[]
|
capi: {
|
||||||
) => {
|
sqlite3_js_posix_create_file: (
|
||||||
columns: string[];
|
filename: string,
|
||||||
rows: unknown[][];
|
data: Uint8Array | ArrayBuffer,
|
||||||
}[];
|
dataLen?: number
|
||||||
close: () => void;
|
) => void;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let sqlite3Module: SQLite3API | null = null;
|
let sqlite3Module: SQLite3API | null = null;
|
||||||
let dbInstance: InstanceType<SQLite3API["Database"]> | null = null;
|
let dbInstance: SQLite3Database | null = null;
|
||||||
let dbReady = false;
|
let dbReady = false;
|
||||||
|
|
||||||
async function loadSQLite(): Promise<SQLite3API> {
|
async function loadSQLite(): Promise<SQLite3API> {
|
||||||
if (sqlite3Module) return sqlite3Module;
|
if (sqlite3Module) return sqlite3Module;
|
||||||
|
|
||||||
const sqliteModule = await import("@sqlite.org/sqlite-wasm");
|
const sqliteModule = await import("@sqlite.org/sqlite-wasm");
|
||||||
sqlite3Module = (sqliteModule.default || sqliteModule) as unknown as SQLite3API;
|
const initSQLite = sqliteModule.default;
|
||||||
|
sqlite3Module = (await initSQLite()) as unknown as SQLite3API;
|
||||||
return sqlite3Module;
|
return sqlite3Module;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDB(): Promise<InstanceType<SQLite3API["Database"]>> {
|
export async function checkWASMSupport(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
if (typeof WebAssembly === "undefined") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await WebAssembly.instantiate(
|
||||||
|
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)
|
||||||
|
);
|
||||||
|
await loadSQLite();
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDB(): Promise<SQLite3Database> {
|
||||||
if (dbReady && dbInstance) return dbInstance;
|
if (dbReady && dbInstance) return dbInstance;
|
||||||
|
|
||||||
const sqlite3 = await loadSQLite();
|
const sqlite3 = await loadSQLite();
|
||||||
|
|
||||||
const response = await fetch(`${dataBaseURL()}/ent.db`);
|
const response = await fetch(`${dataBaseURL()}/ent.db`);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to fetch SQLite database: ${response.status} ${response.statusText}`
|
||||||
|
);
|
||||||
|
}
|
||||||
const buffer = await response.arrayBuffer();
|
const buffer = await response.arrayBuffer();
|
||||||
|
const bytes = new Uint8Array(buffer);
|
||||||
|
const filename = "/ent.db";
|
||||||
|
|
||||||
dbInstance = new sqlite3.Database(new Uint8Array(buffer));
|
try {
|
||||||
|
sqlite3.capi.sqlite3_js_posix_create_file(filename, bytes, bytes.byteLength);
|
||||||
|
} catch {
|
||||||
|
// Ignore duplicate file creation in hot-reload or repeated initialization cases.
|
||||||
|
}
|
||||||
|
|
||||||
|
dbInstance = new sqlite3.oo1.DB(filename, "r");
|
||||||
dbReady = true;
|
dbReady = true;
|
||||||
return dbInstance;
|
return dbInstance;
|
||||||
}
|
}
|
||||||
@@ -43,64 +83,64 @@ async function getDB(): Promise<InstanceType<SQLite3API["Database"]>> {
|
|||||||
export class WASMEngine implements Engine {
|
export class WASMEngine implements Engine {
|
||||||
async listOS(): Promise<OS[]> {
|
async listOS(): Promise<OS[]> {
|
||||||
const db = await getDB();
|
const db = await getDB();
|
||||||
const results = db.exec(
|
const rows = db.exec({
|
||||||
"SELECT name, version, build, devices FROM os ORDER BY version DESC"
|
sql: "SELECT name, version, build, devices FROM os ORDER BY version DESC",
|
||||||
);
|
rowMode: "array",
|
||||||
if (!results.length) return [];
|
returnValue: "resultRows",
|
||||||
|
});
|
||||||
|
|
||||||
const cols = results[0].columns;
|
return rows.map((row) => ({
|
||||||
const nameIdx = cols.indexOf("name");
|
name: row[0] as string,
|
||||||
const versionIdx = cols.indexOf("version");
|
version: row[1] as string,
|
||||||
const buildIdx = cols.indexOf("build");
|
build: row[2] as string,
|
||||||
const devicesIdx = cols.indexOf("devices");
|
devices: JSON.parse(row[3] as string),
|
||||||
|
|
||||||
return results[0].rows.map((row) => ({
|
|
||||||
name: row[nameIdx] as string,
|
|
||||||
version: row[versionIdx] as string,
|
|
||||||
build: row[buildIdx] as string,
|
|
||||||
devices: JSON.parse(row[devicesIdx] as string),
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPaths(build: string): Promise<string[]> {
|
async getPaths(build: string): Promise<string[]> {
|
||||||
const db = await getDB();
|
const db = await getDB();
|
||||||
const results = db.exec(
|
const rows = db.exec({
|
||||||
`SELECT path FROM bin JOIN os ON bin.osid=os.id WHERE os.build=?`,
|
sql: `SELECT path FROM bin JOIN os ON bin.osid=os.id WHERE os.build=?`,
|
||||||
[build]
|
bind: [build],
|
||||||
);
|
rowMode: "array",
|
||||||
if (!results.length) return [];
|
returnValue: "resultRows",
|
||||||
return results[0].rows.map((row) => row[0] as string);
|
});
|
||||||
|
return rows.map((row) => row[0] as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBinaryXML(build: string, path: string): Promise<string> {
|
async getBinaryXML(build: string, path: string): Promise<string> {
|
||||||
const db = await getDB();
|
const db = await getDB();
|
||||||
const results = db.exec(
|
const rows = db.exec({
|
||||||
`SELECT xml FROM bin JOIN os ON bin.osid=os.id WHERE os.build=? AND bin.path=?`,
|
sql: `SELECT xml FROM bin JOIN os ON bin.osid=os.id WHERE os.build=? AND bin.path=?`,
|
||||||
[build, path]
|
bind: [build, path],
|
||||||
);
|
rowMode: "array",
|
||||||
if (!results.length || !results[0].rows.length) {
|
returnValue: "resultRows",
|
||||||
|
});
|
||||||
|
if (!rows.length) {
|
||||||
throw new Error(`Binary not found: ${path}`);
|
throw new Error(`Binary not found: ${path}`);
|
||||||
}
|
}
|
||||||
return results[0].rows[0][0] as string;
|
return rows[0][0] as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getKeys(build: string): Promise<string[]> {
|
async getKeys(build: string): Promise<string[]> {
|
||||||
const db = await getDB();
|
const db = await getDB();
|
||||||
const results = db.exec(
|
const rows = db.exec({
|
||||||
`SELECT DISTINCT key FROM pair JOIN bin ON pair.binid=bin.id JOIN os ON bin.osid=os.id WHERE os.build=?`,
|
sql: `SELECT DISTINCT key FROM pair JOIN bin ON pair.binid=bin.id JOIN os ON bin.osid=os.id WHERE os.build=?`,
|
||||||
[build]
|
bind: [build],
|
||||||
);
|
rowMode: "array",
|
||||||
if (!results.length) return [];
|
returnValue: "resultRows",
|
||||||
return results[0].rows.map((row) => row[0] as string);
|
});
|
||||||
|
return rows.map((row) => row[0] as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPathsForKey(build: string, key: string): Promise<string[]> {
|
async getPathsForKey(build: string, key: string): Promise<string[]> {
|
||||||
const db = await getDB();
|
const db = await getDB();
|
||||||
const results = db.exec(
|
const rows = db.exec({
|
||||||
`SELECT path FROM bin JOIN pair ON bin.id=pair.binid JOIN os ON bin.osid=os.id WHERE os.build=? AND pair.key=?`,
|
sql: `SELECT path FROM bin JOIN pair ON bin.id=pair.binid JOIN os ON bin.osid=os.id WHERE os.build=? AND pair.key=?`,
|
||||||
[build, key]
|
bind: [build, key],
|
||||||
);
|
rowMode: "array",
|
||||||
if (!results.length) return [];
|
returnValue: "resultRows",
|
||||||
return results[0].rows.map((row) => row[0] as string);
|
});
|
||||||
|
return rows.map((row) => row[0] as string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user