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.3
to
0.17.4
+6
-6
.turbo/turbo-build$colon$ci.log
> @contractkit/plugin-typescript@0.17.3 build:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> @contractkit/plugin-typescript@0.17.4 build:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> eslint --max-warnings=0 && pnpm run build
> @contractkit/plugin-typescript@0.17.3 build /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> @contractkit/plugin-typescript@0.17.4 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 125.56 KB
ESM dist/index.js.map 272.67 KB
ESM ⚡️ Build success in 328ms
ESM dist/index.js 126.39 KB
ESM dist/index.js.map 274.93 KB
ESM ⚡️ Build success in 216ms
DTS Build start
DTS ⚡️ Build success in 5174ms
DTS ⚡️ Build success in 5850ms
DTS dist/index.d.ts 3.44 KB
> @contractkit/plugin-typescript@0.17.3 test:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> @contractkit/plugin-typescript@0.17.4 test:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript
> vitest run --coverage

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

✓ 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
✓ tests/codegen-operation.test.ts (88 tests) 98ms
✓ tests/codegen-contract.test.ts (124 tests) 242ms
✓ tests/codegen-sdk.test.ts (123 tests) 282ms
✓ tests/codegen-plain-types.test.ts (61 tests) 45ms
✓ tests/codegen-server.test.ts (15 tests) 22ms
✓ tests/pipeline.test.ts (25 tests) 120ms
 Test Files  6 passed (6)
 Tests  433 passed (433)
 Start at  15:36:42
 Duration  6.17s (transform 2.45s, setup 0ms, import 11.28s, tests 833ms, environment 7ms)
 Tests  436 passed (436)
 Start at  15:55:13
 Duration  6.81s (transform 3.80s, setup 0ms, import 13.43s, tests 808ms, environment 1ms)

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

-------------------|---------|----------|---------|---------|-------------------
All files | 77.65 | 74.31 | 82.12 | 79.62 |
src | 77.35 | 73.93 | 81.51 | 79.28 |
All files | 77.84 | 74.45 | 82.5 | 79.74 |
src | 77.54 | 74.08 | 81.92 | 79.4 |
...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
...lain-types.ts | 87.5 | 76.76 | 92.85 | 91.66 | ...99,211,217,269
...lain-types.ts | 89.08 | 78.37 | 96.66 | 92.3 | ...31,243,249,301
codegen-sdk.ts | 88.75 | 83.6 | 85 | 91.49 | ...23,678,712-729

@@ -33,0 +33,0 @@ index.ts | 23.35 | 19.51 | 33.33 | 25.69 | ...97,415,418,421

# @contractkit/contractkit-plugin-typescript
## 0.17.4
### Patch Changes
- 684a639: Fix plain TypeScript codegen producing invalid `extends` clauses when a child contract redeclares an inherited field without the explicit `override` keyword (e.g. narrowing `kind: BusinessRoleKind` to `kind: 'employee'`). The base is now wrapped in `Omit<Base, 'fieldName'>` for any redeclared field, matching the behaviour for explicit `override` fields.
## 0.17.3

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

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

<div class='fl pad1y space-right2'>
<span class="strong">77.65% </span>
<span class="strong">77.84% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1717/2211</span>
<span class='fraction'>1732/2225</span>
</div>

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

<div class='fl pad1y space-right2'>
<span class="strong">74.31% </span>
<span class="strong">74.45% </span>
<span class="quiet">Branches</span>
<span class='fraction'>1108/1491</span>
<span class='fraction'>1119/1503</span>
</div>

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

<div class='fl pad1y space-right2'>
<span class="strong">82.12% </span>
<span class="strong">82.5% </span>
<span class="quiet">Functions</span>
<span class='fraction'>294/358</span>
<span class='fraction'>297/360</span>
</div>

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

