@contractkit/plugin-typescript 0.28.1 → 0.29.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.
- package/.turbo/turbo-build$colon$ci.log +5 -5
- package/.turbo/turbo-test$colon$ci.log +21 -19
- package/CHANGELOG.md +16 -0
- package/README.md +4 -0
- package/dist/codegen-contract.d.ts +7 -0
- package/dist/codegen-contract.d.ts.map +1 -1
- package/dist/codegen-mcp.d.ts +38 -0
- package/dist/codegen-mcp.d.ts.map +1 -0
- package/dist/codegen-operation.d.ts +42 -1
- package/dist/codegen-operation.d.ts.map +1 -1
- package/dist/codegen-plain-types.d.ts +3 -0
- package/dist/codegen-plain-types.d.ts.map +1 -1
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +686 -96
- package/dist/index.js.map +1 -1
- package/dist/ts-render.d.ts +21 -3
- package/dist/ts-render.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/codegen-contract.ts +7 -0
- package/src/codegen-mcp.ts +501 -0
- package/src/codegen-operation.ts +104 -10
- package/src/codegen-plain-types.ts +47 -22
- package/src/index.ts +175 -1
- package/src/ts-render.ts +52 -32
- package/tests/codegen-mcp.test.ts +246 -0
- package/tests/codegen-operation.test.ts +89 -0
- package/tests/codegen-plain-types.test.ts +48 -0
- package/tests/codegen-server.test.ts +37 -0
- package/tests/pipeline.test.ts +59 -0
package/tests/pipeline.test.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { parseCk, decomposeCk, validateOp, validateRefs, applyOptionsDefaults, D
|
|
|
2
2
|
import { generateContract } from '../src/codegen-contract.js';
|
|
3
3
|
import { generateOp } from '../src/codegen-operation.js';
|
|
4
4
|
import { generateSdk } from '../src/codegen-sdk.js';
|
|
5
|
+
import { generateMcpFile } from '../src/codegen-mcp.js';
|
|
5
6
|
import { SIMPLE_USER_CONTRACT, VISIBILITY_CONTRACT, INHERITANCE_CONTRACT, SIMPLE_USERS_OP, PARAMETERIZED_OP } from './helpers.js';
|
|
6
7
|
|
|
7
8
|
function compileContractSource(source: string) {
|
|
@@ -118,6 +119,64 @@ describe('OP pipeline (source -> parse -> codegen)', () => {
|
|
|
118
119
|
});
|
|
119
120
|
});
|
|
120
121
|
|
|
122
|
+
describe('MCP pipeline (source -> parse -> codegen)', () => {
|
|
123
|
+
function compileMcp(source: string, file = 'payments.ck') {
|
|
124
|
+
const diag = new DiagnosticCollector();
|
|
125
|
+
const ck = parseCk(source, file, diag);
|
|
126
|
+
const { op } = decomposeCk(ck);
|
|
127
|
+
return { output: generateMcpFile(op, { includeInternal: false }), diag };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
it('generates a tool handler from a parsed mcp block', () => {
|
|
131
|
+
const source = `\
|
|
132
|
+
operation /payments/{id}: {
|
|
133
|
+
params: { id: uuid }
|
|
134
|
+
get: {
|
|
135
|
+
mcp: {
|
|
136
|
+
title: "Get Payment"
|
|
137
|
+
description: "Fetch a payment by id."
|
|
138
|
+
hint: readOnly, idempotent, nonDestructive
|
|
139
|
+
}
|
|
140
|
+
service: PaymentsService.getById
|
|
141
|
+
response: { 200: { application/json: Payment } }
|
|
142
|
+
}
|
|
143
|
+
}`;
|
|
144
|
+
const { output, diag } = compileMcp(source);
|
|
145
|
+
expect(diag.hasErrors()).toBe(false);
|
|
146
|
+
expect(output).toContain('export class GetPaymentsByIdMcpTool implements McpToolHandler');
|
|
147
|
+
expect(output).toContain("title: 'Get Payment'");
|
|
148
|
+
expect(output).toContain('annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }');
|
|
149
|
+
expect(output).toContain('const GetPaymentsByIdArgs = z.object({ id: z.uuid() });');
|
|
150
|
+
expect(output).toContain('constructor(private readonly service: PaymentsService) {}');
|
|
151
|
+
expect(output).toContain('const result = await this.service.getById(id);');
|
|
152
|
+
expect(output).toContain('export function registerPaymentsMcpTools(map: McpToolHandlerMap, container: Container): void {');
|
|
153
|
+
expect(output).toContain("map.set('get_payments_by_id', container.get(GetPaymentsByIdMcpTool));");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('generates a tool from mcp: true with an inferred name', () => {
|
|
157
|
+
const source = `\
|
|
158
|
+
operation /payments: {
|
|
159
|
+
post: {
|
|
160
|
+
mcp: true
|
|
161
|
+
service: PaymentsService.create
|
|
162
|
+
request: { application/json: PaymentInput }
|
|
163
|
+
response: { 201: { application/json: Payment } }
|
|
164
|
+
}
|
|
165
|
+
}`;
|
|
166
|
+
const { output, diag } = compileMcp(source);
|
|
167
|
+
expect(diag.hasErrors()).toBe(false);
|
|
168
|
+
expect(output).toContain("name: 'post_payments'");
|
|
169
|
+
expect(output).toContain('const PostPaymentsArgs = z.object({ body: PaymentInput });');
|
|
170
|
+
expect(output).not.toContain('annotations:');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('emits nothing tool-like for a file with no flagged ops', () => {
|
|
174
|
+
const source = `operation /payments: { get: { response: { 200: { application/json: Payment } } } }`;
|
|
175
|
+
const { output } = compileMcp(source);
|
|
176
|
+
expect(output).not.toContain('implements McpToolHandler');
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
121
180
|
describe('undeclared path param warnings', () => {
|
|
122
181
|
it('warns when a route has path params but no params block', () => {
|
|
123
182
|
const source = `operation /users/{id}: { get: {} }`;
|