chore: make some things a bit more typesafe

This commit is contained in:
Max Richter
2025-11-23 15:15:38 +01:00
parent 2dcd797762
commit 64ea7ac349
4 changed files with 252 additions and 162 deletions

View File

@@ -1,19 +1,24 @@
import { NodeDefinitionSchema, type AsyncCache, type NodeDefinition, type NodeRegistry } from "@nodes/types";
import {
NodeDefinitionSchema,
type AsyncCache,
type NodeDefinition,
type NodeRegistry,
} from "@nodes/types";
import { createLogger, createWasmWrapper } from "@nodes/utils";
const log = createLogger("node-registry");
log.mute();
export class RemoteNodeRegistry implements NodeRegistry {
status: "loading" | "ready" | "error" = "loading";
private nodes: Map<string, NodeDefinition> = new Map();
cache?: AsyncCache<ArrayBuffer>;
fetch: typeof fetch = globalThis.fetch.bind(globalThis);
constructor(private url: string, private cache?: AsyncCache<ArrayBuffer>) { }
constructor(
private url: string,
private cache?: AsyncCache<ArrayBuffer>,
) {}
async fetchUsers() {
const response = await this.fetch(`${this.url}/nodes/users.json`);
@@ -32,7 +37,9 @@ export class RemoteNodeRegistry implements NodeRegistry {
}
async fetchCollection(userCollectionId: `${string}/${string}`) {
const response = await this.fetch(`${this.url}/nodes/${userCollectionId}.json`);
const response = await this.fetch(
`${this.url}/nodes/${userCollectionId}.json`,
);
if (!response.ok) {
throw new Error(`Failed to load collection ${userCollectionId}`);
}
@@ -44,20 +51,16 @@ export class RemoteNodeRegistry implements NodeRegistry {
if (!response.ok) {
throw new Error(`Failed to load node definition ${nodeId}`);
}
return response.json()
return response.json();
}
private async fetchNodeWasm(nodeId: `${string}/${string}/${string}`) {
const fetchNode = async () => {
const response = await this.fetch(`${this.url}/nodes/${nodeId}.wasm`);
return response.arrayBuffer();
}
};
const res = await Promise.race([
fetchNode(),
this.cache?.get(nodeId)
]);
const res = await Promise.race([fetchNode(), this.cache?.get(nodeId)]);
if (!res) {
throw new Error(`Failed to load node wasm ${nodeId}`);
@@ -69,18 +72,17 @@ export class RemoteNodeRegistry implements NodeRegistry {
async load(nodeIds: `${string}/${string}/${string}`[]) {
const a = performance.now();
const nodes = await Promise.all([...new Set(nodeIds).values()].map(async id => {
const nodes = await Promise.all(
[...new Set(nodeIds).values()].map(async (id) => {
if (this.nodes.has(id)) {
return this.nodes.get(id)!;
}
if (this.nodes.has(id)) {
return this.nodes.get(id)!;
}
const wasmBuffer = await this.fetchNodeWasm(id);
return this.register(wasmBuffer);
}));
const wasmBuffer = await this.fetchNodeWasm(id);
return this.register(wasmBuffer);
}),
);
const duration = performance.now() - a;
@@ -90,11 +92,10 @@ export class RemoteNodeRegistry implements NodeRegistry {
log.groupEnd();
this.status = "ready";
return nodes
return nodes;
}
async register(wasmBuffer: ArrayBuffer) {
const wrapper = createWasmWrapper(wasmBuffer);
const definition = NodeDefinitionSchema.safeParse(wrapper.get_definition());
@@ -110,8 +111,8 @@ export class RemoteNodeRegistry implements NodeRegistry {
let node = {
...definition.data,
execute: wrapper.execute
}
execute: wrapper.execute,
};
this.nodes.set(definition.data.id, node);