footprintjs 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +137 -41
  2. package/dist/esm/index.js +7 -1
  3. package/dist/esm/lib/builder/FlowChartBuilder.js +72 -91
  4. package/dist/esm/lib/builder/types.js +1 -1
  5. package/dist/esm/lib/contract/defineContract.js +32 -0
  6. package/dist/esm/lib/contract/index.js +18 -0
  7. package/dist/esm/lib/contract/openapi.js +120 -0
  8. package/dist/esm/lib/contract/schema.js +199 -0
  9. package/dist/esm/lib/contract/types.js +9 -0
  10. package/dist/esm/lib/engine/graph/StageNode.js +1 -1
  11. package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +5 -5
  12. package/dist/esm/lib/engine/handlers/ContinuationResolver.js +6 -6
  13. package/dist/esm/lib/engine/handlers/DeciderHandler.js +4 -4
  14. package/dist/esm/lib/engine/handlers/NodeResolver.js +1 -2
  15. package/dist/esm/lib/engine/handlers/RuntimeStructureManager.js +1 -2
  16. package/dist/esm/lib/engine/handlers/SelectorHandler.js +6 -6
  17. package/dist/esm/lib/engine/narrative/ControlFlowNarrativeGenerator.js +13 -18
  18. package/dist/esm/lib/engine/narrative/types.js +1 -1
  19. package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +10 -11
  20. package/dist/esm/lib/engine/types.js +1 -1
  21. package/dist/esm/lib/runner/ExecutionRuntime.js +1 -1
  22. package/dist/esm/types/index.d.ts +4 -0
  23. package/dist/esm/types/lib/builder/FlowChartBuilder.d.ts +17 -10
  24. package/dist/esm/types/lib/builder/types.d.ts +6 -6
  25. package/dist/esm/types/lib/contract/defineContract.d.ts +18 -0
  26. package/dist/esm/types/lib/contract/index.d.ts +14 -0
  27. package/dist/esm/types/lib/contract/openapi.d.ts +12 -0
  28. package/dist/esm/types/lib/contract/schema.d.ts +14 -0
  29. package/dist/esm/types/lib/contract/types.d.ts +94 -0
  30. package/dist/esm/types/lib/engine/graph/StageNode.d.ts +0 -2
  31. package/dist/esm/types/lib/engine/narrative/ControlFlowNarrativeGenerator.d.ts +6 -6
  32. package/dist/esm/types/lib/engine/narrative/types.d.ts +6 -6
  33. package/dist/esm/types/lib/engine/types.d.ts +0 -1
  34. package/dist/esm/types/lib/runner/ExecutionRuntime.d.ts +0 -1
  35. package/dist/index.js +12 -2
  36. package/dist/lib/builder/FlowChartBuilder.js +72 -91
  37. package/dist/lib/builder/types.js +1 -1
  38. package/dist/lib/contract/defineContract.js +36 -0
  39. package/dist/lib/contract/index.js +26 -0
  40. package/dist/lib/contract/openapi.js +124 -0
  41. package/dist/lib/contract/schema.js +205 -0
  42. package/dist/lib/contract/types.js +10 -0
  43. package/dist/lib/engine/graph/StageNode.js +1 -1
  44. package/dist/lib/engine/handlers/ChildrenExecutor.js +5 -5
  45. package/dist/lib/engine/handlers/ContinuationResolver.js +6 -6
  46. package/dist/lib/engine/handlers/DeciderHandler.js +4 -4
  47. package/dist/lib/engine/handlers/NodeResolver.js +1 -2
  48. package/dist/lib/engine/handlers/RuntimeStructureManager.js +1 -2
  49. package/dist/lib/engine/handlers/SelectorHandler.js +6 -6
  50. package/dist/lib/engine/narrative/ControlFlowNarrativeGenerator.js +13 -18
  51. package/dist/lib/engine/narrative/types.js +1 -1
  52. package/dist/lib/engine/traversal/FlowchartTraverser.js +10 -11
  53. package/dist/lib/engine/types.js +1 -1
  54. package/dist/lib/runner/ExecutionRuntime.js +1 -1
  55. package/dist/types/index.d.ts +4 -0
  56. package/dist/types/lib/builder/FlowChartBuilder.d.ts +17 -10
  57. package/dist/types/lib/builder/types.d.ts +6 -6
  58. package/dist/types/lib/contract/defineContract.d.ts +18 -0
  59. package/dist/types/lib/contract/index.d.ts +14 -0
  60. package/dist/types/lib/contract/openapi.d.ts +12 -0
  61. package/dist/types/lib/contract/schema.d.ts +14 -0
  62. package/dist/types/lib/contract/types.d.ts +94 -0
  63. package/dist/types/lib/engine/graph/StageNode.d.ts +0 -2
  64. package/dist/types/lib/engine/narrative/ControlFlowNarrativeGenerator.d.ts +6 -6
  65. package/dist/types/lib/engine/narrative/types.d.ts +6 -6
  66. package/dist/types/lib/engine/types.d.ts +0 -1
  67. package/dist/types/lib/runner/ExecutionRuntime.d.ts +0 -1
  68. package/package.json +1 -1
