Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
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
35 changes: 12 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,29 @@ 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.
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 +66,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
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ npm install
## 2. Install enskit and enssdk

```sh
npm install enskit@1.15.0 enssdk@1.15.0
npm install enskit@1.15.1 enssdk@1.15.1
```

<Aside type="caution" title="Pin exact versions">
Expand Down Expand Up @@ -151,6 +151,10 @@ export function DomainView() {
}
```

<Aside type="note" title="BeautifiedName">
`beautified` is the display-ready form of the Canonical Name — its normalized labels rendered per [ENSIP-15](https://docs.ens.domains/ensip/15) (e.g. `♾.eth` → `♾️.eth`) — so you can render it directly with no normalization or emoji logic of your own. It's **display-only**: use `interpreted` (or the Domain `id`) as a lookup key or navigation target, never `beautified`. See [Beautified Name](/docs/reference/terminology#beautified-name).
</Aside>

A few things to notice:

- `graphql(...)` parses your query at typecheck time. Hover over `result.data` and you'll see it's typed exactly to your selection set — try removing `owner { address }` from the query and watch the access below become a type error.
Expand Down
Loading
Loading