<div class='fl pad1y space-right2'>
<span class="strong">79.62% </span>
<span class="strong">79.74% </span>
<span class="quiet">Lines</span>
<span class='fraction'>1497/1880</span>
<span class='fraction'>1508/1891</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.35" class="pic medium">
<td data-value="77.54" 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.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>
<td data-value="77.54" class="pct medium">77.54%</td>
<td data-value="2173" class="abs medium">1685/2173</td>
<td data-value="74.08" class="pct medium">74.08%</td>
<td data-value="1470" class="abs medium">1089/1470</td>
<td data-value="81.92" class="pct high">81.92%</td>
<td data-value="332" class="abs high">272/332</td>
<td data-value="79.4" class="pct medium">79.4%</td>
<td data-value="1845" class="abs medium">1465/1845</td>
</tr>

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

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

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

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

<div class='fl pad1y space-right2'>
<span class="strong">87.5% </span>
<span class="strong">89.08% </span>
<span class="quiet">Statements</span>
<span class='fraction'>140/160</span>
<span class='fraction'>155/174</span>
</div>

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

<div class='fl pad1y space-right2'>
<span class="strong">76.76% </span>
<span class="strong">78.37% </span>
<span class="quiet">Branches</span>
<span class='fraction'>76/99</span>
<span class='fraction'>87/111</span>
</div>

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

<div class='fl pad1y space-right2'>
<span class="strong">92.85% </span>
<span class="strong">96.66% </span>
<span class="quiet">Functions</span>
<span class='fraction'>26/28</span>
<span class='fraction'>29/30</span>
</div>

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

<div class='fl pad1y space-right2'>
<span class="strong">91.66% </span>
<span class="strong">92.3% </span>
<span class="quiet">Lines</span>
<span class='fraction'>121/132</span>
<span class='fraction'>132/143</span>
</div>

@@ -342,3 +342,35 @@

<a name='L272'></a><a href='#L272'>272</a>
<a name='L273'></a><a href='#L273'>273</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<a name='L273'></a><a href='#L273'>273</a>
<a name='L274'></a><a href='#L274'>274</a>
<a name='L275'></a><a href='#L275'>275</a>
<a name='L276'></a><a href='#L276'>276</a>
<a name='L277'></a><a href='#L277'>277</a>
<a name='L278'></a><a href='#L278'>278</a>
<a name='L279'></a><a href='#L279'>279</a>
<a name='L280'></a><a href='#L280'>280</a>
<a name='L281'></a><a href='#L281'>281</a>
<a name='L282'></a><a href='#L282'>282</a>
<a name='L283'></a><a href='#L283'>283</a>
<a name='L284'></a><a href='#L284'>284</a>
<a name='L285'></a><a href='#L285'>285</a>
<a name='L286'></a><a href='#L286'>286</a>
<a name='L287'></a><a href='#L287'>287</a>
<a name='L288'></a><a href='#L288'>288</a>
<a name='L289'></a><a href='#L289'>289</a>
<a name='L290'></a><a href='#L290'>290</a>
<a name='L291'></a><a href='#L291'>291</a>
<a name='L292'></a><a href='#L292'>292</a>
<a name='L293'></a><a href='#L293'>293</a>
<a name='L294'></a><a href='#L294'>294</a>
<a name='L295'></a><a href='#L295'>295</a>
<a name='L296'></a><a href='#L296'>296</a>
<a name='L297'></a><a href='#L297'>297</a>
<a name='L298'></a><a href='#L298'>298</a>
<a name='L299'></a><a href='#L299'>299</a>
<a name='L300'></a><a href='#L300'>300</a>
<a name='L301'></a><a href='#L301'>301</a>
<a name='L302'></a><a href='#L302'>302</a>
<a name='L303'></a><a href='#L303'>303</a>
<a name='L304'></a><a href='#L304'>304</a>
<a name='L305'></a><a href='#L305'>305</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -366,28 +398,28 @@ <span class="cline-any cline-neutral">&nbsp;</span>

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-yes">19x</span>
<span class="cline-any cline-yes">19x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-no">&nbsp;</span>

