@ovotech/avro-ts
Advanced tools
Comparing version 3.0.0 to 3.1.0
@@ -7,3 +7,6 @@ import { Schema, schema } from 'avsc'; | ||
declare type UnionRegistry = { | ||
[key: string]: string[]; | ||
[key: string]: { | ||
members: string[]; | ||
namespace: string; | ||
}; | ||
}; | ||
@@ -16,3 +19,4 @@ export interface Context { | ||
unionRegistry: UnionRegistry; | ||
unionMember: boolean; | ||
recordNeedsNS: boolean; | ||
parentName?: string; | ||
namespace?: string; | ||
@@ -19,0 +23,0 @@ namespaces: { |
@@ -38,5 +38,5 @@ "use strict"; | ||
const namespaceContext = type.namespace ? exports.withNamespace(context, type) : context; | ||
const fieldContext = { ...namespaceContext, unionMember: false }; | ||
const fieldContext = { ...namespaceContext, recordNeedsNS: false }; | ||
const fields = type.fields.map(fieldType => { | ||
const field = convertType(fieldContext, fieldType.type); | ||
const field = convertType({ ...fieldContext, parentName: type.name }, fieldType.type); | ||
const prop = ts.createPropertySignature(undefined, fieldType.name, isOptional(fieldType.type) ? ts.createToken(ts.SyntaxKind.QuestionToken) : undefined, field.type, undefined); | ||
@@ -50,12 +50,13 @@ const propWithDoc = fieldType.doc | ||
const recordContext = exports.withContexts(exports.withEntry(fieldContext, interfaceType), fields.map(item => item.context)); | ||
if (context.unionMember) { | ||
if (context.recordNeedsNS) { | ||
const namespaced = fullyQualifiedName(context, type); | ||
const currentNamespace = type.namespace || context.namespace; | ||
const props = [ | ||
ts.createPropertySignature(undefined, ts.createStringLiteral(namespaced), undefined, ts.createTypeReferenceNode(type.name, undefined), undefined), | ||
]; | ||
if (currentNamespace) { | ||
props.push(...(context.unionRegistry[currentNamespace] || []) | ||
const registryKey = getUnionRegistryKey(type, context); | ||
if (registryKey) { | ||
const registryEntry = context.unionRegistry[registryKey] || {}; | ||
props.push(...(registryEntry.members || []) | ||
.filter((name) => name !== type.name) | ||
.map(name => ts.createPropertySignature(undefined, ts.createStringLiteral(`${currentNamespace}.${name}`), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword), undefined))); | ||
.map(name => ts.createPropertySignature(undefined, ts.createStringLiteral(`${registryEntry.namespace}.${name}`), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword), undefined))); | ||
} | ||
@@ -123,6 +124,9 @@ const namespacedInterfaceType = ts.createInterfaceDeclaration(undefined, [ts.createToken(ts.SyntaxKind.ExportKeyword)], `${context.namespacedPrefix}${type.name}`, undefined, undefined, props); | ||
const convertPredefinedType = (context, type) => context.namespaces[type] ? exports.result(context, context.namespaces[type]) : convertPrimitive(context, type); | ||
const recordNeedsNS = (items) => { | ||
return items.filter(item => typeof item === 'object' && !Array.isArray(item) && isRecordType(item)).length > 1; | ||
}; | ||
const convertArrayType = (context, type) => { | ||
const map = exports.mapContext(context, type, (itemContext, item) => { | ||
if (typeof item === 'object' && !Array.isArray(item) && isRecordType(item)) { | ||
return convertType({ ...itemContext, unionMember: true }, item); | ||
return convertType({ ...itemContext, recordNeedsNS: recordNeedsNS(type) }, item); | ||
} | ||
@@ -176,3 +180,3 @@ else { | ||
const logicalTypes = options.logicalTypes || {}; | ||
const isRootUnion = Array.isArray(recordType); | ||
const isRootUnion = Array.isArray(recordType) && recordNeedsNS(recordType); | ||
const context = { | ||
@@ -183,5 +187,5 @@ ...options, | ||
namespacedPrefix: options.namespacedPrefix || defaultOptions.namespacedPrefix, | ||
unionMember: isRootUnion, | ||
recordNeedsNS: isRootUnion, | ||
registry: {}, | ||
unionRegistry: buildUnionRegistry({}, recordType, { namespace: recordType.namespace, unionMember: isRootUnion }), | ||
unionRegistry: buildUnionRegistry({}, recordType, { namespace: recordType.namespace, recordNeedsNS: isRootUnion }), | ||
namespaces: {}, | ||
@@ -212,3 +216,6 @@ visitedLogicalTypes: [], | ||
function unionRegisryToNamespace(registry, namespaceName) { | ||
const names = Object.keys(registry).reduce((nodes, namespace) => nodes.concat(registry[namespace].map(name => ts.createVariableStatement([ts.createToken(ts.SyntaxKind.ExportKeyword)], ts.createVariableDeclarationList([ts.createVariableDeclaration(name, undefined, ts.createLiteral(`${namespace}.${name}`))], ts.NodeFlags.Const)))), []); | ||
const names = Object.keys(registry).reduce((nodes, key) => { | ||
const { namespace, members } = registry[key]; | ||
return nodes.concat(members.map(name => ts.createVariableStatement([ts.createToken(ts.SyntaxKind.ExportKeyword)], ts.createVariableDeclarationList([ts.createVariableDeclaration(name, undefined, ts.createLiteral(`${namespace}.${name}`))], ts.NodeFlags.Const)))); | ||
}, []); | ||
if (!names.length) { | ||
@@ -220,2 +227,8 @@ return; | ||
} | ||
const getUnionRegistryKey = (type, { parentName, namespace }) => { | ||
const currentNamespace = type.namespace || namespace; | ||
if (currentNamespace) { | ||
return parentName ? `${currentNamespace}.${parentName}` : currentNamespace; | ||
} | ||
}; | ||
function buildUnionRegistry(registry, schema, context) { | ||
@@ -226,9 +239,16 @@ if (Array.isArray(schema)) { | ||
if (isRecordParent(schema)) { | ||
return buildUnionRegistry(registry, schema.type, { ...context, unionMember: isUnionParent(schema) }); | ||
return buildUnionRegistry(registry, schema.type, { | ||
...context, | ||
recordNeedsNS: isUnionParent(schema) && recordNeedsNS(schema.type), | ||
}); | ||
} | ||
if (isRecordType(schema)) { | ||
const { name, fields } = schema; | ||
const currentNamespace = schema.namespace || context.namespace; | ||
if (currentNamespace && context.unionMember) { | ||
(registry[currentNamespace] = registry[currentNamespace] || []).push(name); | ||
const namespace = schema.namespace || context.namespace; | ||
const registryKey = getUnionRegistryKey(schema, context); | ||
if (registryKey && context.recordNeedsNS) { | ||
if (!registry[registryKey]) { | ||
registry[registryKey] = { namespace: namespace, members: [] }; | ||
} | ||
registry[registryKey].members.push(name); | ||
} | ||
@@ -240,2 +260,3 @@ fields.reduce((acc, field) => | ||
unionMember: false, | ||
parentName: schema.name, | ||
namespace: schema.namespace || context.namespace, | ||
@@ -242,0 +263,0 @@ }), registry); |
{ | ||
"name": "@ovotech/avro-ts", | ||
"description": "Convert avro schemas into typescript interfaces", | ||
"version": "3.0.0", | ||
"version": "3.1.0", | ||
"main": "dist/index.js", | ||
@@ -36,3 +36,3 @@ "source": "src/index.ts", | ||
}, | ||
"gitHead": "2a3ad08e9fb4427a9bb5f384ac66095678b7e3fe" | ||
"gitHead": "25d55039d4369fb71b8573486d2942e365f85ba5" | ||
} |
@@ -9,3 +9,6 @@ import { Schema, schema } from 'avsc'; | ||
type UnionRegistry = { | ||
[key: string]: string[]; | ||
[key: string]: { | ||
members: string[]; | ||
namespace: string; | ||
}; | ||
}; | ||
@@ -19,3 +22,4 @@ | ||
unionRegistry: UnionRegistry; | ||
unionMember: boolean; | ||
recordNeedsNS: boolean; | ||
parentName?: string; | ||
namespace?: string; | ||
@@ -32,3 +36,3 @@ namespaces: { [key: string]: ts.TypeReferenceNode }; | ||
type TypeRecordType = { type: schema.RecordType }; | ||
type TypeRecordType = { type: schema.RecordType; name: string }; | ||
@@ -96,6 +100,6 @@ export type Convert<TType = Schema> = (context: Context, type: TType) => Result<any>; | ||
const namespaceContext = type.namespace ? withNamespace(context, type) : context; | ||
const fieldContext = { ...namespaceContext, unionMember: false }; | ||
const fieldContext = { ...namespaceContext, recordNeedsNS: false }; | ||
const fields = type.fields.map(fieldType => { | ||
const field = convertType(fieldContext, fieldType.type); | ||
const field = convertType({ ...fieldContext, parentName: type.name }, fieldType.type); | ||
const prop = ts.createPropertySignature( | ||
@@ -126,5 +130,4 @@ undefined, | ||
if (context.unionMember) { | ||
if (context.recordNeedsNS) { | ||
const namespaced = fullyQualifiedName(context, type); | ||
const currentNamespace = type.namespace || context.namespace; | ||
const props = [ | ||
@@ -140,5 +143,7 @@ ts.createPropertySignature( | ||
if (currentNamespace) { | ||
const registryKey = getUnionRegistryKey(type, context); | ||
if (registryKey) { | ||
const registryEntry = context.unionRegistry[registryKey] || {}; | ||
props.push( | ||
...(context.unionRegistry[currentNamespace] || []) | ||
...(registryEntry.members || []) | ||
.filter((name: string) => name !== type.name) | ||
@@ -148,3 +153,3 @@ .map(name => | ||
undefined, | ||
ts.createStringLiteral(`${currentNamespace}.${name}`), | ||
ts.createStringLiteral(`${registryEntry.namespace}.${name}`), | ||
ts.createToken(ts.SyntaxKind.QuestionToken), | ||
@@ -233,6 +238,10 @@ ts.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword), | ||
const recordNeedsNS = (items: any[]): boolean => { | ||
return items.filter(item => typeof item === 'object' && !Array.isArray(item) && isRecordType(item)).length > 1; | ||
}; | ||
const convertArrayType: Convert<any[]> = (context, type) => { | ||
const map = mapContext(context, type, (itemContext, item) => { | ||
if (typeof item === 'object' && !Array.isArray(item) && isRecordType(item)) { | ||
return convertType({ ...itemContext, unionMember: true }, item); | ||
return convertType({ ...itemContext, recordNeedsNS: recordNeedsNS(type) }, item); | ||
} else { | ||
@@ -330,3 +339,3 @@ return convertType(itemContext, item); | ||
const logicalTypes = options.logicalTypes || {}; | ||
const isRootUnion = Array.isArray(recordType); | ||
const isRootUnion = Array.isArray(recordType) && recordNeedsNS(recordType); | ||
@@ -338,5 +347,5 @@ const context: Context = { | ||
namespacedPrefix: options.namespacedPrefix || defaultOptions.namespacedPrefix, | ||
unionMember: isRootUnion, | ||
recordNeedsNS: isRootUnion, | ||
registry: {}, | ||
unionRegistry: buildUnionRegistry({}, recordType, { namespace: recordType.namespace, unionMember: isRootUnion }), | ||
unionRegistry: buildUnionRegistry({}, recordType, { namespace: recordType.namespace, recordNeedsNS: isRootUnion }), | ||
namespaces: {}, | ||
@@ -379,17 +388,16 @@ visitedLogicalTypes: [], | ||
function unionRegisryToNamespace(registry: UnionRegistry, namespaceName: string): ts.Node | undefined { | ||
const names = Object.keys(registry).reduce<Array<ts.Statement>>( | ||
(nodes, namespace) => | ||
nodes.concat( | ||
registry[namespace].map(name => | ||
ts.createVariableStatement( | ||
[ts.createToken(ts.SyntaxKind.ExportKeyword)], | ||
ts.createVariableDeclarationList( | ||
[ts.createVariableDeclaration(name, undefined, ts.createLiteral(`${namespace}.${name}`))], | ||
ts.NodeFlags.Const, | ||
), | ||
const names = Object.keys(registry).reduce<Array<ts.Statement>>((nodes, key) => { | ||
const { namespace, members } = registry[key]; | ||
return nodes.concat( | ||
members.map(name => | ||
ts.createVariableStatement( | ||
[ts.createToken(ts.SyntaxKind.ExportKeyword)], | ||
ts.createVariableDeclarationList( | ||
[ts.createVariableDeclaration(name, undefined, ts.createLiteral(`${namespace}.${name}`))], | ||
ts.NodeFlags.Const, | ||
), | ||
), | ||
), | ||
[], | ||
); | ||
); | ||
}, []); | ||
@@ -410,6 +418,17 @@ if (!names.length) { | ||
const getUnionRegistryKey = ( | ||
type: schema.RecordType, | ||
{ parentName, namespace }: { parentName?: string; namespace?: string }, | ||
): string | undefined => { | ||
const currentNamespace = type.namespace || namespace; | ||
if (currentNamespace) { | ||
return parentName ? `${currentNamespace}.${parentName}` : currentNamespace; | ||
} | ||
}; | ||
function buildUnionRegistry( | ||
registry: UnionRegistry, | ||
schema: schema.AvroSchema, | ||
context: { namespace?: string; unionMember: boolean }, | ||
context: { parentName?: string; namespace?: string; recordNeedsNS: boolean }, | ||
): UnionRegistry { | ||
@@ -421,3 +440,6 @@ if (Array.isArray(schema)) { | ||
if (isRecordParent(schema)) { | ||
return buildUnionRegistry(registry, schema.type, { ...context, unionMember: isUnionParent(schema) }); | ||
return buildUnionRegistry(registry, schema.type, { | ||
...context, | ||
recordNeedsNS: isUnionParent(schema) && recordNeedsNS(schema.type), | ||
}); | ||
} | ||
@@ -427,5 +449,9 @@ | ||
const { name, fields } = schema; | ||
const currentNamespace = schema.namespace || context.namespace; | ||
if (currentNamespace && context.unionMember) { | ||
(registry[currentNamespace] = registry[currentNamespace] || []).push(name); | ||
const namespace = schema.namespace || context.namespace; | ||
const registryKey = getUnionRegistryKey(schema, context); | ||
if (registryKey && context.recordNeedsNS) { | ||
if (!registry[registryKey]) { | ||
registry[registryKey] = { namespace: namespace!, members: [] }; | ||
} | ||
registry[registryKey].members.push(name); | ||
} | ||
@@ -439,2 +465,3 @@ | ||
unionMember: false, | ||
parentName: schema.name, | ||
namespace: schema.namespace || context.namespace, | ||
@@ -441,0 +468,0 @@ }), |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
46712
718