Skip to content

Commit

Permalink
Nullable wrapped unions (#115)
Browse files Browse the repository at this point in the history
* Nullable wrapped unions

Should fix #108

* Fix typescript types
  • Loading branch information
ivank authored Mar 31, 2022
1 parent 2f39619 commit 192599e
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 22 deletions.
4 changes: 2 additions & 2 deletions packages/avro-ts-cli/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@ovotech/avro-ts-cli",
"description": "A cli to convert avro schemas into typescript interfaces",
"version": "3.4.8",
"version": "3.4.9",
"main": "dist/index.js",
"source": "src/index.ts",
"types": "dist/index.d.ts",
Expand All @@ -25,7 +25,7 @@
"preset": "../../jest.json"
},
"dependencies": {
"@ovotech/avro-ts": "^6.0.6",
"@ovotech/avro-ts": "^6.0.7",
"ansi-regex": "^5.0.0",
"chalk": "^4.1.0",
"commander": "^7.1.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/avro-ts/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@ovotech/avro-ts",
"description": "Convert avro schemas into typescript interfaces",
"version": "6.0.6",
"version": "6.0.7",
"main": "dist/index.js",
"source": "src/index.ts",
"types": "dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/avro-ts/src/types/union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Convert } from '../types';
import { Type, mapWithContext, document } from '@ovotech/ts-compose';
import { convertType } from '../convert';

export const isUnion = (type: Schema): type is schema.NamedType[] =>
export const isUnion = (type: Schema): type is (schema.NamedType | schema.PrimitiveType)[] =>
typeof type === 'object' && Array.isArray(type);

export const convertUnionType: Convert<schema.DefinedType[]> = (context, schema) => {
Expand Down
32 changes: 18 additions & 14 deletions packages/avro-ts/src/types/wrapped-union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,32 @@ import { fullName } from '../helpers';
const resolveItem = (context: Context, item: Schema): Schema =>
typeof item === 'string' && context.refs?.[item] ? context.refs?.[item] : item;

export const isWrappedUnion = (type: Schema, context: Context): type is schema.RecordType[] =>
type WrappedUnionItem = schema.RecordType | 'null';

export const isWrappedUnion = (type: Schema, context: Context): type is WrappedUnionItem[] =>
isUnion(type) &&
type.length > 1 &&
type.every((item) => isRecordType(resolveItem(context, item)));
type.filter((item) => item !== 'null').length > 1 &&
type.filter((item) => item !== 'null').every((item) => isRecordType(resolveItem(context, item)));

export const convertWrappedUnionType: Convert<schema.RecordType[]> = (context, schema) => {
const resolved = schema.map((item) => resolveItem(context, item) as schema.RecordType);
export const convertWrappedUnionType: Convert<WrappedUnionItem[]> = (context, schema) => {
const resolved = schema.map((item) => resolveItem(context, item) as WrappedUnionItem);

const map = mapWithContext(context, resolved, (itemContext, item) => {
const converted = convertType(itemContext, item);

return {
context: { ...converted.context, namespace: context.namespace },
type: Type.TypeLiteral({
props: resolved.map((schemaItem) => {
return Type.Prop({
name: fullName(context, schemaItem),
isOptional: schemaItem.name === item.name ? false : true,
type: schemaItem.name === item.name ? converted.type : Type.Never,
});
}),
}),
type: isRecordType(item)
? Type.TypeLiteral({
props: resolved.filter(isRecordType).map((schemaItem) => {
return Type.Prop({
name: fullName(context, schemaItem),
isOptional: schemaItem.name === item.name ? false : true,
type: schemaItem.name === item.name ? converted.type : Type.Never,
});
}),
})
: Type.Null,
};
});

Expand Down
148 changes: 144 additions & 4 deletions packages/avro-ts/test/__snapshots__/integration.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,19 @@ export namespace ComExampleKafkaComms {
/**
* Default: null
*/
recipient: null | ComExampleKafkaCommsRecipient.Email | ComExampleKafkaCommsRecipient.Phone | ComExampleKafkaCommsRecipient.Postal;
recipient: null | {
\\"com.example.kafka.comms.Recipient.Email\\": ComExampleKafkaCommsRecipient.Email;
\\"com.example.kafka.comms.Recipient.Phone\\"?: never;
\\"com.example.kafka.comms.Recipient.Postal\\"?: never;
} | {
\\"com.example.kafka.comms.Recipient.Email\\"?: never;
\\"com.example.kafka.comms.Recipient.Phone\\": ComExampleKafkaCommsRecipient.Phone;
\\"com.example.kafka.comms.Recipient.Postal\\"?: never;
} | {
\\"com.example.kafka.comms.Recipient.Email\\"?: never;
\\"com.example.kafka.comms.Recipient.Phone\\"?: never;
\\"com.example.kafka.comms.Recipient.Postal\\": ComExampleKafkaCommsRecipient.Postal;
};
/**
* Default: null
*/
Expand All @@ -356,7 +368,19 @@ export namespace ComExampleKafkaComms {
/**
* Default: null
*/
content: null | ComExampleKafkaCommsContent.Email | ComExampleKafkaCommsContent.Sms | ComExampleKafkaCommsContent.Print;
content: null | {
\\"com.example.kafka.comms.Content.Email\\": ComExampleKafkaCommsContent.Email;
\\"com.example.kafka.comms.Content.Sms\\"?: never;
\\"com.example.kafka.comms.Content.Print\\"?: never;
} | {
\\"com.example.kafka.comms.Content.Email\\"?: never;
\\"com.example.kafka.comms.Content.Sms\\": ComExampleKafkaCommsContent.Sms;
\\"com.example.kafka.comms.Content.Print\\"?: never;
} | {
\\"com.example.kafka.comms.Content.Email\\"?: never;
\\"com.example.kafka.comms.Content.Sms\\"?: never;
\\"com.example.kafka.comms.Content.Print\\": ComExampleKafkaCommsContent.Print;
};
/**
* Default: []
*/
Expand Down Expand Up @@ -551,7 +575,19 @@ export namespace ComExampleKafkaComms {
/**
* Default: null
*/
recipient?: null | ComExampleKafkaCommsRecipient.Email | ComExampleKafkaCommsRecipient.Phone | ComExampleKafkaCommsRecipient.Postal;
recipient?: null | {
\\"com.example.kafka.comms.Recipient.Email\\": ComExampleKafkaCommsRecipient.Email;
\\"com.example.kafka.comms.Recipient.Phone\\"?: never;
\\"com.example.kafka.comms.Recipient.Postal\\"?: never;
} | {
\\"com.example.kafka.comms.Recipient.Email\\"?: never;
\\"com.example.kafka.comms.Recipient.Phone\\": ComExampleKafkaCommsRecipient.Phone;
\\"com.example.kafka.comms.Recipient.Postal\\"?: never;
} | {
\\"com.example.kafka.comms.Recipient.Email\\"?: never;
\\"com.example.kafka.comms.Recipient.Phone\\"?: never;
\\"com.example.kafka.comms.Recipient.Postal\\": ComExampleKafkaCommsRecipient.Postal;
};
/**
* Default: null
*/
Expand All @@ -563,7 +599,19 @@ export namespace ComExampleKafkaComms {
/**
* Default: null
*/
content?: null | ComExampleKafkaCommsContent.Email | ComExampleKafkaCommsContent.Sms | ComExampleKafkaCommsContent.Print;
content?: null | {
\\"com.example.kafka.comms.Content.Email\\": ComExampleKafkaCommsContent.Email;
\\"com.example.kafka.comms.Content.Sms\\"?: never;
\\"com.example.kafka.comms.Content.Print\\"?: never;
} | {
\\"com.example.kafka.comms.Content.Email\\"?: never;
\\"com.example.kafka.comms.Content.Sms\\": ComExampleKafkaCommsContent.Sms;
\\"com.example.kafka.comms.Content.Print\\"?: never;
} | {
\\"com.example.kafka.comms.Content.Email\\"?: never;
\\"com.example.kafka.comms.Content.Sms\\"?: never;
\\"com.example.kafka.comms.Content.Print\\": ComExampleKafkaCommsContent.Print;
};
/**
* Default: []
*/
Expand Down Expand Up @@ -1802,6 +1850,98 @@ export namespace ComExampleAvro {
"
`;

exports[`Avro ts test Should convert NullableWrappedUnion.avsc successfully 1`] = `
"/* eslint-disable @typescript-eslint/no-namespace */
export type Test = ComOvoenergyKafkaTestEvent.Test;
export namespace ComOvoenergyKafkaTestEvent {
export const AName = \\"com.ovoenergy.kafka.test.event.A\\";
export interface A {
foo: string;
bar: string;
}
export const BName = \\"com.ovoenergy.kafka.test.event.B\\";
export interface B {
/**
* Default: true
*/
fuzz: boolean;
}
export const CName = \\"com.ovoenergy.kafka.test.event.C\\";
export interface C {
foo: string;
bar: string;
}
export const TestName = \\"com.ovoenergy.kafka.test.event.test\\";
export interface Test {
/**
* Default: \\"null\\"
*/
event: null | {
\\"com.ovoenergy.kafka.test.event.A\\": ComOvoenergyKafkaTestEvent.A;
\\"com.ovoenergy.kafka.test.event.B\\"?: never;
\\"com.ovoenergy.kafka.test.event.C\\"?: never;
} | {
\\"com.ovoenergy.kafka.test.event.A\\"?: never;
\\"com.ovoenergy.kafka.test.event.B\\": ComOvoenergyKafkaTestEvent.B;
\\"com.ovoenergy.kafka.test.event.C\\"?: never;
} | {
\\"com.ovoenergy.kafka.test.event.A\\"?: never;
\\"com.ovoenergy.kafka.test.event.B\\"?: never;
\\"com.ovoenergy.kafka.test.event.C\\": ComOvoenergyKafkaTestEvent.C;
};
}
}
"
`;

exports[`Avro ts test Should convert NullableWrappedUnion.avsc successfully with default as optional 1`] = `
"/* eslint-disable @typescript-eslint/no-namespace */
export type Test = ComOvoenergyKafkaTestEvent.Test;
export namespace ComOvoenergyKafkaTestEvent {
export const AName = \\"com.ovoenergy.kafka.test.event.A\\";
export interface A {
foo: string;
bar: string;
}
export const BName = \\"com.ovoenergy.kafka.test.event.B\\";
export interface B {
/**
* Default: true
*/
fuzz?: boolean;
}
export const CName = \\"com.ovoenergy.kafka.test.event.C\\";
export interface C {
foo: string;
bar: string;
}
export const TestName = \\"com.ovoenergy.kafka.test.event.test\\";
export interface Test {
/**
* Default: \\"null\\"
*/
event?: null | {
\\"com.ovoenergy.kafka.test.event.A\\": ComOvoenergyKafkaTestEvent.A;
\\"com.ovoenergy.kafka.test.event.B\\"?: never;
\\"com.ovoenergy.kafka.test.event.C\\"?: never;
} | {
\\"com.ovoenergy.kafka.test.event.A\\"?: never;
\\"com.ovoenergy.kafka.test.event.B\\": ComOvoenergyKafkaTestEvent.B;
\\"com.ovoenergy.kafka.test.event.C\\"?: never;
} | {
\\"com.ovoenergy.kafka.test.event.A\\"?: never;
\\"com.ovoenergy.kafka.test.event.B\\"?: never;
\\"com.ovoenergy.kafka.test.event.C\\": ComOvoenergyKafkaTestEvent.C;
};
}
}
"
`;

exports[`Avro ts test Should convert RecordWithDefault.avsc successfully 1`] = `
"/* eslint-disable @typescript-eslint/no-namespace */
Expand Down
59 changes: 59 additions & 0 deletions packages/avro-ts/test/avro/NullableWrappedUnion.avsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"type": "record",
"name": "test",
"namespace": "com.ovoenergy.kafka.test.event",
"fields": [
{
"name": "event",
"default": "null",
"type": [
"null",
{
"type": "record",
"name": "A",
"fields": [
{
"name": "foo",
"type": "string"
},
{
"name": "bar",
"type": {
"type": "int",
"logicalType": "date"
}
}
]
},
{
"type": "record",
"name": "B",
"fields": [
{
"name": "fuzz",
"type": "boolean",
"default": true
}
]
},
{
"type": "record",
"name": "C",
"fields": [
{
"name": "foo",
"type": "string"
},
{
"name": "bar",
"type": {
"type": "int",
"logicalType": "date"
}
}
]
}
]
}
]
}

0 comments on commit 192599e

Please sign in to comment.