package/README.md CHANGED
@@ -21,9 +21,48 @@ FootPrint is a runtime for building **flowchart pipelines** where each node is j
21
21
  npm install footprintjs
22
22
  ```
23
23
 
24
+ ## Quick Start
25
+
26
+ ```typescript
27
+ import { flowChart, FlowChartExecutor, ScopeFacade, toScopeFactory } from 'footprintjs';
28
+
29
+ const chart = flowChart('Greet', (scope) => {
30
+ scope.setValue('name', 'Alice');
31
+ })
32
+ .addFunction('Personalize', (scope) => {
33
+ const name = scope.getValue('name');
34
+ scope.setValue('message', `Hello, ${name}!`);
35
+ })
36
+ .setEnableNarrative()
37
+ .build();
38
+
39
+ const executor = new FlowChartExecutor(chart, toScopeFactory(ScopeFacade));
40
+ const result = await executor.run();
41
+
42
+ console.log(executor.getNarrative());
43
+ // Stage 1: The process began with Greet.
44
+ // Step 1: Write name = "Alice"
45
+ // Stage 2: Next, it moved on to Personalize.
46
+ // Step 1: Read name = "Alice"
47
+ // Step 2: Write message = "Hello, Alice!"
48
+ ```
49
+
50
+ > **[Try it in the browser](https://footprintjs.github.io/footprint-playground/)** — no install needed
51
+ >
52
+ > **[Browse 20+ examples](https://github.com/footprintjs/footPrint-samples)** — features, flowchart patterns, and a full loan underwriting demo
53
+
24
54
  ---
25
55
 
26
- ## Why causal traces?
56
+ ## Why FootPrint?
57
+
58
+ | | Without FootPrint | With FootPrint |
59
+ |---|---|---|
60
+ | **LLM explains a decision** | Reconstruct from scattered logs; expensive, slow, hallucination-prone | Read the causal trace; cheap model, fewer tokens, zero hallucination |
61
+ | **Tool descriptions** | Write and maintain them by hand | Auto-generated from the flowchart structure |
62
+ | **Debugging** | `console.log` + guesswork | Time-travel replay to any stage |
63
+ | **State management** | Global/manual, race-prone | Transactional scope with atomic commits |
64
+
65
+ ### Example: Loan rejection
27
66
 
28
67
  A loan application pipeline rejects Bob. The user asks: **"Why was I rejected?"**
29
68
 
@@ -69,86 +108,81 @@ No one wrote those trace sentences. Stage functions just read and write scope &m
69
108
 
70
109
  ```typescript
71
110
  import {
72
- FlowChartBuilder, FlowChartExecutor, ScopeFacade, toScopeFactory,
111
+ flowChart, FlowChartExecutor, ScopeFacade, toScopeFactory,
73
112
  } from 'footprintjs';
74
113
 
75
- // ── The application data ──────────────────────────────────────────────
76
-
77
- const app = {
78
- applicantName: 'Bob',
79
- annualIncome: 42_000,
80
- monthlyDebts: 2_100,
81
- creditScore: 580,
82
- employmentType: 'self-employed',
83
- employmentYears: 1,
84
- };
85
-
86
- // ── Stage functions: just do the work, no descriptions needed ──────────
114
+ // ── Stage functions: just read and write scope ─────────────────────────
87
115
 
