@eqtylab/explorer

中文文档
0.22.0发布于 2026/11/14Apache-2.0TypeScriptES Module近 30 天下载 2998

EQTYLab Explorer (commit: 0a51443)

原始使用文档
文档目录19 节
  1. Changelog
  2. Features
  3. Embedding
  4. The default: a custom element
  5. React
  6. Supplying a manifest
  7. Configuration
  8. Styling
  9. Demos
  10. Prerequisites
  11. Local Development
  12. Available Commands
  13. Repository Layout
  14. Build Outputs
  15. Release
  16. How to Release
  17. Version Management
  18. App configuration
  19. Adding Example Manifests

EQTYLab Explorer

A visualization tool for exploring data lineage and computational integrity. Part of the EQTYlab ecosystem, it displays data provenance chains showing how data flows through computational systems, which actors are involved, and what verification statements are attached.

It ships both as the hosted app at explorer.eqtylab.io and as an embeddable library that renders a manifest inside any page — React or not.

Changelog

See CHANGELOG.md for release changes and CONTRIBUTING.md for PR and release instructions.

Features

  • Interactive Graph Visualization: Drag-to-explore canvas with zoom/pan controls using ReactFlow
  • Detailed Inspector: Sidebar showing registration, governance, storage, and signature details for selected nodes
  • Embeddable: Drop into any page with one script tag as <eqty-explorer>, isolated in a shadow root so neither page can restyle the other
  • Dual Operating Modes:
    • Manifest Viewer: Upload or select sample manifest JSON files to explore
    • Integrity Service: Query a backend integrity service for manifests

Embedding

The explorer is designed to be dropped into a page it doesn't control. Use the <eqty-explorer> custom element unless you have a specific reason not to, it's clean and simple.

The default: a custom element

<script type="module" src="https://cdn.jsdelivr.net/npm/@eqtylab/explorer/dist/standalone/explorer.js"></script>

<eqty-explorer manifest-url="/my-manifest.json" theme="auto" style="height: 600px"></eqty-explorer>

Alternatively, you can import the custom element from npm instead of the CDN:

import { defineExplorerElement } from "@eqtylab/explorer";

defineExplorerElement();

React

A React app — use the component, so the explorer composes with your tree, context and error boundaries:

npm install @eqtylab/explorer react react-dom
import { Explorer } from "@eqtylab/explorer";
import "@eqtylab/explorer/style.css"; // required — only the CDN build self-injects

<Explorer manifest={manifestJson} theme="auto" />;

Your build needs an es2022 target. Signature verification loads WebAssembly behind a top-level await, which Vite's default target rejects outright — esbuild fails with "Top-level await is not available in the configured target environment". In Vite that is build: { target: "es2022" }; other bundlers want their own equivalent.

Supplying a manifest

Pass a parsed object or a JSON string as manifest, or a URL as manifestUrl; manifest wins when both are set. These props are the only way to say what the explorer shows: it has no upload or clear controls of its own, so to let users open their own files, read them in your page and pass the result as manifest. Setting neither shows an empty graph.

Configuration

OptionReact<eqty-explorer>DefaultNotes
manifestmanifest={obj}attribute, property, or a child <script type="application/json">—Parsed object or JSON string
manifestUrl✓manifest-url—Fetched on mount, and again if it changes
view✓viewlineagelineage, table or text; initial only
theme✓themeautolight, dark, or follow the host's prefers-color-scheme
cssVars✓property only—Token overrides, e.g. { "--brand-lineage-explorer": "#0af" }
nodeOverrides✓property only—Per-asset-type node appearance
customIcons✓property only—Icon overrides keyed by asset type
groupNodeThreshold✓group-node-threshold, or property5How many sibling nodes collapse into a group
selectedNodeId✓selected-node-id, or property—Select a node by id; re-applied whenever it changes
selectedStatementId✓selected-statement-id, or property—Show a statement in the text view, switching to it
selectedBlobCid✓selected-blob-cid, or property—Show a blob in the text view; a statement wins if both are set
query✓query, or property—Filter every view; re-applied whenever it changes
onManifestChange✓manifestchange event—Detail is Manifest | null
onNodeSelect✓nodeselect event—Detail is the node id, or null when the selection clears
onStatementSelect✓statementselect event—Detail is the statement key, or null when none is shown
onBlobSelect✓blobselect event—Detail is the blob CID, or null when none is shown
onQueryChange✓querychange event—Detail is the applied query string, "" when cleared
onError✓error eventlogged either wayUnparseable JSON, failed fetches
portalContainer✓set for youshared containerOnly needed if you render overlays somewhere unusual
config, vCompData✓——React only — supply a prebuilt config or already-parsed vComp state

Attributes are live — changing one re-renders.

