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
6 changes: 6 additions & 0 deletions .github/workflows/aip-npm-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ jobs:
cache-dependency-path: api/spec/pnpm-lock.yaml
registry-url: "https://registry.npmjs.org"

# Publish gate: the SDK conformance suite and emitter checks must pass on
# the exact checkout being published, so a broken build can never reach npm
# even though this workflow runs independently of the CI workflow.
- name: Run SDK and emitter tests
run: make -C api/spec test

- name: Publish NPM package
run: make -C api/spec publish-aip-sdk
env:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,10 @@ jobs:
run: |
nix develop --impure .#ci -c make lint-api-spec

- name: Run tests - api spec SDK
run: |
nix develop --impure .#ci -c make test-api-spec

- name: Run linters - openapi
run: |
nix develop --impure .#ci -c make lint-openapi
Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ All generated files have `// Code generated by X, DO NOT EDIT.` headers — neve
2. Run `make gen-api` to regenerate OpenAPI spec and SDKs
3. Run `make generate` to regenerate Go server/client code

The TypeSpec JS client emitted from `api/spec/packages/aip` now lands in `api/spec/packages/aip-client-javascript/`. The emitter regenerates `src/` and `README.md` only; `package.json` is **stable, hand-maintained, and committed** (the emitter's `writeOutput` only writes the paths it lists, so the manifest survives regeneration). Keep hand-written Playwright config, tests, and helpers outside `src/`, and put test-runner dependencies/scripts in the `api/spec/package.json` workspace root rather than the client package manifest. Static publish metadata (`name`, `license`, `homepage`, `repository`) lives directly in the client `package.json`; only the per-release `version` is injected at publish time.
The TypeSpec JS client emitted from `api/spec/packages/aip` now lands in `api/spec/packages/aip-client-javascript/`. The emitter regenerates `src/`, `README.md`, and five conformance test files (`tests/client.spec.ts`, `tests/meters.spec.ts`, `tests/errors.spec.ts`, `tests/nesting.spec.ts`, `tests/internal.spec.ts`); every regenerated file carries a `Code generated by @openmeter/typespec-typescript. DO NOT EDIT.` header — treat files without that header as hand-written. `package.json` is **stable, hand-maintained, and committed** (the emitter's `writeOutput` only writes the paths it lists, so the manifest survives regeneration). The test suite is vitest + `@fetch-mock/vitest`; keep hand-written tests and helpers in `tests/` (never `src/`), and put test-runner dependencies/scripts in the `api/spec/package.json` workspace root rather than the client package manifest. Static publish metadata (`name`, `license`, `homepage`, `repository`) lives directly in the client `package.json`; only the per-release `version` is injected at publish time. Operations marked `x-private` in the TypeSpec source are omitted from the generated SDK (they stay in the OpenAPI output); operations marked `x-internal` (without `x-private`) are emitted but quarantined under `client.internal.<group>.<method>` (`src/sdk/internal.ts`, an `Internal` aggregate with `Internal<Group>` facade classes; internal ops share their group's `funcs/` and `models/operations/` modules, a group whose ops are all internal gets no public facade, and the `Internal` class is deliberately not re-exported from the package root — the name belongs to the Internal Server Error model). Removing an operation from the spec (or marking it private) leaves stale generated files behind — the emitter never deletes outputs, so `git rm` them.

The emitted `api/spec/packages/aip-client-javascript/src/openMeterClient.ts` exposes aggregated sub-client getters on `OpenMeterClient` (e.g. `meters`, `customers`, `features`, `productCatalog`, `subscriptions`, `billing`, `entitlements`). Access operations through those getters, e.g. `sdk.meters.list()`, `sdk.customers.create(...)`, `sdk.productCatalog.createPlan(...)`. Note that resources are grouped by tag, so some operations live under a grouped client rather than a same-named top-level getter (for example plan operations are `sdk.productCatalog.createPlan`, not `sdk.plans.create`).
The emitted `api/spec/packages/aip-client-javascript/src/sdk/sdk.ts` exposes aggregated sub-client getters on the `OpenMeter` class (e.g. `events`, `meters`, `customers`, `entitlements`, `subscriptions`, `billing`, `features`, `plans`, `addons`, `planAddons`, `tax`, `defaults`). Access operations through those getters, e.g. `sdk.meters.list()`, `sdk.customers.create(...)`, `sdk.plans.create(...)`. These grouped-client methods throw `HTTPError` on failure; the same operations are also available as tree-shakeable standalone functions under `src/funcs/` that return a `Result` instead of throwing.

**Workflow for changing Go types/DI:**

Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ lint-api-spec: ## Lint OpenAPI spec
$(call print-target)
$(MAKE) -C api/spec lint

.PHONY: test-api-spec
test-api-spec: ## Run AIP TypeScript SDK and emitter tests
$(call print-target)
$(MAKE) -C api/spec test

.PHONY: lint-openapi
lint-openapi: ## Lint OpenAPI spec
$(call print-target)
Expand Down
Loading
Loading