88
116
  const receiveApplication = (scope: ScopeFacade) => {
89
- scope.setValue('app', app);
117
+ scope.setValue('app', {
118
+ applicantName: 'Bob',
119
+ annualIncome: 42_000,
120
+ monthlyDebts: 2_100,
121
+ creditScore: 580,
122
+ employmentType: 'self-employed',
123
+ employmentYears: 1,
124
+ });
90
125
  };
91
126
 
92
127
  const pullCreditReport = (scope: ScopeFacade) => {
93
128
  const { creditScore } = scope.getValue('app') as any;
94
- const tier = creditScore >= 740 ? 'excellent' : creditScore >= 670 ? 'good'
95
- : creditScore >= 580 ? 'fair' : 'poor';
129
+ const tier = creditScore >= 740 ? 'excellent'
130
+ : creditScore >= 670 ? 'good'
131
+ : creditScore >= 580 ? 'fair' : 'poor';
132
+
96
133
  scope.setValue('creditTier', tier);
97
134
  scope.setValue('creditFlags', tier === 'fair' ? ['below-average credit'] : []);
98
135
  };
99
136
 
100
137
  const calculateDTI = (scope: ScopeFacade) => {
101
138
  const { annualIncome, monthlyDebts } = scope.getValue('app') as any;
102
- const dtiRatio = Math.round((monthlyDebts / (annualIncome / 12)) * 100) / 100;
103
- scope.setValue('dtiRatio', dtiRatio);
104
- scope.setValue('dtiPercent', Math.round(dtiRatio * 100));
105
- scope.setValue('dtiStatus', dtiRatio > 0.43 ? 'excessive' : 'healthy');
106
- scope.setValue('dtiFlags',
107
- dtiRatio > 0.43 ? [`DTI at ${Math.round(dtiRatio * 100)}% exceeds 43%`] : []);
139
+ const ratio = Math.round((monthlyDebts / (annualIncome / 12)) * 100) / 100;
140
+
141
+ scope.setValue('dtiRatio', ratio);
142
+ scope.setValue('dtiFlags', ratio > 0.43 ? [`DTI at ${Math.round(ratio * 100)}% exceeds 43%`] : []);
108
143
  };
109
144
 
110
145
  const verifyEmployment = (scope: ScopeFacade) => {
111
146
  const { employmentType, employmentYears } = scope.getValue('app') as any;
112
147
  const verified = employmentType !== 'self-employed' || employmentYears >= 2;
148
+
113
149
  scope.setValue('employmentVerified', verified);
114
- scope.setValue('employmentFlags',
115
- !verified ? [`${employmentType}, ${employmentYears}yr < 2yr minimum`] : []);
150
+ scope.setValue('employmentFlags', !verified
151
+ ? [`${employmentType}, ${employmentYears}yr < 2yr minimum`] : []);
116
152
  };
117
153
 
118
154
  const assessRisk = (scope: ScopeFacade) => {
119
- const creditTier = scope.getValue('creditTier') as string;
120
- const dtiStatus = scope.getValue('dtiStatus') as string;
155
+ const tier = scope.getValue('creditTier') as string;
156
+ const ratio = scope.getValue('dtiRatio') as number;
121
157
  const verified = scope.getValue('employmentVerified') as boolean;
122
- const riskTier = (!verified || dtiStatus === 'excessive' || creditTier === 'poor')
123
- ? 'high' : 'low';
124
- scope.setValue('riskTier', riskTier);
125
- scope.setValue('riskFactors', [/* collected flags */]);
158
+
159
+ scope.setValue('riskTier', (!verified || ratio > 0.43 || tier === 'poor') ? 'high' : 'low');
126
160
  };
127
161
 
162
+ // Deciders return a branch ID — the only stage that needs a return value
128
163
  const loanDecider = (scope: ScopeFacade): string => {
129
164
  const tier = scope.getValue('riskTier') as string;
130
- return tier === 'low' ? 'approved' : tier === 'high' ? 'rejected' : 'manual-review';
165
+ if (tier === 'low') return 'approved';
166
+ if (tier === 'high') return 'rejected';
167
+ return 'manual-review';
131
168
  };
132
169
 
133
- // ── Build the flow ─────────────────────────────────────────────────────
170
+ // ── Build Run → Narrative (D3-style chaining) ──────────────────────
134
171
 
