import {Command} from "https://deno.land/x/cliffy@v0.25.7/command/mod.ts"; import {concat, partial} from 'https://deno.land/x/lodash@4.17.15-es/lodash.js'; import {dirname, join} from "https://deno.land/std@0.171.0/path/mod.ts"; import avro from "npm:avro-js@1.11.1"; enum AvroPrimitives { Null = "null", Boolean = "boolean", Int = "int", Long = "long", Float = "float", Double = "double", Bytes = "bytes", String = "string" } interface AvroRecordField { name: string, doc?: string, default?: any, type: AvroTypes, } interface AvroRecord { name: string, type: "record", namespace?: string, doc?: string, aliases?: string[] fields: AvroRecordField[] } interface AvroEnum { name: string, namespace?: string, aliases?: string[], type: "enum", symbols: string[], } type AvroUnion = AvroTypes[]; type AvroTypes = AvroPrimitives | AvroRecord | AvroUnion | AvroEnum; const CacheChequeEvent: AvroRecord = { name: "CacheChequeEvent", type: "record", fields: [ {name: "account", type: AvroPrimitives.Long}, ] } const BogusEvent: AvroRecord = { name: "BogusEvent", type: "record", fields: [ {name: "account", type: AvroPrimitives.Long}, {name: "foo", type: AvroPrimitives.Long}, ] } const allEvents: AvroRecord[] = [CacheChequeEvent, BogusEvent] const eventTypes: AvroEnum = { type: "enum", name: "EventType", symbols: allEvents.map(x => x.name), } const LedgerEventsSchema: AvroRecord = { name: "LedgerEvent", type: "record", fields: [ {name: "event_type", type: eventTypes}, {name: "event", type: allEvents}, ] }; interface CliOptions { dry: boolean, output: string, } type Serializer = (rec: AvroRecord) => Promise; function getOutputFileName(outputDir: string, rec: AvroRecord): string { return join(outputDir, rec.name + '.json'); } async function drySerializer(outputDir: string, rec: AvroRecord): Promise { console.log(getOutputFileName(outputDir, rec) + " : " + JSON.stringify(rec)); } async function fileSerializer(outputDir: string, rec: AvroRecord): Promise { const outputFile = getOutputFileName(outputDir, rec); await Deno.mkdir(dirname(outputFile), { recursive: true }); await Deno.writeTextFile(outputFile, JSON.stringify(rec, null, 4)); } function getSerializer(dry: boolean, outputDir: string): Serializer { return dry ? partial(drySerializer, outputDir) : partial(fileSerializer, outputDir); } async function buildSchemata(options: CliOptions): Promise { const serializer = getSerializer(options.dry, options.output); for (const e of concat([], allEvents, LedgerEventsSchema, eventTypes)) { await serializer(e); } } async function testShit(): Promise { const type = avro.parse(CacheChequeEvent); const buff = await Deno.readFile("/tmp/foo.data"); console.log(buff); console.log(type.fromBuffer(buff)); } async function createMockData(): Promise { const type = avro.parse( { "name": "CacheChequeEvent", "type": "record", "fields": [ { "name": "account", "type": "long" } ] } ); const e = { account: 666 // event_type: CacheChequeEvent.name, // event: {CacheChequeEvent: {account: 1788301184}} }; const encoder = avro.createFileEncoder("/tmp/foo.data", type); encoder.write({account: 666}); encoder.end(); return; // const file = await Deno.open("/tmp/foo.data", {write: true, create: true}); // for (let i = 0; i < 1; i++) { // await Deno.write(file.rid, type.toBuffer(e).buffer); // } } function buildSchemataCommand() { return new Command() .description("Build the avro schemata") .option("--dry [value:boolean]", "Do not output any files", { default: false, }) .option("--output [value:file]", "directory to output schemata", { default: '.', }) .action(buildSchemata); } function buildMockEventsCommand() { return new Command() .description("Generate mock data") .option("--output [value:file]", "output data file", { default: '.', }) .action(createMockData); } function buildTestingCommand() { return new Command() .description("Test mock data") .action(testShit); } await new Command() .name("ledger-avro-schemata-builder") .version("0.1.0") .command('build-schema', buildSchemataCommand()) .command('create-mock-data', buildMockEventsCommand()) .command('testing', buildTestingCommand()) .parse(Deno.args);