wow-client · diff

git:20261003.1465ec2 to git:20261004.2702e5d

32 added, 25 removed. Audit A to A.

---
name: "wow-client"
- description: "Build TypeScript clients for Wow services with @ahoo-wang/wow-client: commands and wait stages, snapshot/event queries, aggregate-state loaders, QueryClientFactory, resource attribution, the filter/aggregation query DSL, and React query hooks from @ahoo-wang/wow-react. Use for runtime Wow client code or consuming generated CQRS clients in downstream TypeScript apps, including moving from @ahoo-wang/fetcher-wow. Exclude OpenAPI code generation, Kotlin/Java Wow services, and developing the packages inside the Wow repository."
+ description: "Write TypeScript code that calls Wow services: @ahoo-wang/wow-client commands and wait stages, snapshot/event queries, the filter and aggregation DSL, error handling, @ahoo-wang/wow-react query hooks, and typed clients generated from OpenAPI with the wow-generator CLI. Includes moving from @ahoo-wang/fetcher-wow or fetcher-generator. Exclude Kotlin/Java services, view-engine definitions and hosts, and developing these packages inside the Wow repository."
---
# wow-client
+ Calling a Wow service from TypeScript, with generated or hand-written clients. Full guides: https://wow.ahoo.me/guide/typescript/ ; API reference: https://wow.ahoo.me/reference/typescript/ .
+
## Workflow
- 1. Start from aggregate metadata: service, bounded context, aggregate name, tenant, and owner attribution.
- 2. Use `CommandClient` for command writes and query clients for read-side access; keep those flows separate.
- 3. Use `QueryClientFactory` when multiple query clients share the same metadata and attribution path spec.
- 4. Build query conditions with the `filter.*` and `aggregation.*` builders instead of ad hoc JSON objects. Aggregation groups and metrics take `(target, alias, options?)`, e.g. `aggregation.count('paid', { filter })`.
- 5. Build command headers with `commandHeaders({ … })` and `waitStrategy({ stage, timeoutMs?, tail? })`; `CommandClient` is not generic, so pass the body type per call: `send<C>(request)`.
- 6. Handle failures as exceptions: every refused request and every command whose processing failed rejects with the fetcher's error, never resolves with a failure. Read it with `await toWowError(error)` (a `WowError` with `errorCode`, `errorMsg`, `bindingErrors`, `status`; `undefined` when Wow never answered) and switch on `ErrorCodes`. A stream that fails midway throws a `WowError` from `for await`; in `sendAndWaitStream`, a stage that failed arrives as a result whose `errorCode` is not `ErrorCodes.SUCCEEDED`.
- 7. Pass cancellation as the last argument of query methods: `abort` accepts an `AbortController` or an `AbortSignal` (`AbortSignal.timeout(ms)`, a data library's `signal`).
- 8. Load `references/api.md` for installation and entry points, constructors, client methods, command stages and headers, errors, query DSL operators, key types, generated clients, React hooks, and complete flows.
+ 1. Start from aggregate metadata: service, bounded context, aggregate name, tenant, and owner attribution. When the service publishes OpenAPI (`/v3/api-docs`), generate the clients (`wow-generator generate`) and treat that document as the source of truth; load `references/generator.md`.
+ 2. Use `CommandClient` (or a generated `…CommandClient`) for writes and query clients for reads; keep the flows separate. Use `QueryClientFactory` when several query clients share metadata and attribution.
+ 3. Build queries with the `filter.*` and `aggregation.*` builders, not ad hoc JSON. Aggregation groups and metrics take `(target, alias, options?)`, e.g. `aggregation.count('paid', { filter })`.
+ 4. Build command headers with `commandHeaders({ … })` and `waitStrategy({ stage, timeoutMs?, tail? })`. `CommandClient` is not generic: pass the body type per call, `send<C>(request)`.
+ 5. Handle failures as exceptions (below). Pass cancellation as the last argument of query methods: `abort` takes an `AbortController` or `AbortSignal` (`AbortSignal.timeout(ms)`, a data library's `signal`).
+ 6. Load `references/api.md` for entry points, client methods, headers, errors, the DSL, key types and React hooks. Confirm exact signatures in the installed typings, or in `typescript/wow-client/src`, `typescript/wow-react/src` and `typescript/wow-generator/src` at the matching release, before relying on an overload, default or output shape.
## Packages
- - Install `@ahoo-wang/wow-client` with its peer dependencies `@ahoo-wang/fetcher`, `@ahoo-wang/fetcher-decorator`, and `@ahoo-wang/fetcher-eventstream`. Those fetcher packages keep their names; only the Wow client moved. The Wow 9.2 packages accept them as `^5.1.5`: fetcher 6 is outside the range until a Wow patch release widens it after 6.0 is released and verified.
- - For React, add `@ahoo-wang/wow-react`. It runs its own request state machine and does not need `@ahoo-wang/fetcher-react`.
- - Entries: `@ahoo-wang/wow-client` exports everything except the deprecated `Condition` API; `@ahoo-wang/wow-client/dsl` exports only the query DSL (`filter`, `aggregation`, sort, projection, pagination, cursor and query factories) without loading any HTTP code; `@ahoo-wang/wow-client/legacy` exports the `Condition` API for Wow 8.10 servers until v10.
- - Code moving from `@ahoo-wang/fetcher-wow` swaps the dependency and import specifiers to `@ahoo-wang/wow-client`, imports `Condition` builders from `@ahoo-wang/wow-client/legacy`, imports Wow query hooks from `@ahoo-wang/wow-react` instead of the `@ahoo-wang/fetcher-react` root, and fixes the first release's API changes the type check reports (`ErrorCodes.isSucceeded` removed, non-generic `CommandClient`, typed command headers, `abort` parameter, aggregation builder arguments, `createLoadOwnerStateAggregateClient`).
+ - `@ahoo-wang/wow-client` with peers `@ahoo-wang/fetcher`, `@ahoo-wang/fetcher-decorator` and `@ahoo-wang/fetcher-eventstream`; the fetcher packages keep their names. From Wow 9.2.1 the Wow packages accept them as `^5.1.5 || ^6.0.0`; 9.2.0 accepts `^5.1.5` only, so an application moving to fetcher 6 takes Wow 9.2.1 or later.
+ - React: `@ahoo-wang/wow-react` (React 19.0 or later). It runs its own request state machine and does not need `@ahoo-wang/fetcher-react`.
+ - Generation: `@ahoo-wang/wow-generator` and `typescript` as dev dependencies; generated code imports `@ahoo-wang/wow-client`, `@ahoo-wang/fetcher`, `@ahoo-wang/fetcher-decorator` and `@ahoo-wang/fetcher-eventstream` at run time, so the application depends on them directly.
+ - Entries: `@ahoo-wang/wow-client` exports everything except the deprecated `Condition` API; `/dsl` exports only the query DSL with no HTTP code; `/legacy` exports the `Condition` API for Wow 8.10 servers until v10.
+ - Supported servers: Wow 8.11 and later with `filter.*`; Wow 8.10 only through `/legacy`. Node `>=22.12.0`.
- ## Key Practices
+ ## Moving from fetcher packages
- - Errors are exceptions: wrap calls in `try`/`catch` and read failures with `toWowError`; do not branch on a returned `errorCode` for plain `send` calls.
- - Generated clients merge their constructor options over their defaults: `new CartCommandClient({ fetcher })` keeps the bounded-context prefix (`example` in `example/owner/...`), which a gateway routes by. When the application calls the service directly, pass `basePath: ''` to command clients and `contextAlias: ''` to query factories.
- - Authentication belongs to the Fetcher, not the clients: register the service's Fetcher (for example `new NamedFetcher('default', { baseURL })`) and apply `@ahoo-wang/fetcher-cosec`'s `CoSecConfigurer` to it; CoSec adds the Bearer token and fills `{tenantId}`/`{ownerId}` from the token. Without CoSec, pass `urlParams: { path: { ownerId } }`. On a server, create a Fetcher per request that carries a user's credentials; never put them on the process-wide default.
- - Supported servers: Wow 8.11 and later with `filter.*`; Wow 8.10 only through `@ahoo-wang/wow-client/legacy`. Node `>=22.12.0`; `wow-react` needs React 19.0 or later.
- - Keep command requests explicit about aggregate identity and expected command result behavior.
- - Use generated clients when OpenAPI metadata is the source of truth.
- - Confirm exact signatures in the installed package typings, or in the Wow repository sources under `typescript/wow-client/src` and `typescript/wow-react/src` at the matching release, before relying on an overload or default.
- - Route generation-time questions to `wow-generator`; keep this skill focused on runtime Wow clients, the query DSL, and React query hooks.
+ - `@ahoo-wang/fetcher-wow` → `@ahoo-wang/wow-client` in dependencies and imports; `Condition` builders from `@ahoo-wang/wow-client/legacy`; Wow query hooks from `@ahoo-wang/wow-react` instead of the `@ahoo-wang/fetcher-react` root. Then fix what the type check reports: `ErrorCodes.isSucceeded` removed, non-generic `CommandClient`, typed command headers, the `abort` parameter, aggregation builder arguments, `createLoadOwnerStateAggregateClient`.
+ - `@ahoo-wang/fetcher-generator` → `@ahoo-wang/wow-generator`: rename the script command (`fetcher-generator` stays an alias until v10) and `fetcher-generator.config.json` → `wow-generator.config.json`, then regenerate so imports switch to `@ahoo-wang/wow-client`.
+ - fetcher-wow and fetcher-generator are deprecated on npm. Guide: https://wow.ahoo.me/guide/typescript/migration.html.
+ ## Gotchas
+
+ - Errors are exceptions: every refused request and every command whose processing failed rejects; it never resolves with a failure. Read it with `await toWowError(error)` (a `WowError` with `errorCode`, `errorMsg`, `bindingErrors`, `status`; `undefined` when Wow never answered) and switch on `ErrorCodes`. A stream that fails midway throws a `WowError` from `for await`; in `sendAndWaitStream` a failed stage arrives as a result whose `errorCode` is not `ErrorCodes.SUCCEEDED`.
+ - Generated clients merge constructor options over their defaults: `new CartCommandClient({ fetcher })` keeps the bounded-context prefix (`example/owner/...`), which a gateway routes by. Calling the service directly, pass `basePath: ''` to command clients and `contextAlias: ''` to query factories.
+ - Authentication belongs to the Fetcher: register the service's Fetcher (for example `new NamedFetcher('default', { baseURL })`) and apply `@ahoo-wang/fetcher-cosec`'s `CoSecConfigurer`, which adds the Bearer token and fills `{tenantId}`/`{ownerId}`. Without CoSec, pass `urlParams: { path: { ownerId } }`. On a server, create a Fetcher per request that carries a user's credentials, never on the process-wide default (https://wow.ahoo.me/guide/typescript/ssr-and-node.html).
+ - Treat generated code as an output boundary: change the OpenAPI document or `wow-generator.config.json` and regenerate, never hand-edit. Commit the output with its `.wow-generator.json` manifest; in CI run with `--strict` (https://wow.ahoo.me/guide/typescript/regenerate-in-ci.html).
+ - An aggregate is generated only with a `{context}.{aggregate}` tag plus both `.snapshot_state.single` and `.snapshot.count` operations; otherwise it is skipped with a warning, not turned into a plain API client.
+ - Keep command requests explicit about aggregate identity and the expected command result.
+
## References
- - `references/api.md`: Detailed package API, examples, and edge-case guidance. Load it only when the task needs imports and entry points, constructors, command APIs and headers, error handling, query clients, aggregate load clients, factory setup, query DSL operators, key types, generated clients, React query hooks, and end-to-end examples.
+ - `references/api.md`: entry points, constructors, `CommandClient`, stages and headers, errors, query clients and loaders, `QueryClientFactory`, cursors, the filter and aggregation DSL, the legacy `Condition` API, key types, generated clients, React hooks, and a complete flow. Load it before writing client code.
+ - `references/generator.md`: CLI flags and exit codes, `CodeGenerator`, configuration, output layout, aggregate discovery, generated command, query and API clients. Load it for generation, regeneration, or reading generated code.
## Related Skills
- - $wow-generator: Use to generate Wow CQRS clients from OpenAPI specs.
- - Fetcher core, decorator, event-stream, CoSec, and generic React hooks are documented by the fetcher project skills.
+ - $wow-develop: the Kotlin/Java service behind the client.
+ - $wow-view-host: wiring the view engine and its declared actions; $wow-view-definition: what a view declares.
+ - Fetcher core, decorator, event-stream, CoSec and generic React hooks are documented by the fetcher project skills.