Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,44 +27,6 @@ The easiest way to get started is through the new **ENS Omnigraph API** — the
- 🚀 **Quickstart:** [ensnode.io/docs/integrate](https://ensnode.io/docs/integrate)
- 💬 **Telegram:** [t.me/ensnode](https://t.me/ensnode)

## Example: query the subnames of '.eth' via the ENS Omnigraph API

Note that substantial ENS data is not directly queryable through traditional smart contract RPC calls. Examples include: the subnames of a name, or the names owned by an address. ENSNode is the world's first and only solution that makes the full set of ENS data spanning both ENSv1 and ENSv2 accessible through a single unified API.

```graphql
query HelloWorld {
domain(by: { name: "eth" }) {
__typename
canonical {
name {
interpreted
}
}
owner {
address
}
subdomains(first: 20) {
totalCount
edges {
node {
__typename
canonical {
name {
interpreted
}
}
owner {
address
}
}
}
}
}
}
```

To get started with ENSNode and the ENS Omnigraph API, follow the [Quickstart](https://ensnode.io/docs/integrate).

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export const integrateSidebarTopic = {
link: "/docs/integrate/integration-options/ensdb-cli",
},
{
label: "ENSEngine (webhooks)",
label: "ENSEngine (Webhooks)",
link: "/docs/integrate/integration-options/ensengine",
},
],
Expand Down
25 changes: 7 additions & 18 deletions docs/ensnode.io/scripts/fetch-omnigraph-example-responses.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

import { ACTIVE_OMNIGRAPH_VERSION } from "../src/data/omnigraph-examples/active.ts";
import { OMNIGRAPH_EXAMPLES_META } from "../src/data/omnigraph-examples/meta.ts";
import type { SnapshotExample } from "../src/data/omnigraph-examples/types.ts";
import { ENSNODE_URL } from "../src/lib/examples/omnigraph/constants.ts";
Expand All @@ -15,30 +14,20 @@ function logError(message: string, id?: string) {
console.error(`[omnigraph-examples] ERROR: ${message} ${id ? `for example '${id}'` : ""}`);
}

// Target version defaults to the active one; override to fill responses for a staged version.
const version = process.env.OMNIGRAPH_VERSION ?? ACTIVE_OMNIGRAPH_VERSION;
// Used as a directory name; reject anything that could escape the versions/ dir.
if (!/^[0-9A-Za-z._-]+$/.test(version) || version.includes("..")) {
logError(`Invalid version "${version}": use only letters, digits, '.', '_', '-'.`);
process.exit(1);
}
const versionDir = join(
dirname(fileURLToPath(import.meta.url)),
`../src/data/omnigraph-examples/versions/${version}`,
);
const examplesPath = join(versionDir, "examples.json");
const outputPath = join(versionDir, "responses.json");
const dataDir = join(dirname(fileURLToPath(import.meta.url)), "../src/data/omnigraph-examples");
const examplesPath = join(dataDir, "examples.json");
const outputPath = join(dataDir, "responses.json");

if (!existsSync(examplesPath)) {
logError(`No examples snapshot at ${examplesPath}. Snapshot version "${version}" first.`);
logError(`No examples snapshot at ${examplesPath}. Run pnpm omnigraph:snapshot <version> first.`);
process.exit(1);
}

const snapshotById = new Map(
(JSON.parse(readFileSync(examplesPath, "utf8")) as SnapshotExample[]).map((e) => [e.id, e]),
);

// Only fetch responses for the rendered set: meta entries supported by this version's snapshot.
// Only fetch responses for the rendered set: meta entries supported by the vendored snapshot.
const allExampleIds = (Object.keys(OMNIGRAPH_EXAMPLES_META) as string[])
.filter((id) => snapshotById.has(id))
.sort();
Expand Down Expand Up @@ -66,8 +55,8 @@ const url = new URL("/api/omnigraph", process.env.OMNIGRAPH_ENDPOINT ?? ENSNODE_

logStep(
argIds.length > 0
? `Refreshing ${exampleIds.length} of ${allExampleIds.length} examples (${version}) from ${url}: ${exampleIds.join(", ")}`
: `Fetching all ${exampleIds.length} Omnigraph examples (${version}) from ${url}`,
? `Refreshing ${exampleIds.length} of ${allExampleIds.length} examples from ${url}: ${exampleIds.join(", ")}`
: `Fetching all ${exampleIds.length} Omnigraph examples from ${url}`,
);

// When refreshing a subset, load the existing responses so unaffected entries are preserved.
Expand Down
36 changes: 13 additions & 23 deletions docs/ensnode.io/scripts/snapshot-omnigraph-version.mts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { execSync } from "node:child_process";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { readFileSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

Expand All @@ -11,35 +11,30 @@ import { GRAPHQL_API_EXAMPLE_QUERIES } from "@ensnode/ensnode-sdk/internal";
import type { SnapshotExample } from "../src/data/omnigraph-examples/types.ts";
import { DOCS_OMNIGRAPH_NAMESPACE, ENSNODE_URL } from "../src/lib/examples/omnigraph/constants.ts";

// Freeze the CURRENT workspace SDK omnigraph bundle (examples + schema) into a version
// snapshot. Run this on the release commit of <version>, where the SDK's example set is
// — by construction — valid against that release's schema. Responses are filled separately
// Freeze the CURRENT workspace SDK omnigraph bundle (examples + schema) into the single
// vendored snapshot the docs render. Run this on the release commit of <version>, where the
// SDK's example set is — by construction — valid against that release's schema. <version> is
// recorded in snapshot.json for provenance. Responses are filled separately
// (`pnpm omnigraph-examples:refresh-responses`) once the version is live in production.
// Overwrites the existing snapshot; new-version work happens on a separate branch.
//
// Usage: pnpm omnigraph:snapshot <version> e.g. pnpm omnigraph:snapshot v1.14.0
// Usage: pnpm omnigraph:snapshot <version> e.g. pnpm omnigraph:snapshot v1.16.0

const version = process.argv[2];
if (!version) {
console.error("Usage: pnpm omnigraph:snapshot <version>");
process.exit(1);
}
// Used as a directory name; reject anything that could escape the versions/ dir.
// Sanity-check the CLI argument; <version> is only written to snapshot.json, not used as a path.
if (!/^[0-9A-Za-z._-]+$/.test(version) || version.includes("..")) {
console.error(`Invalid version "${version}": use only letters, digits, '.', '_', '-'.`);
process.exit(1);
}
Comment thread
shrugs marked this conversation as resolved.

const here = dirname(fileURLToPath(import.meta.url));
const versionDir = join(here, `../src/data/omnigraph-examples/versions/${version}`);
const dataDir = join(here, "../src/data/omnigraph-examples");
const sdkSchemaPath = join(here, "../../../packages/enssdk/src/omnigraph/generated/schema.graphql");

if (existsSync(versionDir)) {
console.error(
`Snapshot already exists: ${versionDir}. Snapshots are immutable; delete it first to re-cut.`,
);
process.exit(1);
}

const sdl = readFileSync(sdkSchemaPath, "utf8");
const schema = buildSchema(sdl);

Expand Down Expand Up @@ -72,20 +67,15 @@ try {
// not in a git checkout; leave "unknown"
}

mkdirSync(versionDir, { recursive: true });
writeFileSync(join(versionDir, "schema.graphql"), sdl, "utf8");
writeFileSync(join(versionDir, "examples.json"), `${JSON.stringify(examples, null, 2)}\n`, "utf8");
writeFileSync(join(dataDir, "schema.graphql"), sdl, "utf8");
writeFileSync(join(dataDir, "examples.json"), `${JSON.stringify(examples, null, 2)}\n`, "utf8");
writeFileSync(
join(versionDir, "snapshot.json"),
join(dataDir, "snapshot.json"),
`${JSON.stringify({ version, commit, sdkVersion, schemaTag: version, endpoint: ENSNODE_URL, snapshottedAt: new Date().toISOString().slice(0, 10) }, null, 2)}\n`,
"utf8",
);

console.log(`Snapshotted ${examples.length} examples + schema for ${version} (commit ${commit}).`);
console.log("Next:");
console.log(
` 1. OMNIGRAPH_VERSION=${version} pnpm omnigraph-examples:refresh-responses # once ${version} is live`,
);
console.log(
` 2. set ACTIVE_OMNIGRAPH_VERSION = "${version}" in src/data/omnigraph-examples/active.ts`,
`Next: pnpm omnigraph-examples:refresh-responses # once ${version} is live in production`,
);
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
import ENSAdminCTAButton from "@components/atoms/ENSAdminCTAButton.astro";
import { ACTIVE_OMNIGRAPH_VERSION } from "@data/omnigraph-examples/active";
import snapshot from "@data/omnigraph-examples/snapshot.json";

const { instanceURL, connectWithENSAdminURL, namespace, ensVersions, plugins } = Astro.props;
const hostedEnsNodeVersion = ACTIVE_OMNIGRAPH_VERSION;
const hostedEnsNodeVersion = snapshot.version;
---

<table style={{ marginTop: "0" }}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
import { Aside } from "@astrojs/starlight/components";

import { ACTIVE_OMNIGRAPH_VERSION } from "@data/omnigraph-examples/active";
import snapshot from "@data/omnigraph-examples/snapshot.json";

// The SDK version is locked to the production-deployed Omnigraph version (see
// `@data/omnigraph-examples/active`). The SDK bundles the Omnigraph schema, so pinning the matching
// version keeps gql.tada's generated types aligned with the deployed API. Updates on promotion.
const VERSION = ACTIVE_OMNIGRAPH_VERSION.replace(/^v/, "");
// The SDK version is locked to the production-deployed Omnigraph version (see the vendored
// `@data/omnigraph-examples/snapshot.json`). The SDK bundles the Omnigraph schema, so pinning the
// matching version keeps gql.tada's generated types aligned with the deployed API.
const VERSION = snapshot.sdkVersion;
---

<Aside type="caution" title="Version compatibility with hosted instances">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,7 @@
import { buildSchema } from "graphql";
import { ACTIVE_OMNIGRAPH_VERSION } from "@data/omnigraph-examples/active";
import omnigraphSchemaSdl from "@data/omnigraph-examples/schema.graphql?raw";
import GraphQLSchemaDocExplorer from "./GraphQLSchemaDocExplorer.tsx";

// select the active omnigraph schema for rendering
const schemasByVersion = import.meta.glob<string>(
"../../data/omnigraph-examples/versions/*/schema.graphql",
{ query: "?raw", import: "default", eager: true },
);

const omnigraphSchemaSdl =
schemasByVersion[
`../../data/omnigraph-examples/versions/${ACTIVE_OMNIGRAPH_VERSION}/schema.graphql`
];

if (!omnigraphSchemaSdl) {
throw new Error(`No Omnigraph schema snapshot for version "${ACTIVE_OMNIGRAPH_VERSION}".`);
}

const omnigraphSchema = buildSchema(omnigraphSchemaSdl);

export default function OmnigraphSchemaDocExplorer() {
Expand Down
Loading
Loading