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

@contractkit/core

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@contractkit/core - npm Package Compare versions

Comparing version
0.15.1
to
0.16.0
+7
-7
.turbo/turbo-build$colon$ci.log
> @contractkit/core@0.15.1 build:ci /home/runner/work/ContractKit/ContractKit/packages/contractkit
> @contractkit/core@0.16.0 build:ci /home/runner/work/ContractKit/ContractKit/packages/contractkit
> eslint --max-warnings=0 && pnpm run build
> @contractkit/core@0.15.1 build /home/runner/work/ContractKit/ContractKit/packages/contractkit
> @contractkit/core@0.16.0 build /home/runner/work/ContractKit/ContractKit/packages/contractkit
> tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly --declaration && cp src/contractkit.ohm dist/

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

ESM Build start
ESM dist/index.js 88.92 KB
ESM dist/index.js.map 211.24 KB
ESM ⚡️ Build success in 77ms
ESM dist/index.js 88.95 KB
ESM dist/index.js.map 211.52 KB
ESM ⚡️ Build success in 80ms
DTS Build start
DTS ⚡️ Build success in 1201ms
DTS dist/index.d.ts 31.82 KB
DTS ⚡️ Build success in 1235ms
DTS dist/index.d.ts 32.62 KB
> @contractkit/core@0.15.1 test:ci /home/runner/work/ContractKit/ContractKit/packages/contractkit
> @contractkit/core@0.16.0 test:ci /home/runner/work/ContractKit/ContractKit/packages/contractkit
> vitest run --coverage

@@ -9,8 +9,8 @@

✓ tests/incremental.test.ts (18 tests) 17ms
✓ tests/apply-options-defaults.test.ts (12 tests) 115ms
✓ tests/validate-inheritance.test.ts (16 tests) 73ms
✓ tests/parser-ck.test.ts (170 tests) 542ms
✓ tests/incremental.test.ts (18 tests) 22ms
✓ tests/apply-options-defaults.test.ts (12 tests) 104ms
✓ tests/validate-inheritance.test.ts (16 tests) 59ms
✓ tests/diagnostics.test.ts (10 tests) 15ms
✓ tests/apply-variable-substitution.test.ts (10 tests) 56ms
✓ tests/parser-ck.test.ts (170 tests) 595ms
✓ tests/apply-variable-substitution.test.ts (10 tests) 38ms
✓ tests/validate-discriminated.test.ts (5 tests) 28ms

@@ -20,4 +20,4 @@

 Tests  241 passed (241)
 Start at  11:16:31
 Duration  2.07s (transform 389ms, setup 0ms, import 2.71s, tests 847ms, environment 1ms)
 Start at  11:38:13
 Duration  2.08s (transform 564ms, setup 0ms, import 2.78s, tests 859ms, environment 1ms)

@@ -28,3 +28,3 @@  % Coverage report from v8

-------------------|---------|----------|---------|---------|-------------------
All files | 84.77 | 73.3 | 89.34 | 87.18 |
All files | 84.68 | 73.3 | 88.88 | 87.07 |
...ns-defaults.ts | 98 | 95.34 | 100 | 100 | 67,93

@@ -36,3 +36,3 @@ ...ubstitution.ts | 97.56 | 94.87 | 100 | 100 | 26,55

grammar.ts | 75 | 100 | 100 | 75 | 23-24
incremental.ts | 98.57 | 93.47 | 100 | 100 | 76-77,81
incremental.ts | 97.1 | 93.47 | 90.9 | 98.21 | 198
parser.ts | 100 | 66.66 | 100 | 100 | 25-26

@@ -39,0 +39,0 @@ semantics.ts | 92.55 | 79.37 | 92.52 | 95.5 | ...1200,1220-1224

