Skip to content

Commit 1caae5b

Browse files
tothandrasclaude
andcommitted
feat(sdk): generate TypeScript SDK and Zod schemas for the AIP spec
Generate a TypeScript SDK (`@openmeter/sdk`) and matching Zod schemas from the AIP TypeSpec definitions, via a vendored fork of the TypeSpec http-client-js emitter (`@openmeter/typespec-typescript`) and a Zod emitter (`@openmeter/typespec-zod`). All naming/packaging logic lives in the emitters; no `.tsp` spec files or OpenAPI output are changed, so the OpenAPI schema is unaffected. SDK surface: - One `OpenMeterClient` with tag-grouped sub-clients and lazy getters; list operations return a lazy PagedAsyncIterableIterator. - Honor `@friendlyName` when naming declarations, so template-derived request bodies are `CreatePlanRequest` rather than `CreateRequest_9`. References resolve via refkey, keeping all call sites consistent. - `strip-name-prefixes` emitter option (opt-in) strips configured prefixes from type and sub-client class names (`BillingPriceType` -> `PriceType`, `OpenMeterFeaturesClient` -> `FeaturesClient`). Collision-guarded: a prefix is only removed when the shortened name does not clash with another emitted name, so disambiguating prefixes (`BillingAddress` vs `Address`) are kept. The root `OpenMeterClient` is never stripped. Enabled as `[Billing, OpenMeter]` for both emitters. - Drop std-library scalar aliases (`String = string`, `Boolean = boolean`); user-declared domain scalars are kept. `delete` is no longer mangled to `delete_` in member position. - `OperationOptions.onResponse` body typed `unknown` instead of `any`. Packaging & tooling: - Wire up the Zod schemas: emitted to `src/zod-schemas.ts` (compiled) and exposed via a `@openmeter/sdk/zod` export. - `files: ["dist"]` allowlist so publish tarballs are dist-scoped. - Per-service URL resolvers filtered by `include-services`. - Auto-generated README ("Available Resources", quickstart, error handling) and MIGRATION guide; runnable quickstart example exercised in CI. - serializer + client-runtime smoke tests; npm release workflow. Verified: build, tsc, smoke tests, and lint all pass; regeneration is idempotent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 1175288 commit 1caae5b

236 files changed

Lines changed: 47842 additions & 4507 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,19 @@ jobs:
699699
run: |
700700
nix develop --impure .#ci -c go test -v -count=1 ./quickstart/
701701
702+
- name: Run TypeScript SDK example
703+
env:
704+
OPENMETER_URL: http://localhost:48888/api/v3
705+
working-directory: api/spec
706+
run: |
707+
# Build dist/ from src/, then run the quickstart example against it.
708+
nix develop --impure ../../.#ci -c bash -c '
709+
corepack enable >/dev/null 2>&1 || true
710+
pnpm install --frozen-lockfile 2>&1 | tail -5
711+
pnpm --filter @openmeter/sdk run build
712+
node --experimental-strip-types packages/aip-client-javascript/examples/quickstart/main.ts
713+
'
714+
702715
- name: Cleanup Docker Compose
703716
run: docker compose -f docker-compose.yaml -f docker-compose.override.yaml down -v
704717
working-directory: quickstart

AGENTS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ All generated files have `// Code generated by X, DO NOT EDIT.` headers — neve
9090
2. Run `make gen-api` to regenerate OpenAPI spec and SDKs
9191
3. Run `make generate` to regenerate Go server/client code
9292

93+
The TypeSpec JS client emitted from `api/spec/packages/aip` now lands in `api/spec/packages/aip-client-javascript/`. Treat `api/spec/packages/aip-client-javascript/src/` and its generated `package.json` as emitter output: keep hand-written Playwright config, tests, and helpers outside `src/`, and put test runner dependencies/scripts in the stable `api/spec/package.json` workspace root instead of the generated client package manifest.
94+
95+
The emitted `api/spec/packages/aip-client-javascript/src/openMeterClient.ts` currently exports an `OpenMeterClient` class without aggregated operation properties. For tests or local tooling, compose the generated `*EndpointsClient` / `*Client` classes around `OpenMeterClient` instead of assuming the top-level class exposes `meters`, `customers`, `plans`, or similar sub-clients.
96+
9397
When adding query decorators (for example `@query`) to a TypeSpec file that does not already use HTTP decorators, import `@typespec/http` and add `using TypeSpec.Http;` in that file; otherwise compilation fails with `Unknown decorator @query`.
9498

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

