2025-01-12 14:41:58 +00:00
|
|
|
import { createWorker, loadFile } from "./platform.js";
|
|
|
|
|
|
|
|
|
|
const DEFAULT_OPTIONS = {
|
|
|
|
|
layout: "dagre",
|
|
|
|
|
sketch: false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export class D2 {
|
|
|
|
|
constructor() {
|
|
|
|
|
this.ready = this.init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setupMessageHandler() {
|
|
|
|
|
const isNode = typeof window === "undefined";
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
if (isNode) {
|
|
|
|
|
this.worker.on("message", (data) => {
|
|
|
|
|
if (data.type === "ready") resolve();
|
|
|
|
|
if (data.type === "error") reject(new Error(data.error));
|
|
|
|
|
if (data.type === "result" && this.currentResolve) {
|
|
|
|
|
this.currentResolve(data.data);
|
|
|
|
|
}
|
|
|
|
|
if (data.type === "error" && this.currentReject) {
|
|
|
|
|
this.currentReject(new Error(data.error));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.worker.onmessage = (e) => {
|
|
|
|
|
if (e.data.type === "ready") resolve();
|
|
|
|
|
if (e.data.type === "error") reject(new Error(e.data.error));
|
|
|
|
|
if (e.data.type === "result" && this.currentResolve) {
|
|
|
|
|
this.currentResolve(e.data.data);
|
|
|
|
|
}
|
|
|
|
|
if (e.data.type === "error" && this.currentReject) {
|
|
|
|
|
this.currentReject(new Error(e.data.error));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async init() {
|
|
|
|
|
this.worker = await createWorker();
|
|
|
|
|
|
|
|
|
|
const wasmExecContent = await loadFile("./wasm_exec.js");
|
|
|
|
|
const wasmBinary = await loadFile("./d2.wasm");
|
|
|
|
|
|
|
|
|
|
const isNode = typeof window === "undefined";
|
|
|
|
|
const messageHandler = this.setupMessageHandler();
|
|
|
|
|
|
|
|
|
|
if (isNode) {
|
|
|
|
|
this.worker.on("error", (error) => {
|
2025-01-12 19:08:17 +00:00
|
|
|
console.error("Worker (node) encountered an error:", error.message || error);
|
2025-01-12 14:41:58 +00:00
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.worker.onerror = (error) => {
|
|
|
|
|
console.error("Worker encountered an error:", error.message || error);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.worker.postMessage({
|
|
|
|
|
type: "init",
|
|
|
|
|
data: {
|
|
|
|
|
wasm: wasmBinary,
|
|
|
|
|
wasmExecContent: isNode ? wasmExecContent.toString() : null,
|
|
|
|
|
wasmExecUrl: isNode
|
|
|
|
|
? null
|
|
|
|
|
: URL.createObjectURL(
|
|
|
|
|
new Blob([wasmExecContent], { type: "application/javascript" })
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return messageHandler;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async sendMessage(type, data) {
|
|
|
|
|
await this.ready;
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
this.currentResolve = resolve;
|
|
|
|
|
this.currentReject = reject;
|
|
|
|
|
this.worker.postMessage({ type, data });
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async compile(input, options = {}) {
|
|
|
|
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
|
|
|
const request =
|
|
|
|
|
typeof input === "string"
|
|
|
|
|
? { fs: { index: input }, options: opts }
|
|
|
|
|
: { ...input, options: { ...opts, ...input.options } };
|
|
|
|
|
return this.sendMessage("compile", request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async render(diagram, options = {}) {
|
|
|
|
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
|
|
|
return this.sendMessage("render", { diagram, options: opts });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async encode(script) {
|
|
|
|
|
return this.sendMessage("encode", script);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async decode(encoded) {
|
|
|
|
|
return this.sendMessage("decode", encoded);
|
|
|
|
|
}
|
|
|
|
|
}
|