# @contractkit/core
## 0.16.0
### Minor Changes
- 4ac6d4d: Move plugin incremental-build manifests under the CLI cache directory (default `.contractkit/cache/`, configurable via `config.cache.dir`). Bruno's `.contractkit-bruno-manifest.json` (in the bruno-collection dir), Python's `.contractkit-python-manifest.json` (in the python-sdk dir), and TypeScript's `.contractkit-typescript-manifest.json` (at rootDir) now all live as `bruno-manifest.json` / `python-manifest.json` / `typescript-manifest.json` under `ctx.cacheDir`, alongside the CLI's existing `build.json` and HTTP cache. Output dirs no longer contain build state.
`PluginContext` gains a `cacheDir: string` field. `runIncrementalCodegen` no longer takes a `manifestFilename` argument and no longer bundles the manifest into `filesToWrite` — the result's `manifest` is returned separately so plugins can persist it wherever they want. New helper `serializeIncrementalManifest(manifest)` produces the JSON form.
After upgrading, the old in-output manifests can be deleted manually (or with `--force`); plugins will simply do a full regen on the first run since they won't find a manifest at the new path.
## 0.15.1

@@ -4,0 +14,0 @@

@@ -358,3 +358,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

@@ -316,3 +316,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

@@ -1114,3 +1114,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1778152593980" clover="3.2.0">
<project timestamp="1778152593980" name="All files">
<metrics statements="1061" coveredstatements="925" conditionals="723" coveredconditionals="530" methods="197" coveredmethods="176" elements="1981" coveredelements="1631" complexity="0" loc="1061" ncloc="1061" packages="1" files="12" classes="12"/>
<coverage generated="1778153895258" clover="3.2.0">
<project timestamp="1778153895258" name="All files">
<metrics statements="1060" coveredstatements="923" conditionals="723" coveredconditionals="530" methods="198" coveredmethods="176" elements="1981" coveredelements="1629" complexity="0" loc="1060" ncloc="1060" packages="1" files="12" classes="12"/>
<file name="apply-options-defaults.ts" path="/home/runner/work/ContractKit/ContractKit/packages/contractkit/src/apply-options-defaults.ts">

@@ -125,3 +125,3 @@ <metrics statements="38" coveredstatements="38" conditionals="43" coveredconditionals="41" methods="9" coveredmethods="9"/>

<file name="incremental.ts" path="/home/runner/work/ContractKit/ContractKit/packages/contractkit/src/incremental.ts">
<metrics statements="57" coveredstatements="57" conditionals="46" coveredconditionals="43" methods="10" coveredmethods="10"/>
<metrics statements="56" coveredstatements="55" conditionals="46" coveredconditionals="43" methods="11" coveredmethods="10"/>
<line num="7" count="1" type="stmt"/>

@@ -180,6 +180,5 @@ <line num="62" count="9" type="stmt"/>

<line num="185" count="13" type="stmt"/>
<line num="186" count="13" type="stmt"/>
<line num="192" count="13" type="stmt"/>
<line num="194" count="14" type="stmt"/>
<line num="195" count="13" type="stmt"/>
<line num="193" count="13" type="stmt"/>
<line num="198" count="0" type="stmt"/>
</file>

@@ -186,0 +185,0 @@ <file name="parser.ts" path="/home/runner/work/ContractKit/ContractKit/packages/contractkit/src/parser.ts">

@@ -145,3 +145,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

@@ -187,3 +187,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

@@ -154,3 +154,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

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

<div class='fl pad1y space-right2'>
<span class="strong">98.57% </span>
<span class="strong">97.1% </span>
<span class="quiet">Statements</span>
<span class='fraction'>69/70</span>
<span class='fraction'>67/69</span>
</div>

@@ -41,5 +41,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="strong">90.9% </span>
<span class="quiet">Functions</span>
<span class='fraction'>10/10</span>
<span class='fraction'>10/11</span>
</div>

@@ -49,5 +49,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="strong">98.21% </span>
<span class="quiet">Lines</span>
<span class='fraction'>57/57</span>
<span class='fraction'>55/56</span>
</div>

@@ -265,3 +265,6 @@

