Skip to content

client: add @hypercerts-org/api with record types from @hypercerts-org/lexicon/records - #45

Merged
kristoferlund merged 10 commits into
mainfrom
kristofer/tech-799-hypercerts-api-typescript-types-for-the-xrpc-queries-as-a
Nov 2, 2026
Merged

kristoferlund merged 10 commits into
mainfrom
kristofer/tech-799-hypercerts-api-typescript-types-for-the-xrpc-queries-as-a

Conversation

@kristoferlund

@kristoferlund kristoferlund commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Adds @hypercerts-org/api as a workspace package in packages/api/: @atproto/lex query definitions and TypeScript types for the API, so apps and the SDK can call it typed instead of generating their own bindings. Implements TECH-799 and TECH-817 of the implementation plan.

Depends on hypercerts-lexicon#270 (@hypercerts-org/lexicon/records, TECH-750). Review the two together. Until #270 is released, this PR builds against a vendored tarball of it; see "Before merging".

import { Client } from "@atproto/lex";
import { app, org } from "@hypercerts-org/api";

const api = new Client("https://api.hypercerts.dev");
const { activity } = await api.call(org.hypercerts.claim.getActivity, { uri });
const { badgeAwards } = await api.call(app.certified.badge.listBadgeAwards, { limit: 50 });

type ActivityView = org.hypercerts.claim.getActivity.ActivityView;
type Activity = org.hypercerts.claim.activity.Main; // the record, shared with @hypercerts-org/lexicon/records

