Bondery Docs

Schemas package imports

@bondery/schemas is the shared contract layer (types, Zod schemas, constants). Keep imports narrow by consumer so the webapp never loads API-only OpenAPI fixture graphs at runtime.

Import policy

ConsumerAllowed imports
webapp@bondery/schemas (types + entity schemas + constants), @bondery/schemas/constants, @bondery/schemas/entities/* — not @bondery/schemas/http
mobile@bondery/schemas, @bondery/schemas/sync, entity subpaths, constants
APIAny subpath, including @bondery/schemas/openapi/*, @bondery/schemas/http/responses

Webapp rules

  • Do not import @bondery/schemas/openapi/* at runtime (OpenAPI fixtures and registry are API-only).
  • Do not import EXAMPLE_* or registerOpenApiComponentSchemas from the root @bondery/schemas barrel.
  • import type { ... } from "@bondery/schemas" is always fine — types erase at compile time.

pnpm run check:schemas-imports -w webapp enforces these rules in CI.

API OpenAPI examples

Route-level examples live in @bondery/schemas/openapi/fixtures/*. Runtime modules (entities/*, sync/*, root index.ts, contact-id.ts) must not import those fixtures or attach .meta({ example }) at module init.

OpenAPI example validation runs in CI only:

  • scripts/openapi-example-fixtures.ts — maps schema export names → fixture payloads
  • scripts/check-contracts-openapi-examples.ts — validates fixtures against runtime Zod schemas
  • scripts/check-contracts-no-init-cycles.mjs — blocks #openapi/ imports in runtime paths

http/index.ts may inline small request/response samples; it must not import schema-examples or requests fixture barrels.

Types vs schemas (module split)

Each domain module uses a subfolder under packages/schemas/src (for example entities/contact/, sync/pull/, geocode/):

  • types.ts — public interfaces (no zod import)
  • schema.ts — Zod validators (satisfies z.ZodType<T> on chainable schemas)
  • contract.ts — compile-time equality locks (internal, not exported)
  • index.ts — barrel: export type { … } from "./types.js" and export { …Schema } from "./schema.js"

Do not add export type X = z.infer<…> to any file except *.contract.ts.

import type { Contact } from "@bondery/schemas" must resolve only through types.ts, not through schema modules.

After adding a new public subfolder barrel, run pnpm run sync-exports from the repo root.

Why this matters

Importing the full OpenAPI fixture barrel from entity modules created a circular module graph when Turbopack bundled @bondery/schemas with Zod for SSR, causing Cannot access '…' before initialization at runtime. The root barrel must stay web-safe: do not re-export #http/index.js or OpenAPI fixture barrels from src/index.ts.

Exporting z.infer types from the same modules as Zod schemas forces every consumer to materialize massive z.ZodObject<…> type graphs and slows TypeScript across the monorepo (especially webapp).

On this page