pipework 0.261.1 → 0.261.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.261.2
4
+
5
+ - **Fixed: OpenAPI tuples keep their positions again** (#920). Since 0.261.1 a `check.tuple` was written as `items: { anyOf: [...] }`, so generators typed `[string, string]` as `string[]`. It is now `items: [...]` with `additionalItems: false` (or the rest element's schema), as before 0.261.1; a rest tuple's `minItems` counts only its fixed positions. #918's hoisting into `components.schemas` still applies inside tuples.
6
+
3
7
  ## 0.261.1
4
8
 
5
9
  - **Fixed: a recursive `check.lazy` no longer gives an OpenAPI document with refs nothing can resolve** (#918). `generateOpenAPI` (and `pipework openapi`) hoists a recursive schema into `components.schemas` (`Schema1`, `Schema2`, …; a `.meta({ id })` keeps its id) and references it as `#/components/schemas/<name>`; the same schema used by many routes is one component. Schemas are now written in OpenAPI 3.0 form: `.nullable()` is `nullable: true` instead of `anyOf [.., { type: 'null' }]`, and no `$schema` key. `components` is present only when something was hoisted. Fastify's request/response validation is unchanged.
@@ -4,7 +4,28 @@ export function toJsonSchema(schema) {
4
4
  }
5
5
  /** OpenAPI 3.0 form: `nullable: true`, no `$schema`; recursion still arrives as a `definitions` block. */
6
6
  export function toOpenApiSchema(schema) {
7
- return collapseSingleRefAllOf(z.toJSONSchema(schema, { target: 'openapi-3.0' }));
7
+ return collapseSingleRefAllOf(z.toJSONSchema(schema, { target: 'openapi-3.0', override: positionalTuple }));
8
+ }
9
+ // zod's openapi-3.0 target folds a tuple into `items: { anyOf: [...members, rest?] }`, which
10
+ // loses the positions. Rewrite it to `items: [...]` + `additionalItems` (false, or the rest schema).
11
+ function positionalTuple(ctx) {
12
+ const def = ctx.zodSchema._zod?.def;
13
+ if (def?.type !== 'tuple' || def.items === undefined)
14
+ return;
15
+ const items = ctx.jsonSchema['items'];
16
+ const members = items?.anyOf;
17
+ if (members === undefined)
18
+ return;
19
+ const count = def.items.length;
20
+ ctx.jsonSchema['items'] = members.slice(0, count);
21
+ if (def.rest === undefined || def.rest === null) {
22
+ ctx.jsonSchema['additionalItems'] = false;
23
+ }
24
+ else {
25
+ ctx.jsonSchema['additionalItems'] = members[count];
26
+ // zod counts the rest member in minItems; a rest tuple still accepts just its positions.
27
+ ctx.jsonSchema['minItems'] = count;
28
+ }
8
29
  }
9
30
  // zod emits a lazy reference as `{ allOf: [{ $ref }] }`; fast-json-stringify recurses
10
31
  // forever on that form when the target is recursive, and accepts the bare `$ref`.
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../../../src/data/schema/json-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AAK1B,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC5C,OAAO,sBAAsB,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAe,CAAA;AAC7F,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,OAAO,sBAAsB,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAe,CAAA;AAChG,CAAC;AAED,sFAAsF;AACtF,kFAAkF;AAClF,SAAS,sBAAsB,CAAC,IAAa;IAC3C,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;IAChE,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC1D,MAAM,MAAM,GAAG,IAA+B,CAAA;IAC9C,MAAM,GAAG,GAA4B,EAAE,CAAA;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,GAAG,KAAK,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QAChC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAA;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAC7D,MAAM,MAAM,GAAY,KAAK,CAAC,CAAC,CAAC,CAAA;IAChC,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IACxF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAChC,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,CAAA;AAChD,CAAC"}
1
+ {"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../../../src/data/schema/json-schema.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pipework",
3
- "version": "0.261.1",
3
+ "version": "0.261.2",
4
4
  "description": "TypeScript framework for multi-tenant SaaS applications. PostgreSQL-only.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -9,7 +9,26 @@ export function toJsonSchema(schema: z.ZodType): JsonSchema {
9
9
 
10
10
  /** OpenAPI 3.0 form: `nullable: true`, no `$schema`; recursion still arrives as a `definitions` block. */
11
11
  export function toOpenApiSchema(schema: z.ZodType): JsonSchema {
12
- return collapseSingleRefAllOf(z.toJSONSchema(schema, { target: 'openapi-3.0' })) as JsonSchema
12
+ return collapseSingleRefAllOf(z.toJSONSchema(schema, { target: 'openapi-3.0', override: positionalTuple })) as JsonSchema
13
+ }
14
+
15
+ // zod's openapi-3.0 target folds a tuple into `items: { anyOf: [...members, rest?] }`, which
16
+ // loses the positions. Rewrite it to `items: [...]` + `additionalItems` (false, or the rest schema).
17
+ function positionalTuple(ctx: { zodSchema: unknown; jsonSchema: Record<string, unknown> }): void {
18
+ const def = (ctx.zodSchema as { _zod?: { def?: { type?: string; items?: unknown[]; rest?: unknown } } })._zod?.def
19
+ if (def?.type !== 'tuple' || def.items === undefined) return
20
+ const items = ctx.jsonSchema['items'] as { anyOf?: unknown[] } | undefined
21
+ const members = items?.anyOf
22
+ if (members === undefined) return
23
+ const count = def.items.length
24
+ ctx.jsonSchema['items'] = members.slice(0, count)
25
+ if (def.rest === undefined || def.rest === null) {
26
+ ctx.jsonSchema['additionalItems'] = false
27
+ } else {
28
+ ctx.jsonSchema['additionalItems'] = members[count]
29
+ // zod counts the rest member in minItems; a rest tuple still accepts just its positions.
30
+ ctx.jsonSchema['minItems'] = count
31
+ }
13
32
  }
14
33
 
15
34
  // zod emits a lazy reference as `{ allOf: [{ $ref }] }`; fast-json-stringify recurses