<a name='L196'></a><a href='#L196'>196</a>
<a name='L197'></a><a href='#L197'>197</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<a name='L197'></a><a href='#L197'>197</a>
<a name='L198'></a><a href='#L198'>198</a>
<a name='L199'></a><a href='#L199'>199</a>
<a name='L200'></a><a href='#L200'>200</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>

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

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

@@ -458,7 +460,11 @@ <span class="cline-any cline-neutral">&nbsp;</span>

<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">13x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">13x</span>
<span class="cline-any cline-yes">13x</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-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { createHash } from 'node:crypto';

@@ -511,9 +517,9 @@ &nbsp;

&nbsp;
/** What {@link runIncrementalCodegen} produces — files the caller must write, the new manifest, paths that should be deleted, and a count of skipped units (useful for logging). */
/** What {@link runIncrementalCodegen} produces — output files the caller must write, the new manifest the caller must persist (separately, typically in the build cache directory), paths that should be deleted, and a count of skipped units (useful for logging). */
export interface IncrementalResult {
/** Files the caller should write (changed/new units' files plus global files plus the new manifest). */
/** Output files the caller should write (changed/new units' files plus global files). The manifest is **not** included — persist it separately via {@link IncrementalResult.manifest}. */
filesToWrite: IncrementalOutputFile[];
/** New manifest the caller should persist. Already included in `filesToWrite`. */
/** New manifest the caller should persist (typically as JSON to a path under the build cache directory). */
manifest: IncrementalManifest;
/** Relative paths from the prior run that no longer appear in the new manifest. The caller should delete these from disk. */
/** Relative paths from the prior run that no longer appear in the new run. The caller should delete these from disk. */
deletedPaths: string[];

@@ -597,10 +603,10 @@ /** Number of units whose codegen was skipped because their fingerprint matched. */

* The caller is responsible for:
* 1. Writing every `filesToWrite` entry.
* 2. Deleting every `deletedPaths` entry.
* 3. Persisting `manifest` to the manifest file path (already included in `filesToWrite`).
* 1. Writing every `filesToWrite` entry to disk.
* 2. Deleting every `deletedPaths` entry from disk.
* 3. Persisting `manifest` to its own location (typically `&lt;cacheDir&gt;/&lt;plugin&gt;-manifest.json`).
* The manifest is NOT in `filesToWrite` — it's deliberately separate so plugins can
* place build state under the CLI cache dir rather than mixing it with output files.
*/
export function runIncrementalCodegen(args: {
codegenVersion: string;
/** Relative path within the plugin's output dir where the manifest will be written. */
manifestFilename: string;
prevManifest: IncrementalManifest;

@@ -614,3 +620,3 @@ /** Files always written, regardless of cache state — typically aggregators or constants. */

}): IncrementalResult {
const { codegenVersion, manifestFilename, prevManifest, globalFiles, units, fileExists } = args;
const { codegenVersion, prevManifest, globalFiles, units, fileExists } = args;
const filesToWrite: IncrementalOutputFile[] = [];

@@ -650,3 +656,2 @@ const trackedPaths = new Set&lt;string&gt;();

&nbsp;
trackedPaths.add(manifestFilename);
const sortedFiles = [...trackedPaths].sort();

@@ -659,3 +664,2 @@ const manifest: IncrementalManifest = {

};
filesToWrite.push({ relativePath: manifestFilename, content: JSON.stringify(manifest, null, 2) + '\n' });
&nbsp;

@@ -665,2 +669,7 @@ const deletedPaths = prevManifest.files.filter(p =&gt; !trackedPaths.has(p));

}
&nbsp;
/** Serialize a manifest to the JSON form persisted on disk. */
export function <span class="fstat-no" title="function not covered" >serializeIncrementalManifest(m</span>anifest: IncrementalManifest): string {
<span class="cstat-no" title="statement not covered" > return JSON.stringify(manifest, null, 2) + '\n';</span>
}
&nbsp;</pre></td></tr></table></pre>

@@ -673,3 +682,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

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

<div class='fl pad1y space-right2'>
<span class="strong">84.77% </span>
<span class="strong">84.68% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1058/1248</span>
<span class='fraction'>1056/1247</span>
</div>

@@ -41,5 +41,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">89.34% </span>
<span class="strong">88.88% </span>
<span class="quiet">Functions</span>
<span class='fraction'>176/197</span>
<span class='fraction'>176/198</span>
</div>

@@ -49,5 +49,5 @@

<div class='fl pad1y space-right2'>
<span class="strong">87.18% </span>
<span class="strong">87.07% </span>
<span class="quiet">Lines</span>
<span class='fraction'>925/1061</span>
<span class='fraction'>923/1060</span>
</div>

@@ -176,13 +176,13 @@

<td class="file high" data-value="incremental.ts"><a href="incremental.ts.html">incremental.ts</a></td>
<td data-value="98.57" class="pic high">
<div class="chart"><div class="cover-fill" style="width: 98%"></div><div class="cover-empty" style="width: 2%"></div></div>
<td data-value="97.1" class="pic high">
<div class="chart"><div class="cover-fill" style="width: 97%"></div><div class="cover-empty" style="width: 3%"></div></div>
</td>
<td data-value="98.57" class="pct high">98.57%</td>
<td data-value="70" class="abs high">69/70</td>
<td data-value="97.1" class="pct high">97.1%</td>
<td data-value="69" class="abs high">67/69</td>
<td data-value="93.47" class="pct high">93.47%</td>
<td data-value="46" class="abs high">43/46</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="10" class="abs high">10/10</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="57" class="abs high">57/57</td>
<td data-value="90.9" class="pct high">90.9%</td>
<td data-value="11" class="abs high">10/11</td>
<td data-value="98.21" class="pct high">98.21%</td>
<td data-value="56" class="abs high">55/56</td>
</tr>

@@ -273,3 +273,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

@@ -169,3 +169,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

@@ -667,3 +667,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

@@ -763,3 +763,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

@@ -718,3 +718,3 @@

<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-05-07T11:16:33.959Z
at 2026-05-07T11:38:15.239Z
</div>

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

@@ -41,9 +41,9 @@ /**

}
/** What {@link runIncrementalCodegen} produces — files the caller must write, the new manifest, paths that should be deleted, and a count of skipped units (useful for logging). */
/** What {@link runIncrementalCodegen} produces — output files the caller must write, the new manifest the caller must persist (separately, typically in the build cache directory), paths that should be deleted, and a count of skipped units (useful for logging). */
export interface IncrementalResult {
/** Files the caller should write (changed/new units' files plus global files plus the new manifest). */
/** Output files the caller should write (changed/new units' files plus global files). The manifest is **not** included — persist it separately via {@link IncrementalResult.manifest}. */
filesToWrite: IncrementalOutputFile[];
/** New manifest the caller should persist. Already included in `filesToWrite`. */
/** New manifest the caller should persist (typically as JSON to a path under the build cache directory). */
manifest: IncrementalManifest;
/** Relative paths from the prior run that no longer appear in the new manifest. The caller should delete these from disk. */
/** Relative paths from the prior run that no longer appear in the new run. The caller should delete these from disk. */
deletedPaths: string[];

@@ -87,10 +87,10 @@ /** Number of units whose codegen was skipped because their fingerprint matched. */

* The caller is responsible for:
* 1. Writing every `filesToWrite` entry.
* 2. Deleting every `deletedPaths` entry.
* 3. Persisting `manifest` to the manifest file path (already included in `filesToWrite`).
* 1. Writing every `filesToWrite` entry to disk.
* 2. Deleting every `deletedPaths` entry from disk.
* 3. Persisting `manifest` to its own location (typically `<cacheDir>/<plugin>-manifest.json`).
* The manifest is NOT in `filesToWrite` — it's deliberately separate so plugins can
* place build state under the CLI cache dir rather than mixing it with output files.
*/
export declare function runIncrementalCodegen(args: {
codegenVersion: string;
/** Relative path within the plugin's output dir where the manifest will be written. */
manifestFilename: string;
prevManifest: IncrementalManifest;

@@ -104,2 +104,4 @@ /** Files always written, regardless of cache state — typically aggregators or constants. */

}): IncrementalResult;
/** Serialize a manifest to the JSON form persisted on disk. */
export declare function serializeIncrementalManifest(manifest: IncrementalManifest): string;
//# sourceMappingURL=incremental.d.ts.map

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

{"version":3,"file":"incremental.d.ts","sourceRoot":"","sources":["../src/incremental.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,yGAAyG;AACzG,MAAM,WAAW,qBAAqB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,0GAA0G;AAC1G,MAAM,WAAW,qBAAqB;IAClC,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,6HAA6H;IAC7H,KAAK,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,qGAAqG;IACrG,cAAc,EAAE,MAAM,CAAC;IACvB,kJAAkJ;IAClJ,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;CAChD;AAED,mIAAmI;AACnI,MAAM,WAAW,eAAe;IAC5B,yNAAyN;IACzN,GAAG,EAAE,MAAM,CAAC;IACZ,0MAA0M;IAC1M,WAAW,EAAE,MAAM,CAAC;IACpB,wIAAwI;IACxI,MAAM,EAAE,MAAM,qBAAqB,EAAE,CAAC;CACzC;AAED,oLAAoL;AACpL,MAAM,WAAW,iBAAiB;IAC9B,wGAAwG;IACxG,YAAY,EAAE,qBAAqB,EAAE,CAAC;IACtC,kFAAkF;IAClF,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,6HAA6H;IAC7H,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mFAAmF;IACnF,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED,qJAAqJ;AACrJ,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,mBAAmB,CAEpF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAwB7E;AAED,sHAAsH;AACtH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOtD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,mBAAmB,CAAC;IAClC,4FAA4F;IAC5F,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACrC,+CAA+C;IAC/C,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,uJAAuJ;IACvJ,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;CACjD,GAAG,iBAAiB,CAgDpB"}
{"version":3,"file":"incremental.d.ts","sourceRoot":"","sources":["../src/incremental.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,yGAAyG;AACzG,MAAM,WAAW,qBAAqB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,0GAA0G;AAC1G,MAAM,WAAW,qBAAqB;IAClC,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,6HAA6H;IAC7H,KAAK,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,qGAAqG;IACrG,cAAc,EAAE,MAAM,CAAC;IACvB,kJAAkJ;IAClJ,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;CAChD;AAED,mIAAmI;AACnI,MAAM,WAAW,eAAe;IAC5B,yNAAyN;IACzN,GAAG,EAAE,MAAM,CAAC;IACZ,0MAA0M;IAC1M,WAAW,EAAE,MAAM,CAAC;IACpB,wIAAwI;IACxI,MAAM,EAAE,MAAM,qBAAqB,EAAE,CAAC;CACzC;AAED,wQAAwQ;AACxQ,MAAM,WAAW,iBAAiB;IAC9B,0LAA0L;IAC1L,YAAY,EAAE,qBAAqB,EAAE,CAAC;IACtC,4GAA4G;IAC5G,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,wHAAwH;IACxH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mFAAmF;IACnF,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED,qJAAqJ;AACrJ,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,mBAAmB,CAEpF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAwB7E;AAED,sHAAsH;AACtH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOtD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,mBAAmB,CAAC;IAClC,4FAA4F;IAC5F,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACrC,+CAA+C;IAC/C,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,uJAAuJ;IACvJ,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;CACjD,GAAG,iBAAiB,CA8CpB;AAED,+DAA+D;AAC/D,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,CAElF"}

@@ -15,2 +15,9 @@ import type { CkRootNode, ContractRootNode, OpRootNode, PluginValue } from './ast.js';

cacheEnabled: boolean;
/**
* Absolute path to the build-cache directory (default `<rootDir>/.contractkit/cache`,
* configurable via `config.cache.dir`). Plugins that persist incremental-build state
* across runs should write their manifest here so it co-locates with the rest of the
* CLI's cache and is ignored by source control alongside it.
*/
cacheDir: string;
/** Register a file to be written to disk. Only available in generateTargets. */

@@ -17,0 +24,0 @@ emitFile(outPath: string, content: string): void;

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

{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEtF,MAAM,WAAW,aAAa;IAC1B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACpD;AAED,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC3B,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAC9B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAEzE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IAE9F;;;OAGG;IACH,eAAe,CAAC,EAAE,CACd,MAAM,EAAE;QACJ,aAAa,EAAE,gBAAgB,EAAE,CAAC;QAClC,OAAO,EAAE,UAAU,EAAE,CAAC;QACtB,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QACrC,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;KACzC,EACD,GAAG,EAAE,aAAa,KACjB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE;QACN,kDAAkD;QAClD,IAAI,EAAE,MAAM,CAAC;QACb,kEAAkE;QAClE,WAAW,EAAE,MAAM,CAAC;QACpB;;;WAGG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,6DAA6D;QAC7D,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC/D,CAAC;CACL"}
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEtF,MAAM,WAAW,aAAa;IAC1B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACpD;AAED,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC3B,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAC9B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAEzE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IAE9F;;;OAGG;IACH,eAAe,CAAC,EAAE,CACd,MAAM,EAAE;QACJ,aAAa,EAAE,gBAAgB,EAAE,CAAC;QAClC,OAAO,EAAE,UAAU,EAAE,CAAC;QACtB,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QACrC,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;KACzC,EACD,GAAG,EAAE,aAAa,KACjB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE;QACN,kDAAkD;QAClD,IAAI,EAAE,MAAM,CAAC;QACb,kEAAkE;QAClE,WAAW,EAAE,MAAM,CAAC;QACpB;;;WAGG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,6DAA6D;QAC7D,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC/D,CAAC;CACL"}
{
"name": "@contractkit/core",
"version": "0.15.1",
"version": "0.16.0",
"description": "Core DSL compiler library: grammar-driven parser, codegen, and validation",

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

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

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

@@ -112,7 +112,7 @@ # @contractkit/core

`PluginContext` exposes `options`, `rootDir`, `emitFile`, and `cacheEnabled`. `cacheEnabled` is `false` when the user passes `--force` or sets `cache: false`; plugins that maintain incremental-build state should bypass it then.
`PluginContext` exposes `options`, `rootDir`, `cacheDir`, `cacheEnabled`, and `emitFile`. `cacheEnabled` is `false` when the user passes `--force` or sets `cache: false`; plugins that maintain incremental-build state should bypass it then. `cacheDir` is the absolute path to the CLI's build-cache directory (default `<rootDir>/.contractkit/cache`) — plugins should persist their manifests there rather than mixing them with output files.
### Incremental codegen helper
Plugins that emit many files (one per operation, one per contract root, etc.) can opt into per-output caching via `runIncrementalCodegen`. The plugin defines cacheable "units" with a stable `key` and `fingerprint`; on subsequent runs, units whose fingerprint matches the persisted manifest skip their renderer entirely. Files in the prior manifest that aren't produced this run are reported in `deletedPaths` so the plugin can clean them up.
Plugins that emit many files (one per operation, one per contract root, etc.) can opt into per-output caching via `runIncrementalCodegen`. The plugin defines cacheable "units" with a stable `key` and `fingerprint`; on subsequent runs, units whose fingerprint matches the persisted manifest skip their renderer entirely. Files in the prior manifest that aren't produced this run are reported in `deletedPaths` so the plugin can clean them up. The manifest is returned separately from `filesToWrite` so plugins can persist it under `ctx.cacheDir` rather than alongside their outputs.

@@ -123,2 +123,3 @@ ```typescript

parseIncrementalManifest,
serializeIncrementalManifest,
emptyIncrementalManifest,

@@ -128,8 +129,12 @@ hashFingerprint,

} from '@contractkit/core';
import { resolve } from 'node:path';
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
const prev: IncrementalManifest = ctx.cacheEnabled ? readManifestFromDisk(outDir) : emptyIncrementalManifest('1');
const manifestPath = resolve(ctx.cacheDir, 'my-plugin-manifest.json');
const prev: IncrementalManifest = ctx.cacheEnabled && existsSync(manifestPath)
? parseIncrementalManifest(readFileSync(manifestPath, 'utf-8'))
: emptyIncrementalManifest('1');
const result = runIncrementalCodegen({
codegenVersion: '1', // bump to bust every per-unit cache
manifestFilename: '.my-plugin-manifest.json',
prevManifest: prev,

@@ -147,5 +152,9 @@ globalFiles: [/* always-regenerated outputs */],

for (const f of result.filesToWrite) ctx.emitFile(resolve(outDir, f.relativePath), f.content);
// Persist the manifest under the CLI cache dir.
mkdirSync(ctx.cacheDir, { recursive: true });
writeFileSync(manifestPath, serializeIncrementalManifest(result.manifest), 'utf-8');
```
Companion helpers: `hashFingerprint(value)` for stable sha256 hashing, `stableStringify(value)` for deterministic JSON, `collectTransitiveModelRefs(seedTypes, modelMap)` for slicing cross-file model dependencies into per-unit fingerprints.
Companion helpers: `hashFingerprint(value)` for stable sha256 hashing, `stableStringify(value)` for deterministic JSON (handles bigint and undefined), `collectTransitiveModelRefs(seedTypes, modelMap)` for slicing cross-file model dependencies into per-unit fingerprints.

@@ -152,0 +161,0 @@ ### Per-operation plugin files

@@ -48,9 +48,9 @@ import { createHash } from 'node:crypto';

/** What {@link runIncrementalCodegen} produces — files the caller must write, the new manifest, paths that should be deleted, and a count of skipped units (useful for logging). */
/** What {@link runIncrementalCodegen} produces — output files the caller must write, the new manifest the caller must persist (separately, typically in the build cache directory), paths that should be deleted, and a count of skipped units (useful for logging). */
export interface IncrementalResult {
/** Files the caller should write (changed/new units' files plus global files plus the new manifest). */
/** Output files the caller should write (changed/new units' files plus global files). The manifest is **not** included — persist it separately via {@link IncrementalResult.manifest}. */
filesToWrite: IncrementalOutputFile[];
/** New manifest the caller should persist. Already included in `filesToWrite`. */
/** New manifest the caller should persist (typically as JSON to a path under the build cache directory). */
manifest: IncrementalManifest;
/** Relative paths from the prior run that no longer appear in the new manifest. The caller should delete these from disk. */
/** Relative paths from the prior run that no longer appear in the new run. The caller should delete these from disk. */
deletedPaths: string[];

@@ -134,10 +134,10 @@ /** Number of units whose codegen was skipped because their fingerprint matched. */

* The caller is responsible for:
* 1. Writing every `filesToWrite` entry.
* 2. Deleting every `deletedPaths` entry.
* 3. Persisting `manifest` to the manifest file path (already included in `filesToWrite`).
* 1. Writing every `filesToWrite` entry to disk.
* 2. Deleting every `deletedPaths` entry from disk.
* 3. Persisting `manifest` to its own location (typically `<cacheDir>/<plugin>-manifest.json`).
* The manifest is NOT in `filesToWrite` — it's deliberately separate so plugins can
* place build state under the CLI cache dir rather than mixing it with output files.
*/
export function runIncrementalCodegen(args: {
codegenVersion: string;
/** Relative path within the plugin's output dir where the manifest will be written. */
manifestFilename: string;
prevManifest: IncrementalManifest;

@@ -151,3 +151,3 @@ /** Files always written, regardless of cache state — typically aggregators or constants. */

}): IncrementalResult {
const { codegenVersion, manifestFilename, prevManifest, globalFiles, units, fileExists } = args;
const { codegenVersion, prevManifest, globalFiles, units, fileExists } = args;
const filesToWrite: IncrementalOutputFile[] = [];

@@ -187,3 +187,2 @@ const trackedPaths = new Set<string>();

trackedPaths.add(manifestFilename);
const sortedFiles = [...trackedPaths].sort();

@@ -196,3 +195,2 @@ const manifest: IncrementalManifest = {

};
filesToWrite.push({ relativePath: manifestFilename, content: JSON.stringify(manifest, null, 2) + '\n' });

@@ -202,1 +200,6 @@ const deletedPaths = prevManifest.files.filter(p => !trackedPaths.has(p));

}
/** Serialize a manifest to the JSON form persisted on disk. */
export function serializeIncrementalManifest(manifest: IncrementalManifest): string {
return JSON.stringify(manifest, null, 2) + '\n';
}

@@ -16,2 +16,9 @@ import type { CkRootNode, ContractRootNode, OpRootNode, PluginValue } from './ast.js';

cacheEnabled: boolean;
/**
* Absolute path to the build-cache directory (default `<rootDir>/.contractkit/cache`,
* configurable via `config.cache.dir`). Plugins that persist incremental-build state
* across runs should write their manifest here so it co-locates with the rest of the
* CLI's cache and is ignored by source control alongside it.
*/
cacheDir: string;
/** Register a file to be written to disk. Only available in generateTargets. */

@@ -18,0 +25,0 @@ emitFile(outPath: string, content: string): void;

@@ -100,3 +100,2 @@ import { describe, it, expect } from 'vitest';

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: emptyIncrementalManifest('1'),

@@ -108,3 +107,6 @@ globalFiles: [],

expect(result.skippedUnitCount).toBe(0);
expect(result.filesToWrite.map(f => f.relativePath).sort()).toEqual(['a.ts', 'manifest.json']);
// Manifest is returned separately (not included in filesToWrite) so callers can
// persist it under the CLI cache dir rather than the plugin's output dir.
expect(result.filesToWrite.map(f => f.relativePath)).toEqual(['a.ts']);
expect(result.manifest.units['a']?.files).toEqual(['a.ts']);
expect(result.deletedPaths).toEqual([]);

@@ -116,3 +118,2 @@ });

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: emptyIncrementalManifest('1'),

@@ -126,3 +127,2 @@ globalFiles: [],

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: first.manifest,

@@ -144,3 +144,3 @@ globalFiles: [],

expect(renderCalls).toBe(0);
expect(second.filesToWrite.map(f => f.relativePath)).toEqual(['manifest.json']);
expect(second.filesToWrite).toEqual([]);
});

@@ -151,3 +151,2 @@

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: emptyIncrementalManifest('1'),

@@ -160,3 +159,2 @@ globalFiles: [],

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: first.manifest,

@@ -174,3 +172,2 @@ globalFiles: [],

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: emptyIncrementalManifest('1'),

@@ -183,3 +180,2 @@ globalFiles: [],

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: first.manifest,

@@ -197,3 +193,2 @@ globalFiles: [],

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: emptyIncrementalManifest('1'),

@@ -206,3 +201,2 @@ globalFiles: [],

codegenVersion: '2',
manifestFilename: 'manifest.json',
prevManifest: first.manifest,

@@ -219,3 +213,2 @@ globalFiles: [],

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: emptyIncrementalManifest('1'),

@@ -231,3 +224,2 @@ globalFiles: [],

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: first.manifest,

@@ -244,3 +236,2 @@ globalFiles: [],

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: emptyIncrementalManifest('1'),

@@ -253,3 +244,2 @@ globalFiles: [{ relativePath: 'aggregator.ts', content: 'old' }],

codegenVersion: '1',
manifestFilename: 'manifest.json',
prevManifest: first.manifest,

@@ -256,0 +246,0 @@ globalFiles: [{ relativePath: 'aggregator.ts', content: 'new' }],

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