typespec-http-zod 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -177,12 +177,12 @@ then a range such as `4XX`, then `default`.
177
177
 
178
178
  ## What it emits
179
179
 
180
- | file | contents | emitted when |
181
- | ---------------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------- |
182
- | `schemas.gen.ts` | component schemas, per-operation path, query, header, body and response validators, and the response arms | always |
183
- | `requests.gen.ts` | framework-free TypeScript types, with no imports | `contracts-output-dir` is set |
184
- | `vocabularies.gen.ts` | each enum's members as a runtime tuple | `contracts-output-dir` is set |
185
- | `wire-contract.gen.ts` | assertions pairing the emitted Zod against those types | that and `contracts-package` |
180
+ | file | contents | emitted when |
181
+ | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
182
+ | `schemas.gen.ts` | component schemas, per-operation path, query, header, body and response validators, and the response arms | always |
183
+ | `requests.gen.ts` | framework-free TypeScript types, with no imports: the models, and every operation's input, success bodies and result (`WireInputs`, `WireOutputs`, `WireResults`) | `contracts-output-dir` is set |
184
+ | `vocabularies.gen.ts` | each enum's members as a runtime tuple | `contracts-output-dir` is set |
185
+ | `wire-contract.gen.ts` | assertions pairing the emitted Zod against those types | that and `contracts-package` |
186
186
 
187
187
  `wire-contract.gen.ts` is not imported by any other file. The file contains type-level assertions
188
188
  pairing each generated validator with its contract type, so a mismatch between the two is a compile
package/dist/src/api.d.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  import { type EmitContext, type Program, type Type } from "@typespec/compiler";
2
2
  import { type HttpOperation, type HttpService } from "@typespec/http";
3
3
  import { SchemaRegistry } from "./registry.js";
4
+ import { type StatusKey } from "./results.js";
4
5
  import { type EmittedPathSegment } from "./uri-template.js";
5
6
  export type { EmittedPathSegment } from "./uri-template.js";
7
+ export { CONTENTLESS_STATUS_CODES, STATUS_CODES } from "./statuses.js";
8
+ export { type BodyServing, isJsonMediaType, isMediaRange, isTextualMediaType, mediaTypeEssenceOf, mediaTypeTypeOf, type ResponseFacts, type ResultMember, resultMembersOf, type StatusKey, statusCodesOf, } from "./results.js";
6
9
  /**
7
10
  * `typespec-http-zod` - Zod validators and framework-free contract types from a TypeSpec HTTP
8
11
  * service, agreeing with the OpenAPI document `@typespec/openapi3` publishes from the same source.
@@ -64,13 +67,6 @@ export declare function successStatusOf(operation: HttpOperation): number | unde
64
67
  * asserts the two stay in step.
65
68
  */
66
69
  export declare function successStatusesOf(operation: HttpOperation): number[];
67
- /**
68
- * A status as the DOCUMENT keys it: an exact code, a `4XX` bucket, or the catch-all.
69
- *
70
- * `"default"` is kept as itself rather than mapped to a number. The document means "any status not
71
- * listed above", and inventing one would be answering a question the contract left open.
72
- */
73
- export type StatusKey = number | "default" | `${1 | 2 | 3 | 4 | 5}XX`;
74
70
  /**
75
71
  * A header one response declares, as a handler has to supply it.
76
72
  *
@@ -328,10 +324,29 @@ export interface EmittedRoute {
328
324
  /**
329
325
  * The input property that receives the UNPARSED body, when the operation declares one.
330
326
  *
331
- * A `bytes` body means the bytes themselves are the contract: where a signature covers exactly
332
- * what arrived, parsing and re-serialising would verify a different string than the sender signed.
327
+ * Three bodies are handed over unparsed. A `bytes` body, because the bytes themselves are the
328
+ * contract: where a signature covers exactly what arrived, parsing and re-serialising would verify
329
+ * a different string than the sender signed. An `Http.File` body, whose contents are the body. And
330
+ * a body declared only under media types nothing can parse into it, such as a model as
331
+ * `application/xml`, which is the text that arrived, or as `application/octet-stream`, which is
332
+ * the bytes. {@link rawBodyBinary} says which are bytes.
333
333
  */
334
334
  readonly rawBodyProperty: string | undefined;
335
+ /**
336
+ * Whether the raw body is BYTES - handed over as the unread stream - rather than the text a
337
+ * signature covers. A `bytes` body is bytes under a binary media type and text under a JSON one;
338
+ * an `Http.File` body is bytes whatever its media type, which is why a server cannot read this off
339
+ * {@link requestContentTypes}: a file declared `application/json` looks like a JSON body there.
340
+ * `false` where there is no raw body.
341
+ */
342
+ readonly rawBodyBinary: boolean;
343
+ /**
344
+ * **The raw body is declared with a schema nothing checks it against**: it is declared only under
345
+ * media types nothing can parse into it, such as a model as `application/xml`. A `bytes` or
346
+ * `Http.File` body declares nothing to check, so it is not this. The request-side twin of
347
+ * {@link ResultMember.unvalidated}.
348
+ */
349
+ readonly rawBodyUnvalidated: boolean;
335
350
  /**
336
351
  * The input property a PARSED body arrives under, where it must not be spread into the parameters.
337
352
  *
@@ -427,6 +442,17 @@ export interface RouteSchemaNames {
427
442
  */
428
443
  readonly queryFields: string | undefined;
429
444
  readonly header: string | undefined;
445
+ /**
446
+ * **The `accept` the negotiation selects this operation by**, on a route several operations
447
+ * share. `header` leaves it out there, because it chooses the operation rather than constraining
448
+ * one, and the operation's input still declares it: the one value that reaches this operation is
449
+ * its own literal, so a handler receives exactly that. `undefined` wherever `header` validates
450
+ * `accept` itself, or the operation declares no literal one.
451
+ */
452
+ readonly selectedAccept: {
453
+ readonly name: string;
454
+ readonly value: string;
455
+ } | undefined;
430
456
  /**
431
457
  * Cookie parameters. **Optional on the interface, so a server emitter that does not read it yet
432
458
  * still compiles** - this arrived after the other four and two emitters consume this type.
@@ -475,6 +501,13 @@ export interface EmittedService {
475
501
  readonly routes: readonly EmittedRoute[];
476
502
  /** The identifiers every per-operation validator was declared under, keyed by operation id. */
477
503
  readonly schemaNames: ReadonlyMap<string, RouteSchemaNames>;
504
+ /**
505
+ * **The operation each route was collected from, keyed by operation id**, so a wrapping emitter
506
+ * reading its doc comment, tags or diagnostic target reads the right one. Verb and path do not
507
+ * identify an operation: `@sharedRoute` puts several on one, and a lookup by them answers the
508
+ * same operation for each - its description became every member's, and its tags selected them.
509
+ */
510
+ readonly operations: ReadonlyMap<string, HttpOperation>;
478
511
  /** Where this service's artefacts were written - a server emitter writes its own beside them. */
479
512
  readonly outputDir: string;
480
513
  /** Already resolved through the per-service overrides, so a caller re-reads nothing. */