135
- const chart = new FlowChartBuilder()
172
+ const chart = flowChart('ReceiveApplication', receiveApplication)
136
173
  .setEnableNarrative()
137
- .start('ReceiveApplication', receiveApplication)
138
174
  .addFunction('PullCreditReport', pullCreditReport)
139
175
  .addFunction('CalculateDTI', calculateDTI)
140
176
  .addFunction('VerifyEmployment', verifyEmployment)
141
177
  .addFunction('AssessRisk', assessRisk)
142
178
  .addDeciderFunction('LoanDecision', loanDecider as any)
143
- .addFunctionBranch('approved', 'ApproveApplication', () => {})
144
- .addFunctionBranch('rejected', 'RejectApplication', () => {})
179
+ .addFunctionBranch('approved', 'Approve', () => {})
180
+ .addFunctionBranch('rejected', 'Reject', () => {})
145
181
  .addFunctionBranch('manual-review', 'ManualReview', () => {})
146
182
  .setDefault('manual-review')
147
183
  .end()
148
184
  .build();
149
185
 
150
- // ── Run and get the narrative ──────────────────────────────────────────
151
-
152
186
  const executor = new FlowChartExecutor(chart, toScopeFactory(ScopeFacade));
153
187
  await executor.run();
154
188
 
@@ -647,9 +681,70 @@ Measured on Node v22, Apple Silicon. Run `npm run bench` to reproduce.
647
681
 
648
682
  ---
649
683
 
684
+ ## Contract & OpenAPI
685
+
686
+ Define I/O schemas on your flowchart and auto-generate OpenAPI 3.1 specs:
687
+
688
+ ```typescript
689
+ import { flowChart, defineContract } from 'footprintjs';
690
+ import { z } from 'zod'; // optional — raw JSON Schema also works
691
+
692
+ const chart = flowChart('ProcessLoan', receiveFn)
693
+ .addFunction('Assess', assessFn)
694
+ .addDeciderFunction('Decide', deciderFn)
695
+ .addFunctionBranch('approved', 'Approve', approveFn)
696
+ .addFunctionBranch('rejected', 'Reject', rejectFn)
697
+ .end()
698
+ .build();
699
+
700
+ // Define the contract — accepts Zod or raw JSON Schema
701
+ const contract = defineContract(chart, {
702
+ inputSchema: z.object({
703
+ applicantName: z.string(),
704
+ creditScore: z.number(),
705
+ }),
706
+ outputSchema: z.object({
707
+ decision: z.enum(['approved', 'rejected']),
708
+ reason: z.string(),
709
+ }),
710
+ outputMapper: (scope) => ({
711
+ decision: scope.decision as string,
712
+ reason: scope.reason as string,
713
+ }),
714
+ });
715
+
716
+ // Auto-generate OpenAPI 3.1 spec
717
+ const spec = contract.toOpenAPI({ version: '1.0.0', basePath: '/api' });
718
+ // → { openapi: '3.1.0', paths: { '/api/processloan': { post: { ... } } }, ... }
719
+ ```
720
+
721
+ Schemas can also be set at build time:
722
+
723
+ ```typescript
724
+ const chart = flowChart('Greet', greetFn)
725
+ .setInputSchema(z.object({ name: z.string() }))
726
+ .setOutputSchema(z.object({ greeting: z.string() }))
727
+ .setOutputMapper((scope) => ({ greeting: scope.message as string }))
728
+ .build();
729
+ ```
730
+
731
+ Zod is an **optional peer dependency** — zero bundle impact if not used. Pass raw JSON Schema instead:
732
+
733
+ ```typescript
734
+ const contract = defineContract(chart, {
735
+ inputSchema: {
736
+ type: 'object',
737
+ properties: { name: { type: 'string' } },
738
+ required: ['name'],
739
+ },
740
+ });
741
+ ```
742
+
743
+ ---
744
+
650
745
  ## Architecture
651
746
 
652
- FootPrint is five independent libraries, each usable standalone:
747
+ FootPrint is six independent libraries, each usable standalone:
653
748
 
