@ovotech/avro-ts
Advanced tools
+32
-2
@@ -1,2 +0,29 @@ | ||
| import { RecordType } from './types'; | ||
| import { Schema, schema } from 'avsc'; | ||
| import * as ts from 'typescript'; | ||
| export interface Registry { | ||
| [key: string]: ts.InterfaceDeclaration; | ||
| } | ||
| export interface Context { | ||
| registry: Registry; | ||
| root: boolean; | ||
| namespace?: string; | ||
| namespaces: { | ||
| [key: string]: ts.TypeReferenceNode; | ||
| }; | ||
| logicalTypes: { | ||
| [key: string]: ts.TypeReferenceNode; | ||
| }; | ||
| } | ||
| export interface Result<TsType = ts.TypeNode> { | ||
| type: TsType; | ||
| context: Context; | ||
| } | ||
| export declare type Convert<TType = Schema> = (context: Context, type: TType) => Result<any>; | ||
| export declare const result: <TsType = ts.TypeNode>(context: Context, type: TsType) => Result<TsType>; | ||
| export declare const mapContext: <T = any, TsType = ts.TypeNode>(context: Context, items: T[], callbackfn: (context: Context, item: T) => Result<TsType>) => { | ||
| items: TsType[]; | ||
| context: Context; | ||
| }; | ||
| export declare const withEntry: (context: Context, entry: ts.InterfaceDeclaration) => Context; | ||
| export declare const withNamespace: (context: Context, record: schema.RecordType) => Context; | ||
| export interface State { | ||
@@ -11,2 +38,5 @@ output: string[]; | ||
| } | ||
| export declare function avroTs(recordType: RecordType, logicalTypes?: State['logicalTypes']): string; | ||
| export declare const printAstNode: (node: Result<ts.TypeNode>) => string; | ||
| export declare function avroTs(recordType: schema.RecordType, logicalTypes?: { | ||
| [key: string]: string; | ||
| }): string; |
+117
-88
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| function avroTs(recordType, logicalTypes = {}) { | ||
| const state = { output: [], repository: {}, logicalTypes }; | ||
| convertRecord(recordType, state); | ||
| return state.output.join('\n'); | ||
| } | ||
| exports.avroTs = avroTs; | ||
| function convertRecord(recordType, state, namespace) { | ||
| if (recordType.namespace) { | ||
| state.repository[fullyQualifiedName(recordType)] = recordType.name; | ||
| const ts = require("typescript"); | ||
| exports.result = (context, type) => ({ | ||
| context, | ||
| type, | ||
| }); | ||
| exports.mapContext = (context, items, callbackfn) => items.reduce((all, item) => { | ||
| const current = callbackfn(all.context, item); | ||
| return { | ||
| items: [...all.items, current.type], | ||
| context: current.context, | ||
| }; | ||
| }, { items: [], context }); | ||
| exports.withEntry = (context, entry) => ({ | ||
| ...context, | ||
| registry: { ...context.registry, [entry.name.text]: entry }, | ||
| }); | ||
| exports.withNamespace = (context, record) => ({ | ||
| ...context, | ||
| namespace: record.namespace, | ||
| namespaces: { | ||
| ...context.namespaces, | ||
| [fullyQualifiedName(context, record)]: ts.createTypeReferenceNode(record.name, undefined), | ||
| }, | ||
| }); | ||
| const docToJSDoc = (doc) => `*\n${doc | ||
| .split('\n') | ||
| .map(line => ` * ${line}`) | ||
| .join('\n')}\n `; | ||
| const convertRecord = (context, type) => { | ||
| const namespaceContext = type.namespace ? exports.withNamespace(context, type) : context; | ||
| const fields = exports.mapContext({ ...namespaceContext, root: false }, type.fields, (fieldContext, fieldType) => { | ||
| const field = convertType(fieldContext, fieldType.type); | ||
| const prop = ts.createPropertySignature(undefined, fieldType.name, isOptional(fieldType.type) ? ts.createToken(ts.SyntaxKind.QuestionToken) : undefined, field.type, undefined); | ||
| const propWithDoc = fieldType.doc | ||
| ? ts.addSyntheticLeadingComment(prop, ts.SyntaxKind.MultiLineCommentTrivia, docToJSDoc(fieldType.doc), true) | ||
| : prop; | ||
| return exports.result(field.context, propWithDoc); | ||
| }); | ||
| const interfaceType = ts.createInterfaceDeclaration(undefined, [ts.createToken(ts.SyntaxKind.ExportKeyword)], type.name, undefined, undefined, fields.items); | ||
| if (context.root) { | ||
| return exports.result(fields.context, interfaceType); | ||
| } | ||
| let buffer = `export interface ${recordType.name} {\n`; | ||
| for (const field of recordType.fields) { | ||
| buffer += convertFieldDec(field, state, recordType.namespace) + '\n'; | ||
| else { | ||
| return exports.result(exports.withEntry(fields.context, interfaceType), ts.createTypeReferenceNode(type.name, undefined)); | ||
| } | ||
| buffer += '}\n'; | ||
| state.output.push(buffer); | ||
| return recordType.name; | ||
| } | ||
| function convertFieldDec(field, state, namespace) { | ||
| const optional = isOptional(field.type) ? '?' : ''; | ||
| const doc = field.doc ? `/**\n * ${field.doc}\n */\n` : ''; | ||
| return indent(`${doc}${field.name}${optional}: ${convertType(field.type, state, namespace)};`); | ||
| } | ||
| function convertType(type, state, namespace) { | ||
| }; | ||
| const convertType = (context, type) => { | ||
| if (typeof type === 'string') { | ||
| return convertPredefinedType(type, state) || convertPrimitive(type) || type; | ||
| return convertPredefinedType(context, type); | ||
| } | ||
| else if (type instanceof Array) { | ||
| return convertArrayType(type, state, namespace); | ||
| else if (Array.isArray(type)) { | ||
| return convertArrayType(context, type); | ||
| } | ||
| else if (isLogicalType(type)) { | ||
| return convertLogicalType(type, state); | ||
| return convertLogicalType(context, type); | ||
| } | ||
| else if (isRecordType(type)) { | ||
| return convertRecord(type, state, namespace); | ||
| return convertRecord(context, type); | ||
| } | ||
| else if (isArrayType(type)) { | ||
| return convertType(type.items, state, namespace) + '[]'; | ||
| const itemType = convertType(context, type.items); | ||
| return exports.result(itemType.context, ts.createArrayTypeNode(itemType.type)); | ||
| } | ||
| else if (isMapType(type)) { | ||
| return convertMapType(type, state, namespace); | ||
| return convertMapType(context, type); | ||
| } | ||
| else if (isEnumType(type)) { | ||
| return convertEnum(type); | ||
| return convertEnum(context, type); | ||
| } | ||
@@ -51,4 +75,4 @@ else { | ||
| } | ||
| } | ||
| function convertPrimitive(avroType) { | ||
| }; | ||
| const convertPrimitive = (context, avroType) => { | ||
| switch (avroType) { | ||
@@ -59,58 +83,49 @@ case 'long': | ||
| case 'float': | ||
| return 'number'; | ||
| return exports.result(context, ts.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)); | ||
| case 'bytes': | ||
| return 'Buffer'; | ||
| return exports.result(context, ts.createTypeReferenceNode('Buffer', undefined)); | ||
| case 'null': | ||
| return 'null'; | ||
| return exports.result(context, ts.createNull()); | ||
| case 'boolean': | ||
| return 'boolean'; | ||
| return exports.result(context, ts.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword)); | ||
| case 'string': | ||
| return 'string'; | ||
| return exports.result(context, ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)); | ||
| default: | ||
| return 'any'; | ||
| return exports.result(context, ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)); | ||
| } | ||
| } | ||
| function convertEnum(enumType) { | ||
| return enumType.symbols.map(symbol => JSON.stringify(symbol)).join(' | '); | ||
| } | ||
| function convertLogicalType(type, state) { | ||
| return state.logicalTypes[type.logicalType] || convertPrimitive(type.type); | ||
| } | ||
| function convertPredefinedType(type, state) { | ||
| return state.repository[type]; | ||
| } | ||
| function convertArrayType(type, state, namespace) { | ||
| return type | ||
| .map(t => { | ||
| if (typeof t === 'object' && !(t instanceof Array) && isRecordType(t)) { | ||
| return `{ '${fullyQualifiedName(t, namespace)}' : ${convertType(t, state, namespace)} }`; | ||
| }; | ||
| const convertEnum = (context, enumType) => exports.result(context, ts.createUnionTypeNode(enumType.symbols.map(symbol => ts.createLiteralTypeNode(ts.createLiteral(symbol))))); | ||
| const convertLogicalType = (context, type) => context.logicalTypes[type.logicalType] | ||
| ? exports.result(context, context.logicalTypes[type.logicalType]) | ||
| : convertPrimitive(context, type.type); | ||
| const convertPredefinedType = (context, type) => context.namespaces[type] ? exports.result(context, context.namespaces[type]) : convertPrimitive(context, type); | ||
| const convertArrayType = (context, type) => { | ||
| const map = exports.mapContext(context, type, (itemContext, item) => { | ||
| if (typeof item === 'object' && !Array.isArray(item) && isRecordType(item)) { | ||
| const itemType = convertType(itemContext, item); | ||
| return exports.result(itemType.context, ts.createTypeLiteralNode([ | ||
| ts.createPropertySignature(undefined, ts.createStringLiteral(fullyQualifiedName(context, item)), undefined, itemType.type, undefined), | ||
| ])); | ||
| } | ||
| else { | ||
| return convertType(t, state); | ||
| return convertType(itemContext, item); | ||
| } | ||
| }) | ||
| .join(' | '); | ||
| } | ||
| function convertMapType(type, state, namespace) { | ||
| return `{ [index:string]:${convertType(type.values, state, namespace)} }`; | ||
| } | ||
| function isRecordType(type) { | ||
| return type.type === 'record'; | ||
| } | ||
| function isArrayType(type) { | ||
| return type.type === 'array'; | ||
| } | ||
| function isMapType(type) { | ||
| return type.type === 'map'; | ||
| } | ||
| function isEnumType(type) { | ||
| return type.type === 'enum'; | ||
| } | ||
| function isLogicalType(type) { | ||
| return 'logicalType' in type; | ||
| } | ||
| function isUnion(type) { | ||
| return type instanceof Array; | ||
| } | ||
| function isOptional(type) { | ||
| }); | ||
| return exports.result(map.context, ts.createUnionTypeNode(map.items)); | ||
| }; | ||
| const convertMapType = (context, type) => { | ||
| const map = convertType(context, type.values); | ||
| return exports.result(map.context, ts.createTypeLiteralNode([ | ||
| ts.createIndexSignature(undefined, undefined, [ | ||
| ts.createParameter(undefined, undefined, undefined, 'index', undefined, ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), undefined), | ||
| ], map.type), | ||
| ])); | ||
| }; | ||
| const isRecordType = (type) => typeof type === 'object' && 'type' in type && type.type === 'record'; | ||
| const isArrayType = (type) => typeof type === 'object' && 'type' in type && type.type === 'array'; | ||
| const isMapType = (type) => typeof type === 'object' && 'type' in type && type.type === 'map'; | ||
| const isEnumType = (type) => typeof type === 'object' && 'type' in type && type.type === 'enum'; | ||
| const isLogicalType = (type) => typeof type === 'object' && 'logicalType' in type; | ||
| const isUnion = (type) => typeof type === 'object' && Array.isArray(type); | ||
| const isOptional = (type) => { | ||
| if (isUnion(type)) { | ||
@@ -123,13 +138,27 @@ const t1 = type[0]; | ||
| return false; | ||
| } | ||
| function fullyQualifiedName(type, namespace) { | ||
| const currentNamespace = type.namespace || namespace; | ||
| }; | ||
| const fullyQualifiedName = (context, type) => { | ||
| const currentNamespace = type.namespace || context.namespace; | ||
| return currentNamespace ? `${currentNamespace}.${type.name}` : type.name; | ||
| }; | ||
| exports.printAstNode = (node) => { | ||
| const resultFile = ts.createSourceFile('someFileName.ts', '', ts.ScriptTarget.Latest); | ||
| const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); | ||
| const entries = Object.values(node.context.registry); | ||
| const fullSourceFile = ts.updateSourceFileNode(resultFile, entries); | ||
| return [ | ||
| printer.printNode(ts.EmitHint.Unspecified, node.type, fullSourceFile), | ||
| ...entries.map(entry => printer.printNode(ts.EmitHint.Unspecified, entry, fullSourceFile)), | ||
| ].join('\n\n'); | ||
| }; | ||
| function avroTs(recordType, logicalTypes = {}) { | ||
| const context = { | ||
| root: true, | ||
| registry: {}, | ||
| namespaces: {}, | ||
| logicalTypes: Object.entries(logicalTypes).reduce((all, [name, type]) => ({ ...all, [name]: ts.createTypeReferenceNode(type, undefined) }), {}), | ||
| }; | ||
| return exports.printAstNode(convertRecord(context, recordType)); | ||
| } | ||
| function indent(text, prefix = ' ') { | ||
| return text | ||
| .split('\n') | ||
| .map(row => prefix + row) | ||
| .join('\n'); | ||
| } | ||
| exports.avroTs = avroTs; | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} |
+6
-4
| { | ||
| "name": "@ovotech/avro-ts", | ||
| "description": "Convert avro schemas into typescript interfaces", | ||
| "version": "1.0.1", | ||
| "version": "1.1.0", | ||
| "main": "dist/index.js", | ||
@@ -28,4 +28,3 @@ "source": "src/index.ts", | ||
| "tslint": "^5.14.0", | ||
| "tslint-config-prettier": "^1.18.0", | ||
| "typescript": "^3.3.4000" | ||
| "tslint-config-prettier": "^1.18.0" | ||
| }, | ||
@@ -35,3 +34,6 @@ "jest": { | ||
| }, | ||
| "gitHead": "f68210eef2100a3c8e844c843e8745aa450cb62d" | ||
| "dependencies": { | ||
| "typescript": "^3.4.3" | ||
| }, | ||
| "gitHead": "33fbdb8057520cf1d3f229059a0231089febbaee" | ||
| } |
+3
-2
@@ -5,3 +5,3 @@ # Avro TS | ||
| It consists of a very quick sequential, functional parser. No dependencies. | ||
| It consists of a very quick sequential, functional parser. Uses typescript's compiler api to convert avro to typescript AST, and pretty prints the results. No dependencies apart from typescript. | ||
@@ -17,5 +17,6 @@ ### Using | ||
| ```typescript | ||
| import { schema } from 'avsc'; | ||
| import { avroTs } from '@ovotech/avro-ts'; | ||
| const avro: RecordType = JSON.parse(String(readFileSync(join(__dirname, 'avro', file)))); | ||
| const avro: schema.RecordType = JSON.parse(String(readFileSync(join(__dirname, 'avro', file)))); | ||
| const ts = avroTs(avro, { 'timestamp-millis': 'string', date: 'string' }); | ||
@@ -22,0 +23,0 @@ |
+208
-92
@@ -1,3 +0,58 @@ | ||
| import { ArrayType, BaseType, EnumType, Field, LogicalType, MapType, NamedType, RecordType, Type } from './types'; | ||
| import { Schema, schema } from 'avsc'; | ||
| import * as ts from 'typescript'; | ||
| export interface Registry { | ||
| [key: string]: ts.InterfaceDeclaration; | ||
| } | ||
| export interface Context { | ||
| registry: Registry; | ||
| root: boolean; | ||
| namespace?: string; | ||
| namespaces: { [key: string]: ts.TypeReferenceNode }; | ||
| logicalTypes: { [key: string]: ts.TypeReferenceNode }; | ||
| } | ||
| export interface Result<TsType = ts.TypeNode> { | ||
| type: TsType; | ||
| context: Context; | ||
| } | ||
| export type Convert<TType = Schema> = (context: Context, type: TType) => Result<any>; | ||
| export const result = <TsType = ts.TypeNode>(context: Context, type: TsType): Result<TsType> => ({ | ||
| context, | ||
| type, | ||
| }); | ||
| export const mapContext = <T = any, TsType = ts.TypeNode>( | ||
| context: Context, | ||
| items: T[], | ||
| callbackfn: (context: Context, item: T) => Result<TsType>, | ||
| ) => | ||
| items.reduce<{ items: TsType[]; context: Context }>( | ||
| (all, item) => { | ||
| const current = callbackfn(all.context, item); | ||
| return { | ||
| items: [...all.items, current.type], | ||
| context: current.context, | ||
| }; | ||
| }, | ||
| { items: [], context }, | ||
| ); | ||
| export const withEntry = (context: Context, entry: ts.InterfaceDeclaration): Context => ({ | ||
| ...context, | ||
| registry: { ...context.registry, [entry.name.text]: entry }, | ||
| }); | ||
| export const withNamespace = (context: Context, record: schema.RecordType): Context => ({ | ||
| ...context, | ||
| namespace: record.namespace, | ||
| namespaces: { | ||
| ...context.namespaces, | ||
| [fullyQualifiedName(context, record)]: ts.createTypeReferenceNode(record.name, undefined), | ||
| }, | ||
| }); | ||
| export interface State { | ||
@@ -9,51 +64,66 @@ output: string[]; | ||
| export function avroTs(recordType: RecordType, logicalTypes: State['logicalTypes'] = {}): string { | ||
| const state: State = { output: [], repository: {}, logicalTypes }; | ||
| const docToJSDoc = (doc: string) => | ||
| `*\n${doc | ||
| .split('\n') | ||
| .map(line => ` * ${line}`) | ||
| .join('\n')}\n `; | ||
| convertRecord(recordType, state); | ||
| return state.output.join('\n'); | ||
| } | ||
| const convertRecord: Convert<schema.RecordType> = (context, type) => { | ||
| const namespaceContext = type.namespace ? withNamespace(context, type) : context; | ||
| function convertRecord(recordType: RecordType, state: State, namespace?: string): string { | ||
| if (recordType.namespace) { | ||
| state.repository[fullyQualifiedName(recordType)] = recordType.name; | ||
| } | ||
| const fields = mapContext({ ...namespaceContext, root: false }, type.fields, (fieldContext, fieldType) => { | ||
| const field = convertType(fieldContext, fieldType.type); | ||
| const prop = ts.createPropertySignature( | ||
| undefined, | ||
| fieldType.name, | ||
| isOptional(fieldType.type) ? ts.createToken(ts.SyntaxKind.QuestionToken) : undefined, | ||
| field.type, | ||
| undefined, | ||
| ); | ||
| let buffer = `export interface ${recordType.name} {\n`; | ||
| for (const field of recordType.fields) { | ||
| buffer += convertFieldDec(field, state, recordType.namespace) + '\n'; | ||
| } | ||
| buffer += '}\n'; | ||
| state.output.push(buffer); | ||
| return recordType.name; | ||
| } | ||
| const propWithDoc = fieldType.doc | ||
| ? ts.addSyntheticLeadingComment(prop, ts.SyntaxKind.MultiLineCommentTrivia, docToJSDoc(fieldType.doc), true) | ||
| : prop; | ||
| function convertFieldDec(field: Field, state: State, namespace?: string): string { | ||
| const optional = isOptional(field.type) ? '?' : ''; | ||
| const doc = field.doc ? `/**\n * ${field.doc}\n */\n` : ''; | ||
| return result(field.context, propWithDoc); | ||
| }); | ||
| return indent(`${doc}${field.name}${optional}: ${convertType(field.type, state, namespace)};`); | ||
| } | ||
| const interfaceType = ts.createInterfaceDeclaration( | ||
| undefined, | ||
| [ts.createToken(ts.SyntaxKind.ExportKeyword)], | ||
| type.name, | ||
| undefined, | ||
| undefined, | ||
| fields.items, | ||
| ); | ||
| function convertType(type: Type, state: State, namespace?: string): string { | ||
| if (context.root) { | ||
| return result(fields.context, interfaceType); | ||
| } else { | ||
| return result(withEntry(fields.context, interfaceType), ts.createTypeReferenceNode(type.name, undefined)); | ||
| } | ||
| }; | ||
| const convertType: Convert = (context, type) => { | ||
| if (typeof type === 'string') { | ||
| return convertPredefinedType(type, state) || convertPrimitive(type) || type; | ||
| } else if (type instanceof Array) { | ||
| return convertArrayType(type, state, namespace); | ||
| return convertPredefinedType(context, type); | ||
| } else if (Array.isArray(type)) { | ||
| return convertArrayType(context, type); | ||
| } else if (isLogicalType(type)) { | ||
| return convertLogicalType(type, state); | ||
| return convertLogicalType(context, type); | ||
| } else if (isRecordType(type)) { | ||
| return convertRecord(type, state, namespace); | ||
| return convertRecord(context, type); | ||
| } else if (isArrayType(type)) { | ||
| return convertType(type.items, state, namespace) + '[]'; | ||
| const itemType = convertType(context, type.items); | ||
| return result(itemType.context, ts.createArrayTypeNode(itemType.type)); | ||
| } else if (isMapType(type)) { | ||
| return convertMapType(type, state, namespace); | ||
| return convertMapType(context, type); | ||
| } else if (isEnumType(type)) { | ||
| return convertEnum(type); | ||
| return convertEnum(context, type); | ||
| } else { | ||
| throw new Error(`Cannot work out type ${type}`); | ||
| } | ||
| } | ||
| }; | ||
| function convertPrimitive(avroType: string): string { | ||
| const convertPrimitive: Convert = (context, avroType) => { | ||
| switch (avroType) { | ||
@@ -64,69 +134,96 @@ case 'long': | ||
| case 'float': | ||
| return 'number'; | ||
| return result(context, ts.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)); | ||
| case 'bytes': | ||
| return 'Buffer'; | ||
| return result(context, ts.createTypeReferenceNode('Buffer', undefined)); | ||
| case 'null': | ||
| return 'null'; | ||
| return result(context, ts.createNull()); | ||
| case 'boolean': | ||
| return 'boolean'; | ||
| return result(context, ts.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword)); | ||
| case 'string': | ||
| return 'string'; | ||
| return result(context, ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)); | ||
| default: | ||
| return 'any'; | ||
| return result(context, ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)); | ||
| } | ||
| } | ||
| }; | ||
| function convertEnum(enumType: EnumType): string { | ||
| return enumType.symbols.map(symbol => JSON.stringify(symbol)).join(' | '); | ||
| } | ||
| const convertEnum: Convert<schema.EnumType> = (context, enumType) => | ||
| result( | ||
| context, | ||
| ts.createUnionTypeNode(enumType.symbols.map(symbol => ts.createLiteralTypeNode(ts.createLiteral(symbol)))), | ||
| ); | ||
| function convertLogicalType(type: LogicalType, state: State): string { | ||
| return state.logicalTypes[type.logicalType] || convertPrimitive(type.type); | ||
| } | ||
| const convertLogicalType: Convert<schema.LogicalType> = (context, type) => | ||
| context.logicalTypes[type.logicalType] | ||
| ? result(context, context.logicalTypes[type.logicalType]) | ||
| : convertPrimitive(context, type.type); | ||
| function convertPredefinedType(type: string, state: State): string { | ||
| return state.repository[type]; | ||
| } | ||
| const convertPredefinedType: Convert<string> = (context, type) => | ||
| context.namespaces[type] ? result(context, context.namespaces[type]) : convertPrimitive(context, type); | ||
| function convertArrayType(type: Type[], state: State, namespace?: string): string { | ||
| return type | ||
| .map(t => { | ||
| if (typeof t === 'object' && !(t instanceof Array) && isRecordType(t)) { | ||
| return `{ '${fullyQualifiedName(t, namespace)}' : ${convertType(t, state, namespace)} }`; | ||
| } else { | ||
| return convertType(t, state); | ||
| } | ||
| }) | ||
| .join(' | '); | ||
| } | ||
| const convertArrayType: Convert<any[]> = (context, type) => { | ||
| const map = mapContext(context, type, (itemContext, item) => { | ||
| if (typeof item === 'object' && !Array.isArray(item) && isRecordType(item)) { | ||
| const itemType = convertType(itemContext, item); | ||
| return result( | ||
| itemType.context, | ||
| ts.createTypeLiteralNode([ | ||
| ts.createPropertySignature( | ||
| undefined, | ||
| ts.createStringLiteral(fullyQualifiedName(context, item)), | ||
| undefined, | ||
| itemType.type, | ||
| undefined, | ||
| ), | ||
| ]), | ||
| ); | ||
| } else { | ||
| return convertType(itemContext, item); | ||
| } | ||
| }); | ||
| function convertMapType(type: MapType, state: State, namespace?: string): string { | ||
| return `{ [index:string]:${convertType(type.values, state, namespace)} }`; | ||
| } | ||
| return result(map.context, ts.createUnionTypeNode(map.items)); | ||
| }; | ||
| function isRecordType(type: BaseType): type is RecordType { | ||
| return type.type === 'record'; | ||
| } | ||
| const convertMapType: Convert<schema.MapType> = (context, type) => { | ||
| const map = convertType(context, type.values); | ||
| return result( | ||
| map.context, | ||
| ts.createTypeLiteralNode([ | ||
| ts.createIndexSignature( | ||
| undefined, | ||
| undefined, | ||
| [ | ||
| ts.createParameter( | ||
| undefined, | ||
| undefined, | ||
| undefined, | ||
| 'index', | ||
| undefined, | ||
| ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), | ||
| undefined, | ||
| ), | ||
| ], | ||
| map.type, | ||
| ), | ||
| ]), | ||
| ); | ||
| }; | ||
| function isArrayType(type: BaseType): type is ArrayType { | ||
| return type.type === 'array'; | ||
| } | ||
| const isRecordType = (type: Schema): type is schema.RecordType => | ||
| typeof type === 'object' && 'type' in type && type.type === 'record'; | ||
| function isMapType(type: BaseType): type is MapType { | ||
| return type.type === 'map'; | ||
| } | ||
| const isArrayType = (type: Schema): type is schema.ArrayType => | ||
| typeof type === 'object' && 'type' in type && type.type === 'array'; | ||
| function isEnumType(type: BaseType): type is EnumType { | ||
| return type.type === 'enum'; | ||
| } | ||
| const isMapType = (type: Schema): type is schema.MapType => | ||
| typeof type === 'object' && 'type' in type && type.type === 'map'; | ||
| function isLogicalType(type: BaseType): type is LogicalType { | ||
| return 'logicalType' in type; | ||
| } | ||
| const isEnumType = (type: Schema): type is schema.EnumType => | ||
| typeof type === 'object' && 'type' in type && type.type === 'enum'; | ||
| function isUnion(type: Type): type is NamedType[] { | ||
| return type instanceof Array; | ||
| } | ||
| const isLogicalType = (type: Schema): type is schema.LogicalType => typeof type === 'object' && 'logicalType' in type; | ||
| function isOptional(type: Type): boolean { | ||
| const isUnion = (type: Schema): type is schema.NamedType[] => typeof type === 'object' && Array.isArray(type); | ||
| const isOptional = (type: Schema): boolean => { | ||
| if (isUnion(type)) { | ||
@@ -139,14 +236,33 @@ const t1 = type[0]; | ||
| return false; | ||
| } | ||
| }; | ||
| function fullyQualifiedName(type: RecordType, namespace?: string) { | ||
| const currentNamespace = type.namespace || namespace; | ||
| const fullyQualifiedName = (context: Context, type: schema.RecordType) => { | ||
| const currentNamespace = type.namespace || context.namespace; | ||
| return currentNamespace ? `${currentNamespace}.${type.name}` : type.name; | ||
| } | ||
| }; | ||
| function indent(text: string, prefix = ' ') { | ||
| return text | ||
| .split('\n') | ||
| .map(row => prefix + row) | ||
| .join('\n'); | ||
| export const printAstNode = (node: Result): string => { | ||
| const resultFile = ts.createSourceFile('someFileName.ts', '', ts.ScriptTarget.Latest); | ||
| const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); | ||
| const entries = Object.values(node.context.registry); | ||
| const fullSourceFile = ts.updateSourceFileNode(resultFile, entries); | ||
| return [ | ||
| printer.printNode(ts.EmitHint.Unspecified, node.type, fullSourceFile), | ||
| ...entries.map(entry => printer.printNode(ts.EmitHint.Unspecified, entry, fullSourceFile)), | ||
| ].join('\n\n'); | ||
| }; | ||
| export function avroTs(recordType: schema.RecordType, logicalTypes: { [key: string]: string } = {}): string { | ||
| const context: Context = { | ||
| root: true, | ||
| registry: {}, | ||
| namespaces: {}, | ||
| logicalTypes: Object.entries(logicalTypes).reduce( | ||
| (all, [name, type]) => ({ ...all, [name]: ts.createTypeReferenceNode(type, undefined) }), | ||
| {}, | ||
| ), | ||
| }; | ||
| return printAstNode(convertRecord(context, recordType)); | ||
| } |
| /**** Contains the Interfaces and Type Guards for Avro schema */ | ||
| export declare type Type = NameOrType | NameOrType[]; | ||
| export declare type NameOrType = TypeNames | RecordType | ArrayType | NamedType | LogicalType; | ||
| export declare type TypeNames = 'record' | 'array' | 'null' | 'map' | string; | ||
| export interface Field { | ||
| name: string; | ||
| type: Type; | ||
| doc?: string; | ||
| default?: string | number | null | boolean; | ||
| } | ||
| export interface BaseType { | ||
| type: TypeNames; | ||
| } | ||
| export interface RecordType extends BaseType { | ||
| type: 'record'; | ||
| name: string; | ||
| namespace?: string; | ||
| doc?: string; | ||
| fields: Field[]; | ||
| } | ||
| export interface ArrayType extends BaseType { | ||
| type: 'array'; | ||
| items: Type; | ||
| } | ||
| export interface MapType extends BaseType { | ||
| type: 'map'; | ||
| values: Type; | ||
| } | ||
| export interface EnumType extends BaseType { | ||
| type: 'enum'; | ||
| name: string; | ||
| symbols: string[]; | ||
| } | ||
| export interface LogicalType extends BaseType { | ||
| logicalType: 'string'; | ||
| } | ||
| export interface NamedType extends BaseType { | ||
| type: string; | ||
| } |
| "use strict"; | ||
| /**** Contains the Interfaces and Type Guards for Avro schema */ | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| //# sourceMappingURL=types.js.map |
| {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,gEAAgE"} |
-48
| /**** Contains the Interfaces and Type Guards for Avro schema */ | ||
| export type Type = NameOrType | NameOrType[]; | ||
| export type NameOrType = TypeNames | RecordType | ArrayType | NamedType | LogicalType; | ||
| export type TypeNames = 'record' | 'array' | 'null' | 'map' | string; | ||
| export interface Field { | ||
| name: string; | ||
| type: Type; | ||
| doc?: string; | ||
| default?: string | number | null | boolean; | ||
| } | ||
| export interface BaseType { | ||
| type: TypeNames; | ||
| } | ||
| export interface RecordType extends BaseType { | ||
| type: 'record'; | ||
| name: string; | ||
| namespace?: string; | ||
| doc?: string; | ||
| fields: Field[]; | ||
| } | ||
| export interface ArrayType extends BaseType { | ||
| type: 'array'; | ||
| items: Type; | ||
| } | ||
| export interface MapType extends BaseType { | ||
| type: 'map'; | ||
| values: Type; | ||
| } | ||
| export interface EnumType extends BaseType { | ||
| type: 'enum'; | ||
| name: string; | ||
| symbols: string[]; | ||
| } | ||
| export interface LogicalType extends BaseType { | ||
| logicalType: 'string'; | ||
| } | ||
| export interface NamedType extends BaseType { | ||
| type: string; | ||
| } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
28597
55.77%9
-10%430
23.21%66
1.54%1
Infinity%7
-36.36%1
Infinity%+ Added
+ Added