api/spec/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# TypeSpec output (all packages)
22
**/output/
3+
**/dist/
34

45
# Dependency directories
56
node_modules/
7+
tsconfig.tsbuildinfo

api/spec/.prettierignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
.npmrc
22
pnpm-lock.yaml
33
packages/**/output/
4+
packages/**/dist/
5+
packages/typespec-typescript/src/static-helpers/lib-files-data.gen.ts

api/spec/package.json

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
"version": "0.1.0",
44
"type": "module",
55
"scripts": {
6-
"generate": "pnpm --filter @openmeter/api-spec-legacy run generate && pnpm --filter @openmeter/api-spec-aip run generate",
6+
"build": "pnpm --filter @openmeter/typespec-zod --filter @openmeter/typespec-typescript run build",
7+
"generate": "pnpm run build && pnpm --filter @openmeter/api-spec-legacy run generate && pnpm --filter @openmeter/api-spec-aip run generate",
78
"format": "prettier --list-different --find-config-path --write . && pnpm --filter @openmeter/api-spec-aip run format",
89
"lint": "prettier --check . && pnpm --filter @openmeter/api-spec-legacy run lint && pnpm --filter @openmeter/api-spec-aip run lint",
9-
"lint:fix": "prettier --write ."
10+
"lint:fix": "prettier --write .",
11+
"test:sdk": "pnpm --filter @openmeter/sdk run build && node packages/aip-client-javascript/serializer-smoke-test.mjs && node packages/aip-client-javascript/client-runtime-test.mjs",
12+
"test:client:e2e": "playwright test --config packages/client/playwright.config.ts"
1013
},
1114
"devDependencies": {
15+
"@playwright/test": "1.59.1",
1216
"@typespec/prettier-plugin-typespec": "1.11.0",
1317
"prettier": "3.8.3"
1418
},
@@ -19,20 +23,28 @@
1923
"./v3/openapi.yaml": "./packages/aip/output/definitions/metering-and-billing/v3/openapi.MeteringAndBilling.yaml"
2024
},
2125
"private": true,
22-
"packageManager": "pnpm@10.33.2+sha512.a90faf6feeab71ad6c6e57f94e0fe1a12f5dcc22cd754db40ae9593eb6a3e0b6b12e3540218bb37ae083404b1f2ce6db2a4121e979829b4aff94b99f49da1cf8",
26+
"packageManager": "pnpm@10.34.1+sha512.b58fbde6dca66a929538021581f648b4570b6ca19b18e7cbd7f2c07a7b24454155388dacdf08f2af3678e88a6d1fe04f9d609df24bf51735a060ea041b374ab7",
2327
"pnpm": {
24-
"onlyBuiltDependencies": [
25-
"@typespec/http-client-python"
26-
],
2728
"patchedDependencies": {
2829
"@typespec/http": "patches/@typespec__http.patch",
2930
"@typespec/compiler": "patches/@typespec__compiler.patch",
3031
"@typespec/openapi": "patches/@typespec__openapi.patch",
3132
"@typespec/openapi3": "patches/@typespec__openapi3.patch",
32-
"@typespec/http-client-python": "patches/@typespec__http-client-python.patch"
33+
"@typespec/http-client": "patches/@typespec__http-client.patch",
34+
"@typespec/emitter-framework@0.17.0": "patches/@typespec__emitter-framework@0.17.0.patch"
3335
},
3436
"overrides": {
35-
"postcss@<8.5.10": ">=8.5.10"
37+
"postcss@<8.5.10": ">=8.5.10",
38+
"playwright@<1.55.1": ">=1.55.1",
39+
"fast-xml-builder@<=1.1.6": ">=1.1.7",
40+
"fast-xml-builder@=1.1.5": ">=1.1.6",
41+
"fast-uri@<=3.1.0": ">=3.1.1",
42+
"fast-uri@<=3.1.1": ">=3.1.2",
43+
"@protobufjs/utf8@<=1.1.0": ">=1.1.1",
44+
"protobufjs@<=7.5.5": ">=7.5.6",
45+
"semver@<7.7.4": ">=7.7.4",
46+
"@alloy-js/core": "0.23.1",
47+
"@alloy-js/typescript": "0.23.0"
3648
}
3749
}
3850
}

0 commit comments

Comments
 (0)