654
749
  ```
655
750
  src/lib/
@@ -657,7 +752,8 @@ src/lib/
657
752
  ├── builder/ Fluent flowchart DSL (FlowChartBuilder, DeciderList, SelectorFnList)
658
753
  ├── scope/ Scope facades, recorders, protection, Zod integration
659
754
  ├── engine/ DFS traversal, handlers, narrative generators
660
- └── runner/ Execution convenience (FlowChartExecutor, ExecutionRuntime)
755
+ ├── runner/ Execution convenience (FlowChartExecutor, ExecutionRuntime)
756
+ └── contract/ I/O schemas, Zod→JSON Schema, OpenAPI 3.1 generation
661
757
  ```
662
758
 
663
759
  ---
package/dist/esm/index.js CHANGED
@@ -24,4 +24,10 @@ export { NarrativeRecorder } from './lib/scope';
24
24
  // Zod-based scope definitions
25
25
  export { defineScopeFromZod } from './lib/scope';
26
26
  export { CombinedNarrativeBuilder } from './lib/engine';
27
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7OztHQVNHO0FBT0gsT0FBTyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU1RCwrRUFBK0U7QUFDL0UsdUNBQXVDO0FBQ3ZDLCtFQUErRTtBQUUvRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFakQsK0VBQStFO0FBQy9FLDBDQUEwQztBQUMxQywrRUFBK0U7QUFFL0UsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUUxQyxZQUFZO0FBQ1osT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUtoRCw4QkFBOEI7QUFDOUIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBT2pELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRm9vdFByaW50IOKAlCBQdWJsaWMgQVBJXG4gKlxuICogQ29ubmVjdGVkIGNhdXNhbCB0cmFjZSBsaWJyYXJ5IGZvciBMTE0gcGlwZWxpbmVzLlxuICogQnVpbGRzIGZsb3djaGFydHMsIGV4ZWN1dGVzIHRoZW0gdmlhIERGUyB0cmF2ZXJzYWwsIGFuZCBjYXB0dXJlc1xuICogZXZlcnkgc3RhZ2UncyBjb250ZXh0IChzdGF0ZSwgZGVjaXNpb25zLCBlcnJvcnMpIGluIGFuIGF1ZGl0YWJsZSB0cmFjZS5cbiAqXG4gKiBGb3IgYWR2YW5jZWQvaW50ZXJuYWwgQVBJcyAobWVtb3J5IHByaW1pdGl2ZXMsIGVuZ2luZSBoYW5kbGVycywgcHJvdmlkZXJzKSxcbiAqIGltcG9ydCBmcm9tICdmb290cHJpbnQvYWR2YW5jZWQnLlxuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEJ1aWxkZXIg4oCUIEZsb3djaGFydCBjb25zdHJ1Y3Rpb25cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IHR5cGUgeyBGbG93Q2hhcnQsIFBpcGVsaW5lU3RhZ2VGdW5jdGlvbiBhcyBTdGFnZUhhbmRsZXIsIFN0cmVhbUhhbmRsZXJzIH0gZnJvbSAnLi9saWIvYnVpbGRlcic7XG5leHBvcnQgeyBmbG93Q2hhcnQsIEZsb3dDaGFydEJ1aWxkZXIgfSBmcm9tICcuL2xpYi9idWlsZGVyJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUnVubmVyIOKAlCBFeGVjdXRpb24gY29udmVuaWVuY2UgbGF5ZXJcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IHsgRmxvd0NoYXJ0RXhlY3V0b3IgfSBmcm9tICcuL2xpYi9ydW5uZXInO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBTY29wZSDigJQgUGVyLXN0YWdlIGZhY2FkZXMgYW5kIHJlY29yZGVyc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgeyBTY29wZUZhY2FkZSB9IGZyb20gJy4vbGliL3Njb3BlJztcblxuLy8gUmVjb3JkZXJzXG5leHBvcnQgeyBNZXRyaWNSZWNvcmRlciB9IGZyb20gJy4vbGliL3Njb3BlJztcbmV4cG9ydCB7IERlYnVnUmVjb3JkZXIgfSBmcm9tICcuL2xpYi9zY29wZSc7XG5leHBvcnQgeyBOYXJyYXRpdmVSZWNvcmRlciB9IGZyb20gJy4vbGliL3Njb3BlJztcblxuLy8gUmVjb3JkZXIgaW50ZXJmYWNlIGFuZCBjb3JlIGV2ZW50IHR5cGVzIChuZWVkZWQgdG8gaW1wbGVtZW50IGN1c3RvbSBSZWNvcmRlcilcbmV4cG9ydCB0eXBlIHsgQ29tbWl0RXZlbnQsIEVycm9yRXZlbnQsIFJlYWRFdmVudCwgUmVjb3JkZXIsIFdyaXRlRXZlbnQgfSBmcm9tICcuL2xpYi9zY29wZSc7XG5cbi8vIFpvZC1iYXNlZCBzY29wZSBkZWZpbml0aW9uc1xuZXhwb3J0IHsgZGVmaW5lU2NvcGVGcm9tWm9kIH0gZnJvbSAnLi9saWIvc2NvcGUnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFbmdpbmUg4oCUIE5hcnJhdGl2ZSAoY29tbW9ubHkgdXNlZClcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IHR5cGUgeyBDb21iaW5lZE5hcnJhdGl2ZUVudHJ5IH0gZnJvbSAnLi9saWIvZW5naW5lJztcbmV4cG9ydCB7IENvbWJpbmVkTmFycmF0aXZlQnVpbGRlciB9IGZyb20gJy4vbGliL2VuZ2luZSc7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIE1lbW9yeSDigJQgU2NvcGVGYWN0b3J5IHR5cGUgKG5lZWRlZCBmb3IgRmxvd0NoYXJ0RXhlY3V0b3IgY29uc3RydWN0b3IpXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCB0eXBlIHsgUnVuT3B0aW9ucyB9IGZyb20gJy4vbGliL2VuZ2luZSc7XG5leHBvcnQgdHlwZSB7IFNjb3BlRmFjdG9yeSB9IGZyb20gJy4vbGliL21lbW9yeSc7XG4iXX0=
27
+ // ============================================================================
28
+ // Contract — I/O boundary, schemas, and OpenAPI generation
29
+ // ============================================================================
30
+ export { defineContract } from './lib/contract';
31
+ export { normalizeSchema, zodToJsonSchema } from './lib/contract';
32
+ export { generateOpenAPI } from './lib/contract';
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7OztHQVNHO0FBT0gsT0FBTyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU1RCwrRUFBK0U7QUFDL0UsdUNBQXVDO0FBQ3ZDLCtFQUErRTtBQUUvRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFakQsK0VBQStFO0FBQy9FLDBDQUEwQztBQUMxQywrRUFBK0U7QUFFL0UsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUUxQyxZQUFZO0FBQ1osT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUtoRCw4QkFBOEI7QUFDOUIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBT2pELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQVN4RCwrRUFBK0U7QUFDL0UsMkRBQTJEO0FBQzNELCtFQUErRTtBQUUvRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEZvb3RQcmludCDigJQgUHVibGljIEFQSVxuICpcbiAqIENvbm5lY3RlZCBjYXVzYWwgdHJhY2UgbGlicmFyeSBmb3IgTExNIHBpcGVsaW5lcy5cbiAqIEJ1aWxkcyBmbG93Y2hhcnRzLCBleGVjdXRlcyB0aGVtIHZpYSBERlMgdHJhdmVyc2FsLCBhbmQgY2FwdHVyZXNcbiAqIGV2ZXJ5IHN0YWdlJ3MgY29udGV4dCAoc3RhdGUsIGRlY2lzaW9ucywgZXJyb3JzKSBpbiBhbiBhdWRpdGFibGUgdHJhY2UuXG4gKlxuICogRm9yIGFkdmFuY2VkL2ludGVybmFsIEFQSXMgKG1lbW9yeSBwcmltaXRpdmVzLCBlbmdpbmUgaGFuZGxlcnMsIHByb3ZpZGVycyksXG4gKiBpbXBvcnQgZnJvbSAnZm9vdHByaW50L2FkdmFuY2VkJy5cbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBCdWlsZGVyIOKAlCBGbG93Y2hhcnQgY29uc3RydWN0aW9uXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCB0eXBlIHsgRmxvd0NoYXJ0LCBQaXBlbGluZVN0YWdlRnVuY3Rpb24gYXMgU3RhZ2VIYW5kbGVyLCBTdHJlYW1IYW5kbGVycyB9IGZyb20gJy4vbGliL2J1aWxkZXInO1xuZXhwb3J0IHsgZmxvd0NoYXJ0LCBGbG93Q2hhcnRCdWlsZGVyIH0gZnJvbSAnLi9saWIvYnVpbGRlcic7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFJ1bm5lciDigJQgRXhlY3V0aW9uIGNvbnZlbmllbmNlIGxheWVyXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCB7IEZsb3dDaGFydEV4ZWN1dG9yIH0gZnJvbSAnLi9saWIvcnVubmVyJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gU2NvcGUg4oCUIFBlci1zdGFnZSBmYWNhZGVzIGFuZCByZWNvcmRlcnNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IHsgU2NvcGVGYWNhZGUgfSBmcm9tICcuL2xpYi9zY29wZSc7XG5cbi8vIFJlY29yZGVyc1xuZXhwb3J0IHsgTWV0cmljUmVjb3JkZXIgfSBmcm9tICcuL2xpYi9zY29wZSc7XG5leHBvcnQgeyBEZWJ1Z1JlY29yZGVyIH0gZnJvbSAnLi9saWIvc2NvcGUnO1xuZXhwb3J0IHsgTmFycmF0aXZlUmVjb3JkZXIgfSBmcm9tICcuL2xpYi9zY29wZSc7XG5cbi8vIFJlY29yZGVyIGludGVyZmFjZSBhbmQgY29yZSBldmVudCB0eXBlcyAobmVlZGVkIHRvIGltcGxlbWVudCBjdXN0b20gUmVjb3JkZXIpXG5leHBvcnQgdHlwZSB7IENvbW1pdEV2ZW50LCBFcnJvckV2ZW50LCBSZWFkRXZlbnQsIFJlY29yZGVyLCBXcml0ZUV2ZW50IH0gZnJvbSAnLi9saWIvc2NvcGUnO1xuXG4vLyBab2QtYmFzZWQgc2NvcGUgZGVmaW5pdGlvbnNcbmV4cG9ydCB7IGRlZmluZVNjb3BlRnJvbVpvZCB9IGZyb20gJy4vbGliL3Njb3BlJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRW5naW5lIOKAlCBOYXJyYXRpdmUgKGNvbW1vbmx5IHVzZWQpXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCB0eXBlIHsgQ29tYmluZWROYXJyYXRpdmVFbnRyeSB9IGZyb20gJy4vbGliL2VuZ2luZSc7XG5leHBvcnQgeyBDb21iaW5lZE5hcnJhdGl2ZUJ1aWxkZXIgfSBmcm9tICcuL2xpYi9lbmdpbmUnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBNZW1vcnkg4oCUIFNjb3BlRmFjdG9yeSB0eXBlIChuZWVkZWQgZm9yIEZsb3dDaGFydEV4ZWN1dG9yIGNvbnN0cnVjdG9yKVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgdHlwZSB7IFJ1bk9wdGlvbnMgfSBmcm9tICcuL2xpYi9lbmdpbmUnO1xuZXhwb3J0IHR5cGUgeyBTY29wZUZhY3RvcnkgfSBmcm9tICcuL2xpYi9tZW1vcnknO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDb250cmFjdCDigJQgSS9PIGJvdW5kYXJ5LCBzY2hlbWFzLCBhbmQgT3BlbkFQSSBnZW5lcmF0aW9uXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCB7IGRlZmluZUNvbnRyYWN0IH0gZnJvbSAnLi9saWIvY29udHJhY3QnO1xuZXhwb3J0IHsgbm9ybWFsaXplU2NoZW1hLCB6b2RUb0pzb25TY2hlbWEgfSBmcm9tICcuL2xpYi9jb250cmFjdCc7XG5leHBvcnQgeyBnZW5lcmF0ZU9wZW5BUEkgfSBmcm9tICcuL2xpYi9jb250cmFjdCc7XG5leHBvcnQgdHlwZSB7XG4gIEZsb3dDaGFydENvbnRyYWN0LFxuICBGbG93Q2hhcnRDb250cmFjdE9wdGlvbnMsXG4gIEpzb25TY2hlbWEsXG4gIE9wZW5BUElPcHRpb25zLFxuICBPcGVuQVBJU3BlYyxcbn0gZnJvbSAnLi9saWIvY29udHJhY3QnO1xuIl19