typespec-http-zod 0.25.1 → 0.26.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/dist/src/zod.js CHANGED
@@ -12,6 +12,25 @@ import { reportDiagnostic } from "./lib.js";
12
12
  * failed the compile that would have written it.
13
13
  */
14
14
  const UNREPRESENTABLE = "z.never()";
15
+ /**
16
+ * **Installed by the registry, which is the only place that knows what a declared type is CALLED.**
17
+ *
18
+ * A property emitted as a getter needs its Zod type written out - see the getter docblock in
19
+ * `modelToZod`. Naming the type is the registry's job (it resolves a named type to its declaration,
20
+ * versioned name included), and `types.ts` already imports this module, so the annotation is handed
21
+ * in rather than computed here.
22
+ */
23
+ let annotateDeferred = () => undefined;
24
+ export function withDeferredAnnotator(annotator, run) {
25
+ const previous = annotateDeferred;
26
+ annotateDeferred = annotator;
27
+ try {
28
+ return run();
29
+ }
30
+ finally {
31
+ annotateDeferred = previous;
32
+ }
33
+ }
15
34
  /**
16
35
  * TypeSpec type -> Zod source text.
17
36
  *
@@ -762,9 +781,26 @@ function modelToZod(program, model) {
762
781
  .map((property) => {
763
782
  const key = propertyKey(program, property);
764
783
  const { value, deferred } = captureBackEdges(() => withDeclarationSite(property, () => propertyToZod(program, property)));
784
+ /**
785
+ * **A getter without a return type infers `unknown`, and the collapse is SILENT.**
786
+ *
787
+ * The docblock above claims the getter keeps `z.infer` inferring the recursive type. It does
788
+ * for the declaration itself, and not for a schema that WRAPS it: measured on the conformance
789
+ * corpus, `z.record(z.string(), innerModelSchema)` - what `@body body: Record<InnerModel>`
790
+ * emits - infers `children?: unknown`, and `.parse()` on it returns `unknown` outright. The
791
+ * generated server then failed to compile with `TS2322`, in `type/dictionary`, which is how
792
+ * this was found; nothing said the emitted TYPE was weaker than the document.
793
+ *
794
+ * Annotating the GETTER rather than the declaration is what keeps `.shape` and `.extend`,
795
+ * which inheritance and every group spread depend on. `: z.ZodType<T, T>` names both of Zod's
796
+ * parameters for the reason `renderSchemas` names both: one leaves the input side `unknown`.
797
+ */
798
+ const annotation = deferred ? (annotateDeferred(property) ?? "") : "";
765
799
  return {
766
800
  deferred,
767
- text: deferred ? `\tget ${key}() {\n\t\treturn ${value};\n\t},` : `\t${key}: ${value},`,
801
+ text: deferred
802
+ ? `\tget ${key}()${annotation} {\n\t\treturn ${value};\n\t},`
803
+ : `\t${key}: ${value},`,
768
804
  };
769
805
  });
770
806
  const entries = members.map((member) => member.text);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typespec-http-zod",
3
- "version": "0.25.1",
3
+ "version": "0.26.0",
4
4
  "description": "TypeSpec emitter and library: turn an HTTP service definition into Zod validators and framework-free contract types that agree, keyword for keyword, with the OpenAPI document @typespec/openapi3 publishes from the same source.",
5
5
  "keywords": [
6
6
  "codegen",