Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@contractkit/plugin-typescript

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@contractkit/plugin-typescript - npm Package Compare versions

Comparing version
0.17.2
to
0.17.3
+6
-6
.turbo/turbo-build$colon$ci.log
> @contractkit/plugin-typescript@0.17.2 build:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> @contractkit/plugin-typescript@0.17.3 build:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> eslint --max-warnings=0 && pnpm run build
> @contractkit/plugin-typescript@0.17.2 build /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> @contractkit/plugin-typescript@0.17.3 build /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly --declaration

@@ -14,7 +14,7 @@

ESM Build start
ESM dist/index.js 124.43 KB
ESM dist/index.js.map 269.86 KB
ESM ⚡️ Build success in 431ms
ESM dist/index.js 125.56 KB
ESM dist/index.js.map 272.67 KB
ESM ⚡️ Build success in 328ms
DTS Build start
DTS ⚡️ Build success in 4618ms
DTS ⚡️ Build success in 5174ms
DTS dist/index.d.ts 3.44 KB
> @contractkit/plugin-typescript@0.17.2 test:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> @contractkit/plugin-typescript@0.17.3 test:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> vitest run --coverage

@@ -9,13 +9,13 @@

✓ tests/codegen-operation.test.ts (88 tests) 57ms
✓ tests/codegen-contract.test.ts (122 tests) 122ms
✓ tests/codegen-sdk.test.ts (123 tests) 86ms
✓ tests/codegen-server.test.ts (15 tests) 32ms
✓ tests/codegen-plain-types.test.ts (58 tests) 27ms
✓ tests/pipeline.test.ts (25 tests) 102ms
✓ tests/codegen-operation.test.ts (88 tests) 168ms
✓ tests/codegen-sdk.test.ts (123 tests) 255ms
✓ tests/codegen-contract.test.ts (124 tests) 248ms
✓ tests/codegen-plain-types.test.ts (58 tests) 35ms
✓ tests/pipeline.test.ts (25 tests) 111ms
✓ tests/codegen-server.test.ts (15 tests) 17ms
 Test Files  6 passed (6)
 Tests  431 passed (431)
 Start at  18:49:08
 Duration  6.55s (transform 3.76s, setup 0ms, import 13.69s, tests 428ms, environment 1ms)
 Tests  433 passed (433)
 Start at  15:36:42
 Duration  6.17s (transform 2.45s, setup 0ms, import 11.28s, tests 833ms, environment 7ms)

@@ -26,5 +26,5 @@  % Coverage report from v8

-------------------|---------|----------|---------|---------|-------------------
All files | 77.47 | 74.06 | 82.02 | 79.41 |
src | 77.16 | 73.68 | 81.4 | 79.06 |
...n-contract.ts | 87.57 | 81.63 | 89.91 | 88.57 | ...1025,1030-1031
All files | 77.65 | 74.31 | 82.12 | 79.62 |
src | 77.35 | 73.93 | 81.51 | 79.28 |
...n-contract.ts | 87.83 | 82.12 | 90.08 | 88.96 | ...1069,1074-1075
...-operation.ts | 78.18 | 74.26 | 78.08 | 79.69 | ...68-679,684-685

@@ -31,0 +31,0 @@ ...lain-types.ts | 87.5 | 76.76 | 92.85 | 91.66 | ...99,211,217,269

# @contractkit/contractkit-plugin-typescript
## 0.17.3
### Patch Changes
- 1247514: Fix `override readonly` fields not being omitted from child Input schemas in Zod codegen
## 0.17.2

@@ -4,0 +10,0 @@

@@ -26,5 +26,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">77.47% </span>
<span class="strong">77.65% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1696/2189</span>
<span class='fraction'>1717/2211</span>
</div>

@@ -34,5 +34,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">74.06% </span>
<span class="strong">74.31% </span>
<span class="quiet">Branches</span>
<span class='fraction'>1091/1473</span>
<span class='fraction'>1108/1491</span>
</div>

@@ -42,5 +42,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">82.02% </span>
<span class="strong">82.12% </span>
<span class="quiet">Functions</span>
<span class='fraction'>292/356</span>
<span class='fraction'>294/358</span>
</div>

@@ -50,5 +50,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">79.41% </span>
<span class="strong">79.62% </span>
<span class="quiet">Lines</span>
<span class='fraction'>1478/1861</span>
<span class='fraction'>1497/1880</span>
</div>

@@ -87,13 +87,13 @@