What's in it

  • lex's NSID namespace tree. The package exports app, com, org and pub, as generated by lex build --index-file, the layout the @atproto/lex docs use and the same as @hypercerts-org/lexicon/records. Every name is an NSID: queries at org.hypercerts.claim.getActivity (with .$Params, .ActivityView), shared views at org.hypercerts.api.defs.
  • Records are shared, not copied. Records and other referenced definitions in the tree re-export the lexicon package's modules, so org.hypercerts.claim.activity is the same module in both packages. Records no query returns (such as org.hyperboards.board) are not in this tree; apps import them from @hypercerts-org/lexicon/records. Generation fails if a module it needs is missing from /records.
  • packages/api/scripts/generate.js runs lex build over happyview-modules/manifest.json validationLexicons, keeps the modules of the API's own 65 Lexicons (63 queries, 2 defs) and the namespace modules on the path to them, points everything else at @hypercerts-org/lexicon/records/<nsid path>, puts lex's exports and imports in a fixed order (lex otherwise follows the file system's listing order, and the output is committed and compared), replaces lex's banner with its own, and applies the bluesky-social/atproto#5738 import fix.
  • LEXICON_VERSION (also hypercerts.lexiconVersion in package.json).
  • Peer dependencies: @atproto/lex ^0.4.2 and @hypercerts-org/lexicon ^1.7.0.
  • Generated packages/api/src/ is committed (it is what reviewers see change when an API Lexicon changes); pnpm check runs freshness, Biome, typecheck, build, a type test against the built package and runtime tests (every export of the tree's records is the lexicon package's, and embedded records are validated with its schemas). pnpm check:package follows the SDK's check: it installs the packed tarball in a pnpm project outside the workspace, imports it in Node, typechecks a consumer and bundles one query with Vite. CI runs it.
  • pnpm client:generate at the root regenerates; README, CONTRIBUTING and AGENTS.md say when.
  • Node 24 pinned in .nvmrc; all CI and release jobs read it with node-version-file.

Before merging

  • Release #270 (as @hypercerts-org/lexicon 1.7.0), then replace the vendored packages/api/vendor/hypercerts-org-lexicon-1.7.0.tgz with "@hypercerts-org/lexicon": "1.7.0", delete packages/api/vendor/, regenerate and update the lockfile.
  • The server modules still pin @hypercerts-org/lexicon 1.5.0 in happyview-modules/package.json, so the indexer validates against 1.5.0 while the client types come from 1.7.0. Aligning them is TECH-822.

Decisions to review

  • Folder and package rename (Karma, please confirm or suggest another name). The package named "api" lived in client/, and the folder api/ held a package named @hypercerts-org/hypercerts-api. Now:

    • api/ is happyview-modules/, package @hypercerts-org/happyview-modules. The modules, installer and tests are unchanged; only paths move. The installer runs from happyview-modules/.
    • client/ is packages/api/, like the SDK's packages/sdk/.
    • Release tags from the next release on are @hypercerts-org/happyview-modules@X.Y.Z; earlier releases keep their @hypercerts-org/hypercerts-api@X.Y.Z tags (changeset added, README updated). CI, the release workflow, the explorer sources and the pending changesets follow the new paths.
    • It is one commit (8e080e4), so a different name is a search-and-replace on top of it. The server package cannot keep the name "api" either way, because @hypercerts-org/api is the npm package.
  • Tooling follows the SDK scaffold (TECH-748): Biome 2.6.3 with the same rules, TypeScript 7, the SDK's compiler options, ESM only, Node 24. The rest of this repository keeps ESLint and pnpm 10 for now (TECH-821).

  • exactOptionalPropertyTypes is off for this package: code generated by @atproto/lex 0.4.2 does not compile with it.

  • Not versioned or released yet. The package is in the Changesets ignore list, because the release workflow only tags the server bundle (TECH-818). The server bundle's only changeset is the rename below.

  • Release coupling. The release workflow runs pnpm check and pnpm build, which now include the client package, so a broken packages/api/ blocks releasing the server bundle. Main CI gates the same commands, so this should not bite in practice.

  • Consuming it before npm: from the workspace or a pnpm pack tarball (prepack builds). A git dependency does not work, because dist/ is not committed.

Verification

  • pnpm --filter @hypercerts-org/api check passes; check:generated fails after a manual edit and ignores stray dotfiles.
  • Explorer tests pass; the frozen-lockfile install is clean.
  • A pnpm pack tarball installed with the lexicon tarball in an isolated project: runtime import works, and a TypeScript consumer typechecks api.call(getActivity, …) with ActivityView["record"] assignable to the lexicon package's Activity.
  • Two independent reviews (this PR and #270); their findings are addressed.
  • Not run locally: Luacheck and its unit test (not installed on this machine). CI runs them.

Note

The package is licensed MIT OR Apache-2.0 (packages/api/LICENSE-MIT, packages/api/LICENSE-APACHE, Hypercerts Foundation), following the suggestion for this repository in the licensing proposal (TECH-736); before, the tarball shipped the repository's LICENSE.md, whose copyright line reads "Trezy Studios, LLC". If the team settles on another license, only these two files and the license field change.

RetriggerView in GreptileConfidence Score: 5/5

The reviewed updates appear safe to merge, with the previous installation-example issue fixed.

Summary

Adds @hypercerts-org/api with generated query definitions and shared record types.

  • Apps can call Hypercerts queries with generated types and shared records.
  • The server bundle keeps its work under the happyview-modules name.
  • Workspace checks and release jobs include the client package.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A["happyview-modules/manifest.json"] --> G["scripts/generate.js"]
  L["@hypercerts-org/lexicon"] --> G
  G --> Q["Generated query definitions"]
  Q --> P["@hypercerts-org/api"]
  L --> R["Shared record modules"]
  R --> P
  P --> C["Typed Client.call"]
Loading

Reviews (2) · Last reviewed commit: "docs: cd happyview-modules in install ex..." · Reviewed by Greptile

Generates @atproto/lex query definitions and types for every query
Lexicon in api/manifest.json, plus the record Lexicons they reference
from the pinned @hypercerts-org/lexicon. Generated sources are committed
and checked for freshness in pnpm check. Not versioned or published yet.

TECH-799
@changeset-bot

changeset-bot Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5768b20

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@hypercerts-org/happyview-modules Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
api-endpoints Ready Ready Preview Oct 30, 2026 10:46pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 76959e7c-cf29-48df-ab2d-c2ff52274613
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@socket-security

socket-security Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​types/​node@​24.19.21001008196100
Addedvite@​8.3.5991008296100
Added@​atproto/​lex@​0.4.29810010099100
Added@​biomejs/​biome@​2.6.310010010099100

View full report

The package now generates only the API's own Lexicons and imports the
record schemas and types its views embed from
@hypercerts-org/lexicon/records, which becomes a peer dependency, instead
of shipping a copy. Until that subpath is released (hypercerts-lexicon#270)
the build uses a vendored tarball of it.

Also addresses the review of this PR: a clean build before pnpm pack,
type tests against the built package, a fixed allowlist for view names
defined by more than one Lexicon so a root export cannot vanish silently,
code-unit sorting, a freshness check limited to generated files, matching
the validation error in tests, and corrected docs.

TECH-799, TECH-817
@kristoferlund kristoferlund changed the title client: add @hypercerts-org/api TypeScript query package client: add @hypercerts-org/api with record types from @hypercerts-org/lexicon/records Oct 30, 2026
@hypercerts-org/api now exports app, com, org and pub as generated by
lex build --index-file, matching @hypercerts-org/lexicon/records and the
@atproto/lex docs: api.call(org.hypercerts.claim.getActivity, ...).
Records and other definitions in the tree re-export the lexicon
package's modules, so an app can import everything from this package and
org.hypercerts.claim.activity is the same module in both. This replaces
the flat short names, the PascalCase namespaces and the allowlist for
ambiguous view names.

Adds check:package (pack, install in a clean project, Node and
TypeScript checks) and runs it in CI.

TECH-799, TECH-817
- generate.js puts lex's exports and imports in a fixed order (lex reads
  Lexicon files in file system order, which differs between machines), with
  the same rules as the lexicon repository, and replaces lex's banner with
  its own, since it rewrites the files. check:generated covers all of src/.
- The sharing test compares every export of each record module, not only
  main, so definition-only modules are checked too.
- check:package follows the SDK's shape: pnpm consumer outside the
  workspace, Node, TypeScript and a Vite browser build that must tree-shake
  unused queries. It checks the packed license files. CI runs it on Node 24
  and 26.
- The package is licensed MIT OR Apache-2.0 (LICENSE-MIT, LICENSE-APACHE,
  Hypercerts Foundation) instead of shipping the repository's HappyView
  license, and has a repository field.
- CI: concurrency group; pnpm version read from packageManager.
- @types/node 24.19.2; vendored lexicon tarball rebuilt from #270.
- README: which records the tree contains.
- Remove tests of @atproto/lex's own behaviour (request shape, response
  rejection); keep the tree, sharing, type and embedded-record tests.
- check:package keeps the SDK's three checks, without the tree-shaking and
  packed-license assertions, and runs once in the main CI job.
- Remove tsconfig.scripts.json: the build scripts are not type-checked.
The repository held @hypercerts-org/api in client/ and a package named
@hypercerts-org/hypercerts-api in api/. Folders now match what they hold:

- api/ -> happyview-modules/, package @hypercerts-org/happyview-modules
  (the HappyView modules, installer and tests; unchanged otherwise).
- client/ -> packages/api/ (@hypercerts-org/api), as in the SDK's packages/.

Paths in CI, the release workflow, docs, the explorer sources and the
pending changesets follow. Release tags from the next release on are
@hypercerts-org/happyview-modules@X.Y.Z (changeset added). The name is a
proposal for review.
Comment thread happyview-modules/README.md Resolved
@sonarqubecloud

Copy link
Copy Markdown

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

@kristoferlund
kristoferlund merged commit 5f3ef2b into main Nov 2, 2026
8 of 9 checks passed
@kristoferlund
kristoferlund deleted the kristofer/tech-799-hypercerts-api-typescript-types-for-the-xrpc-queries-as-a branch November 2, 2026 06:47
@github-actions github-actions Bot mentioned this pull request Nov 2, 2026

This branch was successfully deployed

1 active deployment
Preview — 5768b209 Deployed Oct 30, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants