Skip to main content
Version: next

Update the Gezy API v4 client

This guide explains how to update the typed API v4 client when the Gezy backend API changes. The client is generated from the OpenAPI specification using Orval, ensuring type safety between Front-Commerce and Gezy.

Overview​

Front-Commerce uses Orval to generate a fully typed TypeScript client from the Gezy API v4 OpenAPI specification. Orval produces one factory per OpenAPI tag (e.g. getMarketplace, getOauth), each accepting an AxiosInstance and returning typed functions for that domain.

Gezy maintains two backend lines that evolve independently — v11 (e-commerce) and v12 (marketplace) — so the client is generated once per line, from that line's own committed specification.

This ensures that:

  • TypeScript types always reflect the real API contract
  • Breaking changes are caught at compile time
  • The client is request-scoped (no shared singleton)

The OpenAPI specifications are committed in the repository so that CI builds do not depend on a running Gezy backend.

Prerequisites​

  • A running Gezy backend instance with API v4 enabled
  • Node.js and pnpm installed

Updating the client​

Step 1: Fetch the OpenAPI specification of your line​

A deployment talks to one backend line, so it only ever fetches that line's specification:

# e-commerce line (the default)
FRONT_COMMERCE_GEZY_ENDPOINT=https://your-v11-instance.lundimatin.biz \
pnpm --filter @front-commerce/gezy fetch-openapi-v4 v11

# marketplace line
FRONT_COMMERCE_GEZY_ENDPOINT=https://your-v12-instance.lundimatin.biz \
pnpm --filter @front-commerce/gezy fetch-openapi-v4 v12

Pick the first or the second block — one run is enough. Each run saves the spec to packages/gezy/generated/openapi-v4.<flavor>.json. The backend line is the argument of the command and is required: fetching without naming the line is what used to mix two backends into a single specification. The endpoint defaults to http://localhost:8080.

The other line's spec is already committed and does not need refreshing: it belongs to the installations that run that line. Only a maintainer of the connector itself fetches both, to keep the mirror of both backends current.

Step 2: Regenerate the typed clients​

pnpm --filter @front-commerce/gezy generate-api-v4
pnpm prettier --write "packages/gezy/generated/**"

Orval writes with its own quote style and JSDoc indentation, while the committed outputs are prettier-formatted — the Lint job runs prettier --check ./packages and .prettierignore excludes none of packages/gezy/generated/. Format right after generating: without it the commit fails Lint, and the line-isolation check below reports a diff on the untouched line even though the isolation held.

This runs Orval with the configuration in packages/gezy/orval.config.ts — one target per line — and outputs one module per tag in packages/gezy/generated/api-v4/v11/ and packages/gezy/generated/api-v4/v12/. Only the tags listed in each target's input.filters.tags are generated; those filters describe the storefront surface, so a line's client stops at what the storefront calls even when the backend exposes more.

Both targets run and both outputs must exist at compile time — di.ts wires both lines — but the line you did not fetch is regenerated byte-identical: each target reads its own committed spec and only clears its own output directory. Verify it with git diff: the untouched line's directory must show no change.

Step 3: Review the changes​

git diff packages/gezy/generated/

Review the diff to understand what changed in the API. Look for:

  • New or removed endpoints
  • Changed request parameters
  • Changed response shapes
  • Fields that became required or optional

Step 4: Fix compilation errors​

If the API changed in a breaking way, TypeScript will flag errors in the code that uses the generated types. Fix these before committing.

Step 5: Commit both files​

Always commit the OpenAPI spec and the generated client together, so the repository stays consistent:

git add packages/gezy/generated/
git commit -m "chore(gezy): update API v4 OpenAPI spec and generated client"

Using the API v4 client​

The client is accessible through the Gezy DI as publicRestAPIv4 and privateRestAPIv4, organized by domain and built from the line the deployment targets. The clients only one line serves are reached through the requireCatalogAPI() / requireMarketplaceAPI() accessors, which fail with an actionable message on the other line:

// In a runtime.ts contextEnhancer
const marketplace = services.DI.get("gezy").requireMarketplaceAPI();

// Typed call: params and response are inferred from the OpenAPI spec
const response = await marketplace.getMerchants({ query: "tech", limit: 10 });

For tests, create a client bound to the mock server:

import { getMarketplace } from "@front-commerce/gezy/api-v4/v12/marketplace";

const api = getMarketplace(axios.create({ baseURL: mockServer.url }));
new MerchantLoader(api, makeDataLoaderStub);