<td class="file medium" data-value="src"><a href="src/index.html">src</a></td>
<td data-value="77.16" class="pic medium">
<td data-value="77.35" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 77%"></div><div class="cover-empty" style="width: 23%"></div></div>
</td>
<td data-value="77.16" class="pct medium">77.16%</td>
<td data-value="2137" class="abs medium">1649/2137</td>
<td data-value="73.68" class="pct medium">73.68%</td>
<td data-value="1440" class="abs medium">1061/1440</td>
<td data-value="81.4" class="pct high">81.4%</td>
<td data-value="328" class="abs high">267/328</td>
<td data-value="79.06" class="pct medium">79.06%</td>
<td data-value="1815" class="abs medium">1435/1815</td>
<td data-value="77.35" class="pct medium">77.35%</td>
<td data-value="2159" class="abs medium">1670/2159</td>
<td data-value="73.93" class="pct medium">73.93%</td>
<td data-value="1458" class="abs medium">1078/1458</td>
<td data-value="81.51" class="pct high">81.51%</td>
<td data-value="330" class="abs high">269/330</td>
<td data-value="79.28" class="pct medium">79.28%</td>
<td data-value="1834" class="abs medium">1454/1834</td>
</tr>

@@ -124,3 +124,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-01T18:49:14.623Z
at 2026-05-05T15:36:48.642Z
</div>

@@ -127,0 +127,0 @@ <script src="prettify.js"></script>

@@ -889,3 +889,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-01T18:49:14.623Z
at 2026-05-05T15:36:48.642Z
</div>

@@ -892,0 +892,0 @@ <script src="../prettify.js"></script>

@@ -26,5 +26,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">77.16% </span>
<span class="strong">77.35% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1649/2137</span>
<span class='fraction'>1670/2159</span>
</div>

@@ -34,5 +34,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">73.68% </span>
<span class="strong">73.93% </span>
<span class="quiet">Branches</span>
<span class='fraction'>1061/1440</span>
<span class='fraction'>1078/1458</span>
</div>

@@ -42,5 +42,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">81.4% </span>
<span class="strong">81.51% </span>
<span class="quiet">Functions</span>
<span class='fraction'>267/328</span>
<span class='fraction'>269/330</span>
</div>

@@ -50,5 +50,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">79.06% </span>
<span class="strong">79.28% </span>
<span class="quiet">Lines</span>
<span class='fraction'>1435/1815</span>
<span class='fraction'>1454/1834</span>
</div>

@@ -87,13 +87,13 @@

<td class="file high" data-value="codegen-contract.ts"><a href="codegen-contract.ts.html">codegen-contract.ts</a></td>
<td data-value="87.57" class="pic high">
<td data-value="87.83" class="pic high">
<div class="chart"><div class="cover-fill" style="width: 87%"></div><div class="cover-empty" style="width: 13%"></div></div>
</td>
<td data-value="87.57" class="pct high">87.57%</td>
<td data-value="652" class="abs high">571/652</td>
<td data-value="81.63" class="pct high">81.63%</td>
<td data-value="452" class="abs high">369/452</td>
<td data-value="89.91" class="pct high">89.91%</td>
<td data-value="119" class="abs high">107/119</td>
<td data-value="88.57" class="pct high">88.57%</td>
<td data-value="534" class="abs high">473/534</td>
<td data-value="87.83" class="pct high">87.83%</td>
<td data-value="674" class="abs high">592/674</td>
<td data-value="82.12" class="pct high">82.12%</td>
<td data-value="470" class="abs high">386/470</td>
<td data-value="90.08" class="pct high">90.08%</td>
<td data-value="121" class="abs high">109/121</td>
<td data-value="88.96" class="pct high">88.96%</td>
<td data-value="553" class="abs high">492/553</td>
</tr>

@@ -199,3 +199,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-01T18:49:14.623Z
at 2026-05-05T15:36:48.642Z
</div>

@@ -202,0 +202,0 @@ <script src="../prettify.js"></script>

@@ -637,3 +637,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-01T18:49:14.623Z
at 2026-05-05T15:36:48.642Z
</div>

@@ -640,0 +640,0 @@ <script src="../prettify.js"></script>

@@ -580,3 +580,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-01T18:49:14.623Z
at 2026-05-05T15:36:48.642Z
</div>

@@ -583,0 +583,0 @@ <script src="../prettify.js"></script>

@@ -344,7 +344,7 @@

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">847x</span>
<span class="cline-any cline-yes">857x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">308x</span>
<span class="cline-any cline-yes">313x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -393,3 +393,3 @@ <span class="cline-any cline-neutral">&nbsp;</span>

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">242x</span>
<span class="cline-any cline-yes">247x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -406,3 +406,3 @@ <span class="cline-any cline-neutral">&nbsp;</span>

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">166x</span>
<span class="cline-any cline-yes">171x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -417,3 +417,3 @@ <span class="cline-any cline-neutral">&nbsp;</span>

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">132x</span>
<span class="cline-any cline-yes">134x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -818,3 +818,3 @@ <span class="cline-any cline-neutral">&nbsp;</span>

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-01T18:49:14.623Z
at 2026-05-05T15:36:48.642Z
</div>

