@contractkit/plugin-typescript 0.22.0 → 0.23.1
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 +6 -6
- package/.turbo/turbo-test$colon$ci.log +14 -14
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/coverage/clover.xml +828 -826
- package/coverage/coverage-final.json +3 -3
- package/coverage/index.html +14 -14
- package/coverage/src/codegen-contract.ts.html +170 -167
- package/coverage/src/codegen-operation.ts.html +1 -1
- package/coverage/src/codegen-plain-types.ts.html +1 -1
- package/coverage/src/codegen-sdk.ts.html +14 -8
- package/coverage/src/index.html +19 -19
- package/coverage/src/index.ts.html +1 -1
- package/coverage/src/path-utils.ts.html +1 -1
- package/coverage/src/ts-render.ts.html +1 -1
- package/coverage/tests/helpers.ts.html +6 -6
- package/coverage/tests/index.html +1 -1
- package/dist/codegen-contract.d.ts.map +1 -1
- package/dist/codegen-sdk.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/codegen-contract.ts +2 -1
- package/src/codegen-sdk.ts +4 -2
- package/tests/codegen-contract.test.ts +15 -1
- package/tests/codegen-sdk.test.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contractkit/plugin-typescript",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.1",
|
|
4
4
|
"description": "ContractKit built-in plugin: TypeScript codegen (SDK clients, Koa routers, Zod schemas, plain types)",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Marooned Software",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"@contractkit/core": "0.17.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@repo/config-
|
|
33
|
-
"@repo/config-
|
|
32
|
+
"@repo/config-typescript": "0.1.0",
|
|
33
|
+
"@repo/config-eslint": "0.3.1"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly --declaration",
|
package/src/codegen-contract.ts
CHANGED
|
@@ -300,7 +300,8 @@ function generateSimpleModel(model: ModelNode, outPath?: string): string[] {
|
|
|
300
300
|
for (const field of model.fields) {
|
|
301
301
|
const inputKey = applyCase(field.name, inputCase);
|
|
302
302
|
const outputKey = applyCase(field.name, outputCase);
|
|
303
|
-
|
|
303
|
+
const val = field.optional ? `data.${inputKey} ?? undefined` : `data.${inputKey}`;
|
|
304
|
+
lines.push(` ${quoteKey(outputKey)}: ${val},`);
|
|
304
305
|
}
|
|
305
306
|
lines.push(`}));`);
|
|
306
307
|
// When only outputCase is set, the developer-facing type is the schema's
|
package/src/codegen-sdk.ts
CHANGED
|
@@ -138,6 +138,7 @@ export function generateSdk(root: OpRootNode, options: SdkCodegenOptions = {}):
|
|
|
138
138
|
lines.push(' public readonly status: number,');
|
|
139
139
|
lines.push(' public readonly statusText: string,');
|
|
140
140
|
lines.push(' public readonly body: unknown,');
|
|
141
|
+
lines.push(' public readonly headers: Headers,');
|
|
141
142
|
lines.push(' ) {');
|
|
142
143
|
lines.push(' super(`${status} ${statusText}`);');
|
|
143
144
|
lines.push(" this.name = 'SdkError';");
|
|
@@ -168,7 +169,7 @@ export function generateSdk(root: OpRootNode, options: SdkCodegenOptions = {}):
|
|
|
168
169
|
lines.push(' const text = await res.text();');
|
|
169
170
|
lines.push(' let body: unknown;');
|
|
170
171
|
lines.push(' try { body = JSON.parse(text); } catch { body = text; }');
|
|
171
|
-
lines.push(' throw new SdkError(res.status, res.statusText, body);');
|
|
172
|
+
lines.push(' throw new SdkError(res.status, res.statusText, body, res.headers);');
|
|
172
173
|
lines.push(' }');
|
|
173
174
|
lines.push(' return res;');
|
|
174
175
|
lines.push(' };');
|
|
@@ -885,6 +886,7 @@ export function generateSdkOptions(): string {
|
|
|
885
886
|
' public readonly status: number,',
|
|
886
887
|
' public readonly statusText: string,',
|
|
887
888
|
' public readonly body: unknown,',
|
|
889
|
+
' public readonly headers: Headers,',
|
|
888
890
|
' ) {',
|
|
889
891
|
' super(`${status} ${statusText}`);',
|
|
890
892
|
" this.name = 'SdkError';",
|
|
@@ -931,7 +933,7 @@ export function generateSdkOptions(): string {
|
|
|
931
933
|
' const text = await res.text();',
|
|
932
934
|
' let body: unknown;',
|
|
933
935
|
' try { body = JSON.parse(text); } catch { body = text; }',
|
|
934
|
-
' throw new SdkError(res.status, res.statusText, body);',
|
|
936
|
+
' throw new SdkError(res.status, res.statusText, body, res.headers);',
|
|
935
937
|
' }',
|
|
936
938
|
' return res;',
|
|
937
939
|
' };',
|
|
@@ -1060,9 +1060,23 @@ describe('generateContract', () => {
|
|
|
1060
1060
|
/export const Child = z\.strictObject\(\{[\s\S]*grant_type:[\s\S]*client_id:[\s\S]*client_secret:[\s\S]*\}\)\.transform/,
|
|
1061
1061
|
);
|
|
1062
1062
|
expect(output).toContain('grantType: data.grant_type');
|
|
1063
|
-
expect(output).toContain('clientId: data.client_id');
|
|
1063
|
+
expect(output).toContain('clientId: data.client_id ?? undefined');
|
|
1064
1064
|
expect(output).toContain('clientSecret: data.client_secret');
|
|
1065
1065
|
expect(output).toContain('export type Child = z.output<typeof Child>');
|
|
1066
1066
|
});
|
|
1067
|
+
|
|
1068
|
+
it('input=snake: optional fields coerce null → undefined in the transform', () => {
|
|
1069
|
+
const root = contractRoot([
|
|
1070
|
+
model(
|
|
1071
|
+
'User',
|
|
1072
|
+
[field('firstName', scalarType('string')), field('clientId', scalarType('uuid'), { optional: true })],
|
|
1073
|
+
{ inputCase: 'snake' },
|
|
1074
|
+
),
|
|
1075
|
+
]);
|
|
1076
|
+
const output = generateContract(root);
|
|
1077
|
+
expect(output).toContain('client_id: z.uuid().nullish()');
|
|
1078
|
+
expect(output).toContain('firstName: data.first_name,');
|
|
1079
|
+
expect(output).toContain('clientId: data.client_id ?? undefined,');
|
|
1080
|
+
});
|
|
1067
1081
|
});
|
|
1068
1082
|
});
|
|
@@ -648,6 +648,8 @@ describe('generateSdk', () => {
|
|
|
648
648
|
expect(out).toContain('headers?:');
|
|
649
649
|
expect(out).toContain('fetch?: SdkFetch');
|
|
650
650
|
expect(out).toContain('export class SdkError extends Error');
|
|
651
|
+
expect(out).toContain('public readonly headers: Headers');
|
|
652
|
+
expect(out).toContain('throw new SdkError(res.status, res.statusText, body, res.headers)');
|
|
651
653
|
});
|
|
652
654
|
});
|
|
653
655
|
|
|
@@ -756,7 +758,8 @@ describe('generateSdkOptions', () => {
|
|
|
756
758
|
expect(out).toContain('export class SdkError extends Error');
|
|
757
759
|
expect(out).toContain('public readonly status: number');
|
|
758
760
|
expect(out).toContain('public readonly body: unknown');
|
|
759
|
-
expect(out).toContain('
|
|
761
|
+
expect(out).toContain('public readonly headers: Headers');
|
|
762
|
+
expect(out).toContain('throw new SdkError(res.status, res.statusText, body, res.headers)');
|
|
760
763
|
expect(out).toContain('export type SdkFetch');
|
|
761
764
|
expect(out).toContain('export function createSdkFetch(options: SdkOptions): SdkFetch');
|
|
762
765
|
expect(out).toContain('requestIdFactory ?? (() => crypto.randomUUID())');
|