Imports per backend line​

Generated clients and types are exposed per line — there is no shared entry point. The column below tells which backend line serves each client; a consumer still imports the line it is built for — @front-commerce/gezy-marketplace stays on v12 and @front-commerce/gezy internals on v11, enforced by the flavor ESLint guard:

Import pathServed by
@front-commerce/gezy/api-v4/v11/typesBoth lines (schema types)
@front-commerce/gezy/api-v4/v11/cmsBoth lines
@front-commerce/gezy/api-v4/v12/typesBoth lines (schema types)
@front-commerce/gezy/api-v4/v12/cmsBoth lines
@front-commerce/gezy/api-v4/v12/marketplacemarketplace line only

Only these entry points are exposed. The other generated modules (the catalogue, OAuth and System factories of both lines) are consumed by @front-commerce/gezy itself and are not part of the package's public surface: a project that needs one of them should ask for it to be exposed rather than deep-importing the generated files, which is not a stable path.

Imports of @front-commerce/gezy/api-v4/types, …/cms and …/marketplace — the entry points of the former single client — no longer resolve: point them at api-v4/v11/* or api-v4/v12/* (table in the migration guide).

Adding a new API tag​

When the storefront gains a new domain — add a tag only if the storefront calls it. A backend domain the storefront never calls (the merchant back office's Marketplace - * family, for instance) stays out of the filter and out of the client, even though the line serves it:

  1. Add the tag name to input.filters.tags of its line in orval.config.ts
  2. Run pnpm --filter @front-commerce/gezy generate-api-v4
  3. Import the new factory in di.ts and add it to publicRestAPIv4 or privateRestAPIv4, wired to that line
  4. Add the corresponding export in package.json

Manual grafts in a specification​

When shipped code consumes an endpoint its line has not merged yet, the missing block is copied from the other specification (never written by hand) and marked with x-front-commerce-manual-graft, stating why it is provisional. A test suite lists every graft it tolerates and fails as soon as the backend serves the real thing: drop the grafted block and regenerate at that point.

Architecture​

Gezy backend v11 (e-commerce) Gezy backend v12 (marketplace)
└─ GET /api/v4/openapi.json └─ GET /api/v4/openapi.json
└─ generated/openapi-v4.v11.json └─ generated/openapi-v4.v12.json
└─ Orval target gezyApiV4V11 └─ Orval target gezyApiV4V12
└─ generated/api-v4/v11/ └─ generated/api-v4/v12/
├─ index.schemas.ts ├─ index.schemas.ts
├─ catalog/catalog.ts ├─ marketplace/marketplace.ts
├─ cms/cms.ts ├─ cms/cms.ts
├─ oauth/oauth.ts ├─ oauth/oauth.ts
└─ system/system.ts └─ system/system.ts
generated/api-v4/v11/catalog/catalog.ts
└─ getCatalog(axiosInstance) → { getBrands }
generated/api-v4/v12/marketplace/marketplace.ts
└─ getMarketplace(axiosInstance) → { getMerchants }
generated/api-v4/v11/oauth/oauth.ts
└─ getOauth(axiosInstance) → { postToken, getMe }

DI (di.ts) — built from the `flavor` option of `gezy({ storesConfig, flavor })`
└─ publicRestAPIv4 / privateRestAPIv4
├─ marketplace (v12 only): getMarketplace(axiosInstance)
├─ catalog (v11 only): getCatalog(axiosInstance)
├─ oauth, cms, system: factories of the configured line
└─ axiosInstance: baseURL + X-LMB-Ecommerce-UUID header

Troubleshooting​

fetch-openapi-v4 fails immediately with a flavor error​

The command takes the backend line as its argument: fetch-openapi-v4 v11 or fetch-openapi-v4 v12. A fetch without it is what used to mix two backends into one file.

fetch-openapi-v4 fails with a connection error​

The Gezy backend is not running or not reachable. Verify that FRONT_COMMERCE_GEZY_ENDPOINT (or the default http://localhost:8080) is correct and the backend is started.

Generated types do not match the API response​

The committed OpenAPI spec may be outdated. Re-run fetch-openapi-v4 (for the right line) and generate-api-v4 to synchronize.

Orval generates hash-based function names​

The Orval configuration includes a custom operationName function that strips the tag prefix from names (e.g. getMerchants instead of getMarketplaceMerchants). If a new endpoint produces an odd name, adjust the function in packages/gezy/orval.config.ts.