WebAssembly

Nexyron compiles to WebAssembly and runs inside a browser tab. The data stays in the page: nothing is sent to a server, because there is no server in the path.

What this is for

Analysis that must not leave the device. A file the user opens locally, queried in the browser, with results never transmitted anywhere.

Interactive exploration of a bounded dataset. An embedded explorer over a dataset that ships with the page.

Demonstrations and teaching. A working query environment with nothing to install.

What it is not for

The browser is a constrained environment: memory is limited, and the whole dataset lives in the tab. This is not the way to query a large shared business model. For that, run the server and query it over HTTP, which keeps the data in one place and the browser thin.

Getting started

import init, { Database } from '@nexyron/wasm';

await init();

const db = await Database.create();
await db.query(`
  CREATE (a:Customer {name: 'Nora Ellingsen'}),
         (s:Site {name: 'Bergen'}),
         (a)-[:BELONGS_TO]->(s)
`);

const rows = await db.query(`
  MATCH (c:Customer)-[:BELONGS_TO]->(s:Site)
  RETURN element_id(c) AS id, c.name AS name, s.name AS site
`);
console.log(rows);

init() fetches and instantiates the module and must finish before anything else. Call it once, at startup.

Identifiers

The identifier rule matters here more than anywhere: this is JavaScript, so always return identifiers as strings with element_id(). A numeric identifier can be silently rounded and will then match nothing, with no error to tell you why. See Node and TypeScript for the full explanation.

Loading data

Read a file the user selected and load it in-page:

const text = await file.text();
await db.query(
  `UNWIND $rows AS row
   CREATE (c:Customer {name: row.name, revenue: row.revenue})`,
  { rows: JSON.parse(text) },
);

Load in batches rather than one row per query. A single UNWIND over a few thousand rows is far faster than a few thousand separate calls.

Keeping the page responsive

Run the database in a web worker for anything beyond trivial queries. WebAssembly executes on the thread that calls it, so a long query on the main thread freezes the interface. A worker keeps the page interactive and costs little to set up.