@@ -401,9 +433,10 @@ <span class="cline-any cline-no">&nbsp;</span>

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">60x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

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

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">71x</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-neutral">&nbsp;</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">78x</span>
<span class="cline-any cline-yes">5x</span>

@@ -421,27 +461,51 @@ <span class="cline-any cline-neutral">&nbsp;</span>

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">88x</span>
<span class="cline-any cline-yes">97x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">66x</span>
<span class="cline-any cline-yes">73x</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">71x</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">71x</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-neutral">&nbsp;</span>
<span class="cline-any cline-yes">73x</span>
<span class="cline-any cline-yes">73x</span>
<span class="cline-any cline-yes">17x</span>
<span class="cline-any cline-yes">17x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">73x</span>
<span class="cline-any cline-yes">73x</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-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">73x</span>
<span class="cline-any cline-yes">109x</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">78x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-yes">78x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -468,52 +532,52 @@ <span class="cline-any cline-neutral">&nbsp;</span>

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">82x</span>
<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">91x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">6x</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">50x</span>
<span class="cline-any cline-yes">50x</span>
<span class="cline-any cline-yes">55x</span>
<span class="cline-any cline-yes">55x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">50x</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">50x</span>
<span class="cline-any cline-yes">55x</span>
<span class="cline-any cline-yes">55x</span>
<span class="cline-any cline-yes">55x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">50x</span>
<span class="cline-any cline-yes">71x</span>
<span class="cline-any cline-yes">55x</span>
<span class="cline-any cline-yes">77x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">50x</span>
<span class="cline-any cline-yes">50x</span>
<span class="cline-any cline-yes">55x</span>
<span class="cline-any cline-yes">55x</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">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">28x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">28x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">25x</span>
<span class="cline-any cline-yes">32x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">29x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</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">28x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">32x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -524,27 +588,27 @@ <span class="cline-any cline-neutral">&nbsp;</span>

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">96x</span>
<span class="cline-any cline-yes">96x</span>
<span class="cline-any cline-yes">96x</span>
<span class="cline-any cline-yes">96x</span>
<span class="cline-any cline-yes">96x</span>
<span class="cline-any cline-yes">96x</span>
<span class="cline-any cline-yes">96x</span>
<span class="cline-any cline-yes">96x</span>
<span class="cline-any cline-yes">106x</span>
<span class="cline-any cline-yes">106x</span>
<span class="cline-any cline-yes">106x</span>
<span class="cline-any cline-yes">106x</span>
<span class="cline-any cline-yes">106x</span>
<span class="cline-any cline-yes">106x</span>
<span class="cline-any cline-yes">106x</span>
<span class="cline-any cline-yes">106x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">96x</span>
<span class="cline-any cline-yes">106x</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">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -678,4 +742,6 @@ <span class="cline-any cline-neutral">&nbsp;</span>

&nbsp;
const modelMap = new Map(root.models.map(m =&gt; [m.name, m]));
&nbsp;
for (const model of topoSortModels(root.models)) {
lines.push(...generateModel(model, context?.currentOutPath, allModelsWithInput, allModelsWithOutput));
lines.push(...generateModel(model, context?.currentOutPath, allModelsWithInput, allModelsWithOutput, modelMap));
lines.push('');

@@ -689,3 +755,9 @@ }

