Skip to content

Commit 57c8431

Browse files
authored
Merge pull request #53 from codingtools/feature/avro-support-#51
Feature/avro support #51
2 parents ca22fd3 + 3eba066 commit 57c8431

22 files changed

+437
-16
lines changed

README.md

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ $ npm install -g @codingtools/cdt
3939
$ cdt COMMAND
4040
running command...
4141
$ cdt (-v|--version|version)
42-
@codingtools/cdt/0.1.5 darwin-x64 node-v12.9.0
42+
@codingtools/cdt/0.1.6 darwin-x64 node-v12.9.0
4343
$ cdt --help [COMMAND]
4444
USAGE
4545
$ cdt COMMAND
@@ -49,6 +49,7 @@ USAGE
4949
# Commands
5050
<!-- commands -->
5151
* [`cdt autocomplete [SHELL]`](#cdt-autocomplete-shell)
52+
* [`cdt avro [COMMAND]`](#cdt-avro-command)
5253
* [`cdt bundlephobia [PACKAGE]`](#cdt-bundlephobia-package)
5354
* [`cdt crypto [STRING]`](#cdt-crypto-string)
5455
* [`cdt datetime [DATE]`](#cdt-datetime-date)
@@ -79,6 +80,23 @@ EXAMPLES
7980

8081
_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v0.1.4/src/commands/autocomplete/index.ts)_
8182

83+
## `cdt avro [COMMAND]`
84+
85+
Avro Utility command
86+
87+
```
88+
USAGE
89+
$ cdt avro [COMMAND]
90+
91+
OPTIONS
92+
-f, --file=file input file path
93+
-h, --help show CLI help
94+
-o, --output=output output file path
95+
-t, --schemaType=schemaType schema type file path
96+
```
97+
98+
_See code: [src/commands/avro.ts](https://github.com/codingtools/cdt/blob/v0.1.6/src/commands/avro.ts)_
99+
82100
## `cdt bundlephobia [PACKAGE]`
83101

84102
Find cost of adding a npm/yarn packages or all dependencies in package.json file
@@ -93,7 +111,7 @@ OPTIONS
93111
-p, --packages=packages packages for which cost is required, can pass more than one separated by space
94112
```
95113

96-
_See code: [src/commands/bundlephobia.ts](https://github.com/codingtools/cdt/blob/v0.1.5/src/commands/bundlephobia.ts)_
114+
_See code: [src/commands/bundlephobia.ts](https://github.com/codingtools/cdt/blob/v0.1.6/src/commands/bundlephobia.ts)_
97115

98116
## `cdt crypto [STRING]`
99117

@@ -113,7 +131,7 @@ OPTIONS
113131
-s, --string=string string to be encrypted/decrypted
114132
```
115133

116-
_See code: [src/commands/crypto.ts](https://github.com/codingtools/cdt/blob/v0.1.5/src/commands/crypto.ts)_
134+
_See code: [src/commands/crypto.ts](https://github.com/codingtools/cdt/blob/v0.1.6/src/commands/crypto.ts)_
117135

118136
## `cdt datetime [DATE]`
119137

@@ -131,7 +149,7 @@ OPTIONS
131149
-z, --timezone=timezone Timezone for Datetime parsing, default: Your timezone
132150
```
133151

134-
_See code: [src/commands/datetime.ts](https://github.com/codingtools/cdt/blob/v0.1.5/src/commands/datetime.ts)_
152+
_See code: [src/commands/datetime.ts](https://github.com/codingtools/cdt/blob/v0.1.6/src/commands/datetime.ts)_
135153

136154
## `cdt hash [STRING]`
137155

@@ -149,7 +167,7 @@ OPTIONS
149167
-t, --type=type type of hash [SHA1(default), MD5, SHA256, SHA512, RMD160 or RIPEMD160]
150168
```
151169

152-
_See code: [src/commands/hash.ts](https://github.com/codingtools/cdt/blob/v0.1.5/src/commands/hash.ts)_
170+
_See code: [src/commands/hash.ts](https://github.com/codingtools/cdt/blob/v0.1.6/src/commands/hash.ts)_
153171

154172
## `cdt help [COMMAND]`
155173

@@ -185,9 +203,16 @@ OPTIONS
185203
HTML/HTM, CSS
186204
```
187205

188-
_See code: [src/commands/minify.ts](https://github.com/codingtools/cdt/blob/v0.1.5/src/commands/minify.ts)_
206+
_See code: [src/commands/minify.ts](https://github.com/codingtools/cdt/blob/v0.1.6/src/commands/minify.ts)_
189207
<!-- commandsstop -->
190208

209+
## Acknowledgement
210+
* this cli uses following opensource libraries/services
211+
* [bundlephobia](https://bundlephobia.com/)
212+
* [avro-js](https://openbase.io/js/avro-js)
213+
* [avsc](https://github.com/mtth/avsc)
214+
215+
And many others, great thanks to all the people involved in developnment and support :)
191216

192217
## Contribution
193218

@@ -199,6 +224,18 @@ Please feel free to provide any suggestion for new utility in [Issues](https://g
199224

200225
This Project is created and supported by [Ashish Patel](http://ashish.live/)
201226

227+
## Releasing Version
228+
* this needs to be done from release* branch
229+
```bash
230+
npm version patch
231+
```
232+
it will update readme.md and update package.json, also will create tag and commit.
233+
234+
```bash
235+
npm publish --access public
236+
```
237+
this will publish package to **npm**
238+
202239
## License
203240

204241
[MIT](https://raw.githubusercontent.com/codingtools/cdt/master/LICENSE)

my.json

Whitespace-only changes.

oclif.manifest.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"version":"0.1.5","commands":{"avro":{"id":"avro","description":"Avro Utility command","pluginName":"@codingtools/cdt","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"file":{"name":"file","type":"option","char":"f","description":"input file path"},"output":{"name":"output","type":"option","char":"o","description":"output file path"},"schemaType":{"name":"schemaType","type":"option","char":"t","description":"schema type file path"}},"args":[{"name":"command"}]},"bundlephobia":{"id":"bundlephobia","description":"Find cost of adding a npm/yarn packages or all dependencies in package.json file","pluginName":"@codingtools/cdt","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"packages":{"name":"packages","type":"option","char":"p","description":"packages for which cost is required, can pass more than one separated by space"},"file":{"name":"file","type":"option","char":"f","description":"path for package.json file"}},"args":[{"name":"package"}]},"crypto":{"id":"crypto","description":"Encryption and Decryption functionality for File/String","pluginName":"@codingtools/cdt","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"encryption":{"name":"encryption","type":"option","char":"e","description":"encryption type, Supported [AES, DES, 3DES, Rabbit, RC4, RC4Drop]"},"decryption":{"name":"decryption","type":"option","char":"d","description":"decryption type, Supported [AES, DES, 3DES, Rabbit, RC4, RC4Drop]"},"string":{"name":"string","type":"option","char":"s","description":"string to be encrypted/decrypted"},"file":{"name":"file","type":"option","char":"f","description":"file to be encrypted/decrypted"},"key":{"name":"key","type":"option","char":"k","description":"key for encryption/decryption"},"mode":{"name":"mode","type":"option","char":"m","description":"Block Mode, Supported [CBC, CFB, CTR, OFB, ECB]"}},"args":[{"name":"string"}]},"datetime":{"id":"datetime","description":"Date and Time utility","pluginName":"@codingtools/cdt","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"date":{"name":"date","type":"option","char":"d","description":"Datetime input string, default: Current Datetime, could also be passed through argument"},"format":{"name":"format","type":"option","char":"f","description":"Datetime format, default: Do MMMM YYYY, h:m:s A, Z UTC"},"timezone":{"name":"timezone","type":"option","char":"z","description":"Timezone for Datetime parsing, default: Your timezone"},"locale":{"name":"locale","type":"option","char":"l","description":"Locale, default: en"}},"args":[{"name":"date"}]},"hash":{"id":"hash","description":"Hashing functionality for a string/file","pluginName":"@codingtools/cdt","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"type":{"name":"type","type":"option","char":"t","description":"type of hash [SHA1(default), MD5, SHA256, SHA512, RMD160 or RIPEMD160]"},"string":{"name":"string","type":"option","char":"s","description":"string to be hashed"},"file":{"name":"file","type":"option","char":"f","description":"file to be hashed"},"outputFile":{"name":"outputFile","type":"option","char":"o","description":"output file path"}},"args":[{"name":"string"}]},"minify":{"id":"minify","description":"File Minifier","pluginName":"@codingtools/cdt","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"type":{"name":"type","type":"option","char":"t","description":"type of file to be minified, it will try to find type with extension supported: JS, HTML/HTM, CSS"},"file":{"name":"file","type":"option","char":"f","description":"file to be minified"},"outputFile":{"name":"outputFile","type":"option","char":"o","description":"output file path"}},"args":[{"name":"file"}]}}}

package-lock.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@codingtools/cdt",
33
"description": "CLI for Developers",
4-
"version": "0.1.5",
4+
"version": "0.1.6",
55
"author": "Ashish Patel @ashishpatel0720",
66
"bin": {
77
"cdt": "./bin/run"
@@ -16,6 +16,7 @@
1616
"@oclif/plugin-help": "^2.2.1",
1717
"@oclif/plugin-not-found": "^1.2.3",
1818
"@oclif/plugin-warn-if-update-available": "^1.7.0",
19+
"avsc": "^5.4.18",
1920
"axios": "^0.19.0",
2021
"chalk": "^3.0.0",
2122
"crypto-js": "^3.1.9-1",
@@ -76,7 +77,7 @@
7677
"@oclif/plugin-autocomplete"
7778
],
7879
"warn-if-update-available": {
79-
"timeoutInDays": 1,
80+
"timeoutInDays": 7,
8081
"message": "<%= chalk.blue(config.name) %> update available from <%= chalk.greenBright(config.version) %> to <%= chalk.greenBright(latest) %>."
8182
}
8283
},

src/commands/avro.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import {Command, flags} from '@oclif/command'
2+
import * as avro from 'avsc'
3+
import * as chalk from 'chalk'
4+
import * as fs from 'fs' // includes all from avro-js and some more
5+
6+
import Logger from '../utilities/logger'
7+
import Utilities from '../utilities/utilities'
8+
9+
export default class Avro extends Command {
10+
static description = 'Avro Utility command'
11+
12+
static GET_SCHEMA = 'get_schema'
13+
static TO_JSON = 'to_json'
14+
static TO_AVRO = 'to_avro'
15+
16+
// do not change order otherwise we need to change order in getCommand() also
17+
static SupportedCommands = [Avro.GET_SCHEMA, Avro.TO_JSON, Avro.TO_AVRO]
18+
static flags = {
19+
help: flags.help({char: 'h'}),
20+
file: flags.string({char: 'f' , description: 'input file path'}),
21+
output: flags.string({char: 'o' , description: 'output file path'}),
22+
schemaType: flags.string({char: 't' , description: 'schema type file path'}),
23+
24+
}
25+
26+
static args = [{name: 'command'}] // operation type
27+
/*
28+
* input,output, and operation are all must
29+
* */
30+
async run() {
31+
const {args, flags} = this.parse(Avro)
32+
33+
this.checkParameters(flags, args)
34+
this.executeCommand(flags, args)
35+
}
36+
37+
// to check required parameters passed or not
38+
private checkParameters(flags: any, args: any) {
39+
if (!flags.file)
40+
Logger.error(this, 'Input file is not provided')
41+
if (!args.command)
42+
Logger.error(this, 'Command is empty or not provided, supported:' + Avro.SupportedCommands)
43+
44+
// if exists then make it upperCase
45+
args.command = args.command.toLowerCase()
46+
47+
// output is not mendatory for 'get_schema' command
48+
if (args.command !== Avro.GET_SCHEMA && !flags.output)
49+
Logger.error(this, 'Output file is not provided')
50+
51+
}
52+
53+
private executeCommand(flags: any, args: any) {
54+
switch (args.command) {
55+
case Avro.SupportedCommands[0]:
56+
return this.getSchema(flags, args)
57+
case Avro.SupportedCommands[1]:
58+
return this.toJson(flags, args)
59+
case Avro.SupportedCommands[2]:
60+
return this.toAvro(flags, args)
61+
default:
62+
Logger.error(this, 'Unsupported Command, supported: ' + Avro.SupportedCommands)
63+
}
64+
}
65+
66+
// tslint:disable-next-line:no-unused
67+
private getSchema(flags: any, args: any) {
68+
avro.createFileDecoder(flags.file)
69+
.on('metadata', function (type) {
70+
let output = type.schema()
71+
let schemaStr = JSON.stringify(output)
72+
if (flags.output) {
73+
// @ts-ignore
74+
Utilities.writeStringToFile(this, flags.output, schemaStr)
75+
} else {
76+
// @ts-ignore
77+
Logger.success(this,
78+
`${chalk.yellow('Avro Schema')}\n${JSON.stringify(output, null, ' ')}`
79+
)
80+
}
81+
})
82+
}
83+
84+
// tslint:disable-next-line:no-unused
85+
private toJson(flags: any, args: any) {
86+
Utilities.truncateFile(this, flags.output)
87+
avro.createFileDecoder(flags.file)
88+
.on('data', function (recordStr) {
89+
// @ts-ignore
90+
Utilities.appendStringToFile(this, flags.output, JSON.stringify(recordStr))
91+
})
92+
Logger.success(this, `${chalk.blue('Json')} written to file: ${chalk.green(flags.output)}`) // this will output error and exit command
93+
}
94+
95+
private toAvro(flags: any, args: any) {
96+
if (!flags.schemaType)
97+
Logger.error(this, 'Schema file is not provided')
98+
99+
let schema = avro.parse(flags.schemaType)
100+
let avroEncoder = new avro.streams.BlockEncoder(schema)
101+
102+
avroEncoder.pipe(fs.createWriteStream(flags.output))
103+
104+
// We write the records to the block encoder, which will take care of serializing them
105+
// into an object container file.
106+
107+
let jsonStr = '[' + Utilities.getInputString(this, flags, args) + ']'
108+
jsonStr = jsonStr.replace(/[\s\n]+/mg, '')
109+
jsonStr = jsonStr.replace(/\}\{/mg, '},{')
110+
let jsonObjects = JSON.parse(jsonStr)
111+
112+
jsonObjects.forEach(function (data: any) {
113+
if (schema.isValid(data)) {
114+
avroEncoder.write(data)
115+
} else {
116+
// @ts-ignore
117+
Logger.warn(this, `${chalk.yellow('[SKIPPING RECORD]')} schema is invalid: ${chalk.yellowBright(JSON.stringify(data))}`)
118+
}
119+
})
120+
Logger.success(this, `${chalk.blue('Avro')} written to file: ${chalk.green(flags.output)}`) // this will output error and exit command
121+
avroEncoder.end()
122+
}
123+
}

src/commands/bundlephobia.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import Logger from '../utilities/logger'
66
import Utilities from '../utilities/utilities'
77

88
// TODO:
9-
// ADD package.json support
109
// ADD VALID tests ( for now they just ignoring )
1110
export default class Bundlephobia extends Command {
1211
static description = 'Find cost of adding a npm/yarn packages or all dependencies in package.json file'

src/utilities/utilities.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
// tslint:disable-next-line:file-name-casing
2+
import {Command} from '@oclif/command'
23
import * as chalk from 'chalk'
34
import * as fs from 'fs'
45

56
import Logger from './logger'
67
// tslint:disable-next-line:no-unnecessary-class
78
export default class Utilities {
8-
public static getStringFromFile(thisRef: any, filePath: string) {
9+
public static getStringFromFile(thisRef: Command, filePath: string) {
910
let fileStr = ''
1011
if (!fs.existsSync(filePath)) {
1112
Logger.error(thisRef, `Could not find file: ${chalk.red(filePath)}`) // this will output error and exit command
@@ -15,7 +16,7 @@ export default class Utilities {
1516
}
1617
return fileStr
1718
}
18-
public static getJsonObjectFromFile(thisRef: any, filePath: string) {
19+
public static getJsonObjectFromFile(thisRef: Command, filePath: string) {
1920
if (!fs.existsSync(filePath)) {
2021
Logger.error(thisRef, `Could not find file: ${chalk.red(filePath)}`) // this will output error and exit command
2122
} else {
@@ -28,26 +29,40 @@ export default class Utilities {
2829
}
2930
}
3031

31-
public static getInputString(thisRef: any , flags: any, args: any) { //need to make it static so Crypto can use this
32+
public static getInputString(thisRef: Command , flags: any, args: any) { //need to make it static so Crypto can use this
3233
// if -s or -f is not passed we will take it from args
3334
if (flags.string) //if -s given
3435
return flags.string
35-
else if (flags.file) {
36+
else if (flags.file) { // if -f given
3637
Logger.info(thisRef, `reading file: ${chalk.green(flags.file)}`)
3738
return Utilities.getStringFromFile(thisRef, flags.file)
3839
} else
3940
return args.string
4041
}
4142

42-
public static writeStringToFile(thisRef: any, filePath: string, string: string) {
43+
public static writeStringToFile(thisRef: Command, filePath: string, string: string) {
4344
if (!fs.existsSync(filePath))
4445
Logger.info(thisRef, `Could not find file: ${chalk.yellow(filePath + ', creating new one')}`) // this will output error and exit command
4546
else
4647
Logger.warn(thisRef, `File already exists: ${chalk.green(filePath)}, ${chalk.yellow('overriding content')}`) // this will output error and exit command
4748

4849
fs.writeFileSync(filePath, string)
49-
Logger.success(thisRef, `output written to file: ${chalk.green(filePath)}`) // this will output error and exit command
50+
51+
if (string !== '') // this condition comes for truncating
52+
Logger.success(thisRef, `output written to file: ${chalk.green(filePath)}`) // this will output error and exit command
5053
// return `${chalk.red(pkg)} ${message}`
5154

5255
}
56+
57+
public static appendStringToFile(thisRef: Command, filePath: string, string: string) {
58+
if (!fs.existsSync(filePath))
59+
Logger.info(thisRef, `Could not find file: ${chalk.yellow(filePath + ', creating new one')}`) // this will output error and exit command
60+
fs.appendFileSync(filePath, string)
61+
}
62+
63+
public static truncateFile(thisRef: Command, filePath: string) {
64+
if (fs.existsSync(filePath))
65+
Logger.info(thisRef, `file found: ${chalk.yellow(filePath + ', truncating')}`) // this will output error and exit command
66+
Utilities.writeStringToFile(thisRef, filePath, '') // write nothing
67+
}
5368
}

0 commit comments

Comments
 (0)