Options whose values are objects have no attribute form, since an attribute can only carry a string. Set those as properties, before or after the element enters the document:

const el = document.querySelector("eqty-explorer");
el.manifest = parsedObject;
el.customIcons = { dataset: "/icons/dataset.svg" };
el.cssVars = { "--brand-lineage-explorer": "#0af" };

el.addEventListener("nodeselect", (e) => console.log(e.detail)); // string | null
el.addEventListener("statementselect", (e) => console.log(e.detail)); // string | null
el.addEventListener("blobselect", (e) => console.log(e.detail)); // string | null
el.addEventListener("querychange", (e) => console.log(e.detail)); // string
el.addEventListener("manifestchange", (e) => console.log(e.detail)); // Manifest | null
el.addEventListener("error", (e) => console.error(e.detail)); // Error

The container needs a height. The explorer fills whatever it's given; a container with no height renders nothing, and warns about it in the console.

Styling

Hosts and future agent harnesses can check a query before applying it with the exported checkQuery(index, query) API, using an index from buildQueryIndex(nodes, edges, { statements, blobs, anchors }), which reads each node's metadata, credentials and actors from the manifest's statements. It returns { valid, ready, errors, warnings }, where diagnostics have code and message. This check does not match nodes, traverse lineage, update the query, or alter the display. Apply the query through the query prop or attribute only after valid is true. ready additionally excludes bare text, which the UI waits to apply until Enter; an empty query is valid and ready. Values absent from the current manifest produce warnings rather than invalidating a query; these warnings also delay automatic application while a value is still being typed. Closed enums such as has: reject unknown values. The check validates against the same field definitions and compilation logic used by evaluation, without evaluating matches.

Canonical query fields follow manifest names: registeredBy, assetType, metadata.<path>, and associationType. The earlier by, type, meta, assoc, and association spellings remain aliases. Actor choices insert DIDs and display names; actor names can also be queried directly. Adjacent terms mean AND, and precedence is NOT, then AND, then OR. Parentheses override precedence. Numeric comparisons and numeric ranges are supported on metadata; timestamp is text, with inclusive after / before date filters for chronological queries. mentions: (or ref:) takes an id, its start, or a name, and matches what the statements about a node name besides it: an input, a governing document, a storage location, an operator. Bare words search names, types, actor names, metadata and text; identifiers match a bare word from their start.

In the text view the same query filters statements, reading each field one of two ways. Most read what the statement is about (a data or computation node, a DID or an entity, followed through credentials and metadata) as the lineage view reads that node: name, assetType, is, has, metadata.<path>, associationType, the lineage fields and bare words. So assetType:Model lists the model's registration, metadata, the credentials signing them, its storage and governance: the statements behind the nodes the lineage view would show. The rest read the statement itself: statement: (its own type: data, metadata, credential, did, actordid, entity, …; an unknown type only warns), registeredBy, operatedBy, executedOn, timestamp, after, before and mentions. These can differ from the lineage view's answer: registeredBy:alice lists what Alice registered, including metadata she added to a node someone else registered, and statement:metadata lists metadata registrations rather than the nodes they describe. The Blobs tab lists the blobs the query matches, each answering as the statement it belongs to (a data or metadata blob as its registration) or, when it belongs to none, by its CID, name and path, with a listed collection's files. A blob is not listed for being referenced by a matching statement: is:computation lists a computation's metadata blob, not the data it takes in. checkQuery with an index from buildQueryIndex validates the lineage and table meaning.

Fonts aren't bundled. --font-sans resolves to TWK Lausanne/Inter and --font-mono to IBM Plex Mono. Serve those yourself or the explorer falls back to system fonts.

To restyle on purpose, use cssVars rather than a stylesheet. Token overrides work through either entry point, because custom properties cross a shadow boundary where selectors can't.

Demos

pnpm build
pnpm demo   # then open http://localhost:4173/demo/embed.html

demo/embed.html is a deliberately hostile host page — it redefines the same CSS custom property names the explorer uses, styles main/ul/img directly, and defines its own .flex class. Four explorers on it cover all four manifest sources, the object-valued properties and two themes, every one in a shadow root. demo/react/ covers the light-DOM path, which is the React component's. demo/react/ covers the npm path and the peer-dependency split.

Prerequisites

This project uses Nix for development environment management. Install Nix, then the devshell will provide all required dependencies.

Alternatively, ensure you have installed:

  • Node.js
  • pnpm

Local Development

# Enter the Nix development shell (if using Nix)
nix develop

# Install dependencies
pnpm install

# Start development server
pnpm dev

Available Commands