&nbsp;
function generateModel(model: ModelNode, outPath?: string, modelsWithInput?: Set&lt;string&gt;, modelsWithOutput?: Set&lt;string&gt;): string[] {
function generateModel(
model: ModelNode,
outPath?: string,
modelsWithInput?: Set&lt;string&gt;,
modelsWithOutput?: Set&lt;string&gt;,
modelMap?: Map&lt;string, ModelNode&gt;,
): string[] {
// Type alias: Name : typeExpression

@@ -700,3 +772,3 @@ if (model.type) {

&nbsp;
const lines = needsInputSplit ? generateVisibilityModel(model, outPath, modelsWithInput) : generateSimpleModel(model, outPath);
const lines = needsInputSplit ? generateVisibilityModel(model, outPath, modelsWithInput, modelMap) : generateSimpleModel(model, outPath, modelMap);
&nbsp;

@@ -710,2 +782,26 @@ if (modelsWithOutput?.has(model.name)) {

&nbsp;
/** Recursively collect every field name defined on `bases` and their ancestors. Used to detect
* fields that the child re-declares without an explicit `override` keyword — those still need an
* `Omit&lt;Base, …&gt;` wrap, otherwise the child's narrower/incompatible declaration collides with the
* inherited one. */
function collectInheritedFieldNames(bases: string[], modelMap: Map&lt;string, ModelNode&gt;): Set&lt;string&gt; {
const result = new Set&lt;string&gt;();
const visit = (name: string): void =&gt; {
const m = modelMap.get(name);
if (!m || m.type) return;
for (const f of m.fields) result.add(f.name);
for (const b of m.bases ?? []) visit(b);
};
for (const b of bases) visit(b);
return result;
}
&nbsp;
/** Names of fields the child declaration overrides — explicit `override` plus any field whose
* name shadows an inherited one. The latter catches single-base redeclarations that omit the
* `override` keyword (e.g. narrowing `kind: BusinessRoleKind` → `kind: 'employee'`). */
function computeOverrideNames(model: ModelNode, modelMap?: Map&lt;string, ModelNode&gt;): string[] {
const inherited = modelMap ? collectInheritedFieldNames(model.bases ?? [], modelMap) : <span class="branch-1 cbranch-no" title="branch not covered" >new Set&lt;string&gt;();</span>
return model.fields.filter(f =&gt; f.override || inherited.has(f.name)).map(f =&gt; f.name);
}
&nbsp;
function generateComments(model: ModelNode, outPath?: string): string[] {

@@ -740,7 +836,7 @@ const lines: string[] = [];

&nbsp;
/** Build the `extends` clause for a multi-base model.
* Override-marked field names are wrapped in `Omit&lt;Base, 'name1' | 'name2'&gt;` per base so the
* subclass can legally redeclare them with new types. TypeScript's `Omit&lt;T, K extends keyof any&gt;`
* tolerates omit keys that don't appear on the base, so we omit unconditionally — no need to know
* each base's actual field set. */
/** Build the `extends` clause for a model.
* Each entry in `overrideNames` is wrapped in `Omit&lt;Base, 'name1' | 'name2'&gt;` per base so the
* subclass can legally redeclare those fields with new (possibly incompatible) types.
* TypeScript's `Omit&lt;T, K extends keyof any&gt;` tolerates omit keys that don't appear on the base,
* so we apply the same omit list to every base without per-base field-set lookup. */
function buildExtendsClause(bases: string[], overrideNames: string[], baseNameResolver: (b: string) =&gt; string): string {

@@ -754,3 +850,3 @@ if (bases.length === 0) return '';

&nbsp;
function generateSimpleModel(model: ModelNode, outPath?: string): string[] {
function generateSimpleModel(model: ModelNode, outPath?: string, modelMap?: Map&lt;string, ModelNode&gt;): string[] {
const lines: string[] = [];

@@ -760,3 +856,3 @@ lines.push(...generateComments(model, outPath));

const bases = model.bases ?? [];
const overrideNames = model.fields.filter(f =&gt; f.override).map(f =&gt; f.name);
const overrideNames = computeOverrideNames(model, modelMap);
lines.push(`export interface ${model.name}${buildExtendsClause(bases, overrideNames, b =&gt; b)} {`);

@@ -772,3 +868,3 @@ &nbsp;

&nbsp;
function generateVisibilityModel(model: ModelNode, outPath?: string, modelsWithInput?: Set&lt;string&gt;): string[] {
function generateVisibilityModel(model: ModelNode, outPath?: string, modelsWithInput?: Set&lt;string&gt;, modelMap?: Map&lt;string, ModelNode&gt;): string[] {
const lines: string[] = [];

@@ -778,3 +874,3 @@ lines.push(...generateComments(model, outPath));

const bases = model.bases ?? [];
const overrideNames = model.fields.filter(f =&gt; f.override).map(<span class="fstat-no" title="function not covered" >f =&gt; <span class="cstat-no" title="statement not covered" >f</span>.name)</span>;
const overrideNames = computeOverrideNames(model, modelMap);
&nbsp;

@@ -909,3 +1005,3 @@ // Read type — omit writeonly fields

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

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

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

<div class='fl pad1y space-right2'>
<span class="strong">77.35% </span>
<span class="strong">77.54% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1670/2159</span>
<span class='fraction'>1685/2173</span>
</div>

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

<div class='fl pad1y space-right2'>
<span class="strong">73.93% </span>
<span class="strong">74.08% </span>
<span class="quiet">Branches</span>
<span class='fraction'>1078/1458</span>
<span class='fraction'>1089/1470</span>
</div>

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

<div class='fl pad1y space-right2'>
<span class="strong">81.51% </span>
<span class="strong">81.92% </span>
<span class="quiet">Functions</span>
<span class='fraction'>269/330</span>
<span class='fraction'>272/332</span>
</div>

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

<div class='fl pad1y space-right2'>
<span class="strong">79.28% </span>
<span class="strong">79.4% </span>
<span class="quiet">Lines</span>
<span class='fraction'>1454/1834</span>
<span class='fraction'>1465/1845</span>
</div>

@@ -117,13 +117,13 @@

<td class="file high" data-value="codegen-plain-types.ts"><a href="codegen-plain-types.ts.html">codegen-plain-types.ts</a></td>
<td data-value="87.5" class="pic high">
<div class="chart"><div class="cover-fill" style="width: 87%"></div><div class="cover-empty" style="width: 13%"></div></div>
<td data-value="89.08" class="pic high">
<div class="chart"><div class="cover-fill" style="width: 89%"></div><div class="cover-empty" style="width: 11%"></div></div>
</td>
<td data-value="87.5" class="pct high">87.5%</td>
<td data-value="160" class="abs high">140/160</td>
<td data-value="76.76" class="pct medium">76.76%</td>
<td data-value="99" class="abs medium">76/99</td>
<td data-value="92.85" class="pct high">92.85%</td>
<td data-value="28" class="abs high">26/28</td>
<td data-value="91.66" class="pct high">91.66%</td>
<td data-value="132" class="abs high">121/132</td>
<td data-value="89.08" class="pct high">89.08%</td>
<td data-value="174" class="abs high">155/174</td>
<td data-value="78.37" class="pct medium">78.37%</td>
<td data-value="111" class="abs medium">87/111</td>
<td data-value="96.66" class="pct high">96.66%</td>
<td data-value="30" class="abs high">29/30</td>
<td data-value="92.3" class="pct high">92.3%</td>
<td data-value="143" class="abs high">132/143</td>
</tr>

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

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-05T15:36:48.642Z
at 2026-05-05T15:55:20.433Z
</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-05T15:36:48.642Z
at 2026-05-05T15:55:20.433Z
</div>

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

@@ -240,3 +240,3 @@

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

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

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">330x</span>
<span class="cline-any cline-yes">343x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">164x</span>
<span class="cline-any cline-yes">170x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -278,3 +278,3 @@ <span class="cline-any cline-yes">20x</span>

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

@@ -298,3 +298,3 @@ <span class="cline-any cline-yes">3x</span>

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

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

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

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

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

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

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">89x</span>
<span class="cline-any cline-yes">43x</span>
<span class="cline-any cline-yes">92x</span>
<span class="cline-any cline-yes">46x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

@@ -373,3 +373,3 @@ <span class="cline-any cline-yes">15x</span>

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

@@ -588,3 +588,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-05T15:36:48.642Z
at 2026-05-05T15:55:20.433Z
</div>

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

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

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">857x</span>
<span class="cline-any cline-yes">874x</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">313x</span>
<span class="cline-any cline-yes">318x</span>
<span class="cline-any cline-neutral">&nbsp;</span>

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

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

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

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

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

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

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

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

@@ -819,3 +819,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-05T15:36:48.642Z
at 2026-05-05T15:55:20.433Z
</div>

@@ -822,0 +822,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-05T15:36:48.642Z
at 2026-05-05T15:55:20.433Z
</div>

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

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

{"version":3,"file":"codegen-plain-types.d.ts","sourceRoot":"","sources":["../src/codegen-plain-types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAwB,MAAM,mBAAmB,CAAC;AAEhF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAapE;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAyCnG"}
{"version":3,"file":"codegen-plain-types.d.ts","sourceRoot":"","sources":["../src/codegen-plain-types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAwB,MAAM,mBAAmB,CAAC;AAEhF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAapE;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CA2CnG"}
{
"name": "@contractkit/plugin-typescript",
"version": "0.17.3",
"version": "0.17.4",
"description": "ContractKit built-in plugin: TypeScript codegen (SDK clients, Koa routers, Zod schemas, plain types)",

@@ -32,4 +32,4 @@ "author": {

"devDependencies": {
"@repo/config-eslint": "0.3.1",
"@repo/config-typescript": "0.1.0"
"@repo/config-typescript": "0.1.0",
"@repo/config-eslint": "0.3.1"
},

@@ -36,0 +36,0 @@ "scripts": {

@@ -58,4 +58,6 @@ import { relative, dirname } from 'node:path';

const modelMap = new Map(root.models.map(m => [m.name, m]));
for (const model of topoSortModels(root.models)) {
lines.push(...generateModel(model, context?.currentOutPath, allModelsWithInput, allModelsWithOutput));
lines.push(...generateModel(model, context?.currentOutPath, allModelsWithInput, allModelsWithOutput, modelMap));
lines.push('');

@@ -69,3 +71,9 @@ }

function generateModel(model: ModelNode, outPath?: string, modelsWithInput?: Set<string>, modelsWithOutput?: Set<string>): string[] {
function generateModel(
model: ModelNode,
outPath?: string,
modelsWithInput?: Set<string>,
modelsWithOutput?: Set<string>,
modelMap?: Map<string, ModelNode>,
): string[] {
// Type alias: Name : typeExpression

@@ -80,3 +88,3 @@ if (model.type) {

const lines = needsInputSplit ? generateVisibilityModel(model, outPath, modelsWithInput) : generateSimpleModel(model, outPath);
const lines = needsInputSplit ? generateVisibilityModel(model, outPath, modelsWithInput, modelMap) : generateSimpleModel(model, outPath, modelMap);

@@ -90,2 +98,26 @@ if (modelsWithOutput?.has(model.name)) {

/** Recursively collect every field name defined on `bases` and their ancestors. Used to detect
* fields that the child re-declares without an explicit `override` keyword — those still need an
* `Omit<Base, …>` wrap, otherwise the child's narrower/incompatible declaration collides with the
* inherited one. */
function collectInheritedFieldNames(bases: string[], modelMap: Map<string, ModelNode>): Set<string> {
const result = new Set<string>();
const visit = (name: string): void => {
const m = modelMap.get(name);
if (!m || m.type) return;
for (const f of m.fields) result.add(f.name);
for (const b of m.bases ?? []) visit(b);
};
for (const b of bases) visit(b);
return result;
}
/** Names of fields the child declaration overrides — explicit `override` plus any field whose
* name shadows an inherited one. The latter catches single-base redeclarations that omit the
* `override` keyword (e.g. narrowing `kind: BusinessRoleKind` → `kind: 'employee'`). */
function computeOverrideNames(model: ModelNode, modelMap?: Map<string, ModelNode>): string[] {
const inherited = modelMap ? collectInheritedFieldNames(model.bases ?? [], modelMap) : new Set<string>();
return model.fields.filter(f => f.override || inherited.has(f.name)).map(f => f.name);
}
function generateComments(model: ModelNode, outPath?: string): string[] {

@@ -120,7 +152,7 @@ const lines: string[] = [];

/** Build the `extends` clause for a multi-base model.
* Override-marked field names are wrapped in `Omit<Base, 'name1' | 'name2'>` per base so the
* subclass can legally redeclare them with new types. TypeScript's `Omit<T, K extends keyof any>`
* tolerates omit keys that don't appear on the base, so we omit unconditionally — no need to know
* each base's actual field set. */
/** Build the `extends` clause for a model.
* Each entry in `overrideNames` is wrapped in `Omit<Base, 'name1' | 'name2'>` per base so the
* subclass can legally redeclare those fields with new (possibly incompatible) types.
* TypeScript's `Omit<T, K extends keyof any>` tolerates omit keys that don't appear on the base,
* so we apply the same omit list to every base without per-base field-set lookup. */
function buildExtendsClause(bases: string[], overrideNames: string[], baseNameResolver: (b: string) => string): string {

@@ -134,3 +166,3 @@ if (bases.length === 0) return '';

function generateSimpleModel(model: ModelNode, outPath?: string): string[] {
function generateSimpleModel(model: ModelNode, outPath?: string, modelMap?: Map<string, ModelNode>): string[] {
const lines: string[] = [];

@@ -140,3 +172,3 @@ lines.push(...generateComments(model, outPath));

const bases = model.bases ?? [];
const overrideNames = model.fields.filter(f => f.override).map(f => f.name);
const overrideNames = computeOverrideNames(model, modelMap);
lines.push(`export interface ${model.name}${buildExtendsClause(bases, overrideNames, b => b)} {`);

@@ -152,3 +184,3 @@

function generateVisibilityModel(model: ModelNode, outPath?: string, modelsWithInput?: Set<string>): string[] {
function generateVisibilityModel(model: ModelNode, outPath?: string, modelsWithInput?: Set<string>, modelMap?: Map<string, ModelNode>): string[] {
const lines: string[] = [];

@@ -158,3 +190,3 @@ lines.push(...generateComments(model, outPath));

const bases = model.bases ?? [];
const overrideNames = model.fields.filter(f => f.override).map(f => f.name);
const overrideNames = computeOverrideNames(model, modelMap);

@@ -161,0 +193,0 @@ // Read type — omit writeonly fields

@@ -422,2 +422,40 @@ import { describe, it, expect } from 'vitest';

});
it('omits implicit single-base redeclarations even without explicit override', () => {
// BusinessRoleOfficer-style: child redeclares `kind` without `override` keyword,
// narrowing to an incompatible literal — must wrap base in Omit to compile.
const root = contractRoot([
model('Employee', [field('kind', literalType('employee')), field('title', scalarType('string'))]),
model('Officer', [field('kind', literalType('officer')), field('isControlPerson', scalarType('boolean'))], {
bases: ['Employee'],
}),
]);
const output = generatePlainTypes(root);
expect(output).toContain("export interface Officer extends Omit<Employee, 'kind'> {");
});
it('applies implicit-override Omit to both Read and Input interfaces', () => {
const root = contractRoot([
model('Employee', [
field('id', scalarType('uuid'), { visibility: 'readonly' }),
field('kind', literalType('employee')),
]),
model('Officer', [field('kind', literalType('officer')), field('isControlPerson', scalarType('boolean'))], {
bases: ['Employee'],
}),
]);
const output = generatePlainTypes(root);
expect(output).toContain("export interface Officer extends Omit<Employee, 'kind'> {");
expect(output).toContain("export interface OfficerInput extends Omit<EmployeeInput, 'kind'> {");
});
it('detects redeclaration through transitive base chain', () => {
const root = contractRoot([
model('Root', [field('kind', scalarType('string'))]),
model('Mid', [], { bases: ['Root'] }),
model('Leaf', [field('kind', literalType('leaf'))], { bases: ['Mid'] }),
]);
const output = generatePlainTypes(root);
expect(output).toContain("export interface Leaf extends Omit<Mid, 'kind'> {");
});
});

@@ -424,0 +462,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