export class CompilerResource {
#inner;
#getWasm;
#client;
constructor(inner, getWasm, client = null) {
this.#inner = inner;
this.#getWasm = getWasm;
this.#client = client;
}
async component({
code,
namespace,
slots = [],
supportAllTypes = true,
libraries = [],
}) {
this.#client?.assertNotTerminated();
const wasm = await this.#getWasm();
const builder = await this.#inner.createCodeBuilder();
libraries.forEach((lib, i) => {
assertLibrarySource(lib, i, "compile.component");
builder.linkModule(lib.namespace, lib.code);
});
const compiled = namespace
? builder.compileAccountComponentCodeWithPath(namespace, code)
: builder.compileAccountComponentCode(code);
const component = wasm.AccountComponent.compile(compiled, slots);
return supportAllTypes ? component.withSupportsAllTypes() : component;
}
async txScript({ code, libraries = [] }) {
this.#client?.assertNotTerminated();
await this.#getWasm();
const builder = await this.#inner.createCodeBuilder();
linkLibraries(builder, libraries, "compile.txScript");
return builder.compileTxScript(code);
}
async noteScript({ code, libraries = [] }) {
this.#client?.assertNotTerminated();
await this.#getWasm();
const builder = await this.#inner.createCodeBuilder();
linkLibraries(builder, libraries, "compile.noteScript");
return builder.compileNoteScript(code);
}
}
function assertLibrarySource(lib, i, caller) {
if (typeof lib?.namespace !== "string" || typeof lib?.code !== "string") {
throw new TypeError(
`${caller}: libraries[${i}] must be { namespace: string, code: string }`
);
}
}
function linkLibraries(builder, libraries, caller) {
for (const [i, lib] of libraries.entries()) {
if (
lib == null ||
typeof lib !== "object" ||
(!lib.component && ("namespace" in lib || "code" in lib))
) {
assertLibrarySource(lib, i, caller);
}
if (lib && lib.component) {
const componentCode = lib.component.componentCode();
if (lib.linking === "static") {
builder.linkStaticAccountComponentCode(componentCode);
} else {
builder.linkDynamicAccountComponentCode(componentCode);
}
} else if (typeof lib.namespace === "string") {
const built = builder.buildLibrary(lib.namespace, lib.code);
if (lib.linking === "static") {
builder.linkStaticLibrary(built);
} else {
builder.linkDynamicLibrary(built);
}
} else {
builder.linkDynamicLibrary(lib);
}
}
}