@@ -821,0 +821,0 @@ <script src="../prettify.js"></script>

@@ -104,3 +104,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-01T18:49:14.623Z
at 2026-05-05T15:36:48.642Z
</div>

@@ -107,0 +107,0 @@ <script src="../prettify.js"></script>

@@ -8,2 +8,3 @@ import type { ContractRootNode, ModelNode, ContractTypeNode, ObjectMode } from '@contractkit/core';

export declare function modeToWrapper(mode: ObjectMode): string;
/** Cross-file context passed to `generateContract` to wire up imports and Input/Output variant tracking. */
export interface ContractCodegenContext {

@@ -60,5 +61,9 @@ /** Map from model name → absolute output file path */

export declare function renderQueryType(type: ContractTypeNode, modelsWithInput?: Set<string>, defaultMode?: ObjectMode): string;
/** Returns true if `type` (recursively) contains a scalar with the given `name`. */
export declare function typeNeedsScalar(type: ContractTypeNode, name: string): boolean;
/** Returns true if any model in `root` uses a scalar with the given `name`. */
export declare function rootNeedsScalar(root: ContractRootNode, name: string): boolean;
/** Returns true if `type` (recursively) contains a `date`, `time`, or `datetime` scalar. */
export declare function typeNeedsDateTime(type: ContractTypeNode): boolean;
/** Collect model names referenced in `root` that are not defined locally (need to be imported). */
export declare function collectExternalRefs(root: ContractRootNode): string[];

@@ -65,0 +70,0 @@ /** Collect external Input variant refs needed for Input schema fields. */

@@ -1,1 +0,1 @@

{"version":3,"file":"codegen-contract.d.ts","sourceRoot":"","sources":["../src/codegen-contract.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACR,gBAAgB,EAChB,SAAS,EAET,gBAAgB,EAWhB,UAAU,EACb,MAAM,mBAAmB,CAAC;AAO3B;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAStD;AAID,MAAM,WAAW,sBAAsB;IACnC,sDAAsD;IACtD,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,8DAA8D;IAC9D,cAAc,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,6GAA6G;IAC7G,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAChC;AAID;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,uBAAuB,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,GAAG,CAAC,MAAM,CAAC,CAsCzH;AAkBD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAkEjG;AA+RD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,EAAE,OAAO,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CA6B5H;AA0ND;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAuDvH;AA2BD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAsCvH;AA0CD,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAuB7E;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAiBjE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAcpE;AAED,0EAA0E;AAC1E,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,gBAAgB,EAAE,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CA4BvG;AAmCD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CA6D/D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAgB3F;AAED,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD"}
{"version":3,"file":"codegen-contract.d.ts","sourceRoot":"","sources":["../src/codegen-contract.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACR,gBAAgB,EAChB,SAAS,EAET,gBAAgB,EAWhB,UAAU,EACb,MAAM,mBAAmB,CAAC;AAO3B;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAStD;AAID,4GAA4G;AAC5G,MAAM,WAAW,sBAAsB;IACnC,sDAAsD;IACtD,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,8DAA8D;IAC9D,cAAc,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,6GAA6G;IAC7G,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAChC;AAID;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,uBAAuB,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,GAAG,CAAC,MAAM,CAAC,CAsCzH;AAkBD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAkEjG;AAsUD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,EAAE,OAAO,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CA6B5H;AA0ND;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAuDvH;AA2BD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAsCvH;AA0CD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAuB7E;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7E;AAED,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAiBjE;AAED,mGAAmG;AACnG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAcpE;AAED,0EAA0E;AAC1E,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,gBAAgB,EAAE,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CA4BvG;AAmCD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CA6D/D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAgB3F;AAED,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD"}
{
"name": "@contractkit/plugin-typescript",
"version": "0.17.2",
"version": "0.17.3",
"description": "ContractKit built-in plugin: TypeScript codegen (SDK clients, Koa routers, Zod schemas, plain types)",

@@ -5,0 +5,0 @@ "author": {

@@ -43,2 +43,3 @@ import { relative, dirname } from 'node:path';

/** Cross-file context passed to `generateContract` to wire up imports and Input/Output variant tracking. */
export interface ContractCodegenContext {

@@ -254,3 +255,3 @@ /** Map from model name → absolute output file path */

const lines = needsInputSplit
? generateThreeSchemaModel(effective, outPath, modelsWithInput, modelsWithWriteonly)
? generateThreeSchemaModel(effective, outPath, modelsWithInput, modelsWithWriteonly, modelMap)
: generateSimpleModel(effective, outPath);

@@ -347,3 +348,23 @@

function generateThreeSchemaModel(model: ModelNode, outPath?: string, modelsWithInput?: Set<string>, modelsWithWriteonly?: Set<string>): string[] {
function collectEffectiveWritableFieldNames(modelName: string, modelMap: Map<string, ModelNode>): Set<string> {
const model = modelMap.get(modelName);
if (!model || model.type) return new Set();
const result = new Set<string>();
for (const base of model.bases ?? []) {
for (const f of collectEffectiveWritableFieldNames(base, modelMap)) result.add(f);
}
for (const field of model.fields) {
if (field.visibility === 'readonly') result.delete(field.name);
else result.add(field.name);
}
return result;
}
function generateThreeSchemaModel(
model: ModelNode,
outPath?: string,
modelsWithInput?: Set<string>,
modelsWithWriteonly?: Set<string>,
modelMap?: Map<string, ModelNode>,
): string[] {
const lines: string[] = [];

@@ -394,5 +415,24 @@ const name = model.name;

const writeBody = modelsWithInput ? renderInputFields(writeFields, modelsWithInput, model.mode) : renderFields(writeFields, model.mode);
// Fields that become readonly in this model but were writable in a base must be omitted from
// the base Input schema — Zod's .extend() cannot remove inherited fields.
const fieldsToOmit = new Set<string>();
if (bases.length > 0 && modelMap) {
for (const field of allFields) {
if (field.visibility === 'readonly') {
for (const base of bases) {
if (collectEffectiveWritableFieldNames(base, modelMap).has(field.name)) {
fieldsToOmit.add(field.name);
break;
}
}
}
}
}
const omitClause =
fieldsToOmit.size > 0
? `.omit({ ${[...fieldsToOmit].map(f => `${quoteKey(f)}: true`).join(', ')} })`
: '';
if (bases.length > 0) {
const { head, tail } = buildExtendChain(bases, b => (modelsWithInput?.has(b) ? `${b}Input` : b));
lines.push(`export const ${name}Input = ${head}${tail}.extend({`);
lines.push(`export const ${name}Input = ${head}${tail}${omitClause}.extend({`);
} else {

@@ -914,2 +954,3 @@ lines.push(`export const ${name}Input = ${wrapper}({`);

/** Returns true if `type` (recursively) contains a scalar with the given `name`. */
export function typeNeedsScalar(type: ContractTypeNode, name: string): boolean {

@@ -940,2 +981,3 @@ switch (type.kind) {

/** Returns true if any model in `root` uses a scalar with the given `name`. */
export function rootNeedsScalar(root: ContractRootNode, name: string): boolean {

@@ -945,2 +987,3 @@ return root.models.some(m => (m.type && typeNeedsScalar(m.type, name)) || m.fields.some(f => typeNeedsScalar(f.type, name)));

/** Returns true if `type` (recursively) contains a `date`, `time`, or `datetime` scalar. */
export function typeNeedsDateTime(type: ContractTypeNode): boolean {

@@ -965,2 +1008,3 @@ switch (type.kind) {

/** Collect model names referenced in `root` that are not defined locally (need to be imported). */
export function collectExternalRefs(root: ContractRootNode): string[] {

@@ -967,0 +1011,0 @@ const localNames = new Set(root.models.map(m => m.name));

@@ -660,2 +660,28 @@ import { generateContract, renderType } from '../src/codegen-contract.js';

});
it('omits override-readonly field from child Input schema', () => {
const root = contractRoot([
model('Base', [field('id', scalarType('uuid')), field('name', scalarType('string'))]),
model('Child', [field('name', scalarType('string'), { visibility: 'readonly', override: true })], {
bases: ['Base'],
}),
]);
const output = generateContract(root);
// Base has no visibility — no BaseInput
expect(output).not.toContain('BaseInput');
// Child re-declares 'name' as readonly, so 'name' must be omitted from Base before extending
expect(output).toContain('export const ChildInput = Base.omit({ name: true }).extend({');
});
it('omits override-readonly field inherited transitively through multiple bases', () => {
const root = contractRoot([
model('Root', [field('legalId', scalarType('uuid'))]),
model('Mid', [], { bases: ['Root'] }),
model('Child', [field('legalId', scalarType('uuid'), { visibility: 'readonly', override: true })], {
bases: ['Mid'],
}),
]);
const output = generateContract(root);
expect(output).toContain('export const ChildInput = Mid.omit({ legalId: true }).extend({');
});
});

@@ -662,0 +688,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display