CommandDescription
pnpm devStart the site's dev server, on the explorer's source
pnpm buildBuild all three targets and verify CSS scoping
pnpm build:libBuild the npm package
pnpm build:standaloneBuild the CDN bundle
pnpm build:siteBuild the hosted site (needs pnpm build:lib first)
pnpm check:cssVerify the built stylesheets can't escape their scope
pnpm demoServe the repo so demo/embed.html can be opened
pnpm fmtFormat code with Prettier
pnpm format:checkCheck code formatting
pnpm lintRun ESLint
pnpm lint:fixRun ESLint with auto-fix
pnpm typecheckRun TypeScript type checking

Repository Layout

The repository root is the @eqtylab/explorer package. The hosted site lives in site/, a private pnpm workspace member that depends on the package through workspace:* and imports only its public entry points (eslint enforces this), like any other consumer. The site owns its own chrome, the manifest upload UI and the sample manifests in site/public/manifests, which the package's tests also read as fixtures.

Build Outputs

The project builds three things.

  1. npm package (dist/lib/) — published as @eqtylab/explorer. ESM only, with React as a peer dependency. The stylesheet ships alongside it as @eqtylab/explorer/style.css.
  2. CDN bundle (dist/standalone/) — React and every dependency in one file, loaded by a single <script type="module">. It injects its own styles. The signature-verification WebAssembly stays a separate file and loads on first use.
  3. Hosted site (site/dist/) — the site at explorer.eqtylab.io. Its production build resolves @eqtylab/explorer to dist/lib and its scoped stylesheet, so the deployed site runs exactly what npm consumers get. It deploys only on release, like the package.

pnpm dev instead compiles the explorer from src/ for hot reload (see vite/explorer-source.ts), which leaves two things it does not cover.

  • Scoped CSS. scope-css runs at bundle time, so in dev the explorer's stylesheet is unscoped. Scoping mistakes appear only in a real build, so CI runs pnpm check:css, and pnpm build && pnpm preview serves the site against the built package.
  • The custom element. The site renders <Explorer>, so the dev server never creates an <eqty-explorer>. The shadow root, the adopted stylesheet and the per-instance portal container are covered by demo/embed.html, which runs against a built bundle.

Release

Releases are automated via GitHub Actions and triggered by bumping the version in package.json on main.

How to Release

  1. Prepare the stable release section in CHANGELOG.md, following the release instructions.
  2. Bump version in package.json in the same PR and run ./scripts/check-changelog.sh vX.Y.Z with the intended version.
  3. Open a PR and merge it to main

When the change lands on main, the Release workflow will automatically:

  • Check that stable versions have a matching changelog heading
  • Tag the commit as v<version> and create a GitHub Release with generated notes
  • Call the Publish workflow to build and publish to npm

A version containing a hyphen (e.g. 0.11.0-rc1) is marked as a GitHub pre-release. Note that npm still publishes it under the latest dist-tag.

Version Management

package.json is the single source of truth for the version. If the tag v<version> already exists, the release workflow does nothing.

The Publish workflow checks the effective version against the changelog before building, including dry runs. Candidate and unofficial tags skip this check.

Publishing can also be triggered manually:

  • Publish via Run workflow builds and packs without publishing (--dry-run by default; uncheck to publish the version currently in package.json)
  • Creating a GitHub Release by hand still publishes the version from its tag

App configuration

See the configuration documentation for customization options.

Adding Example Manifests

  1. Add the manifest JSON file to ./site/public/manifests
  2. Update the manifests section in ./site/src/config.json
    • The name must match the filename without the extension

版本与发布记录

@eqtylab/explorer 共发布 32 个版本,首次发布于 2026/01/28;过去 12 个月发布了 32 个版本。

版本发布日期距今
0.22.0latest2026/11/14今天
0.21.02026/11/113 天前
0.20.12026/11/0311 天前
0.20.02026/11/0211 天前
0.19.02026/10/1629 天前
0.18.02026/10/131 个月前

其他发布通道:vllm-demo → 0.11.0-vllm-demo.0。

关于 @eqtylab/explorer 的常见问题

@eqtylab/explorer 是什么?

EQTYLab Explorer (commit: 0a51443)

如何安装 @eqtylab/explorer?

在项目目录运行 npm install @eqtylab/explorer,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^18.2.0 || ^19.0.0)、react-dom(^18.2.0 || ^19.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@eqtylab/explorer 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@eqtylab/explorer 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@eqtylab/explorer 可以商用吗?

@eqtylab/explorer 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@eqtylab/explorer 的下载量有多少?

根据 npm 官方下载统计,@eqtylab/explorer 在 2026/10/14 – 2026/11/12 这 30 天内被下载 2,998 次,日均约 100 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@eqtylab/explorer 还在维护吗?

最新版本 0.22.0 发布于 2026/11/14(今天);至今共发布 32 个版本,其中过去 12 个月发布了 32 个;首次发布于 2026/01/28。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。