diff options
| author | Priyansh <[email protected]> | 2022-01-19 00:57:06 -0500 |
|---|---|---|
| committer | Priyansh <[email protected]> | 2022-01-19 00:57:06 -0500 |
| commit | 80eabe37c21ae4965dbafbb9abb5c7a153b209c5 (patch) | |
| tree | 913376ae548fecbe72b2099fa006f81d50dbb5ab | |
| parent | bc6fa1856be7ec26208bb2c4c63b693a163506c3 (diff) | |
| download | izuku.js-80eabe37c21ae4965dbafbb9abb5c7a153b209c5.tar.xz izuku.js-80eabe37c21ae4965dbafbb9abb5c7a153b209c5.zip | |
feat: display data in table function
| -rw-r--r-- | .eslintrc | 9 | ||||
| -rw-r--r-- | .vscode/settings.json | 3 | ||||
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | src/index.ts | 41 | ||||
| -rw-r--r-- | src/interface/frameInterface.ts | 4 | ||||
| -rw-r--r-- | src/lib/display.ts | 20 | ||||
| -rw-r--r-- | src/lib/frame.ts | 72 | ||||
| -rw-r--r-- | tests/frames.test.ts | 61 | ||||
| -rw-r--r-- | tests/frames.ts | 49 | ||||
| -rw-r--r-- | tsconfig.json | 11 |
10 files changed, 177 insertions, 94 deletions
@@ -1,4 +1,7 @@ { + "env": { + "node": true + }, "root": true, "parser": "@typescript-eslint/parser", "plugins": ["@typescript-eslint", "prettier"], @@ -8,7 +11,11 @@ "plugin:@typescript-eslint/recommended", "prettier" ], + "parserOptions": { + "sourceType": "module" + }, "rules": { - "prettier/prettier": 2 // Means error + "prettier/prettier": 2, + "@typescript-eslint/no-explicit-any": "off" } } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..78664b2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.tabSize": 2 +} diff --git a/package.json b/package.json index c245677..b9aae6f 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "In-Console Tabular Data Representation and Manipulation", "main": "dist/index.js", "types": "dist/index.d.ts", + "files": [ "dist" ], "scripts": { "test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha -r ts-node/register 'tests/**/*.ts'", "start": "npm run build && node build/index.js", diff --git a/src/index.ts b/src/index.ts index 37fa533..f085d82 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,40 +1,3 @@ -export default class Izuku { - constructor(rowdata?: Array<unknown[]>, header?: Array<string>) { - this.rowdata = rowdata || []; - this.header = header || []; - } +import { Frame } from './lib/frame'; - protected rowdata: Array<unknown[]> = []; - protected header: Array<string> = []; - /** - * data sets the rowdata of the frame, it creates a new frame if the frame is undefined - * @param rowdata: the rowdata to be sent to the frame - * @returns a new frame with the rowdata or updates the current frame with new rowdata or returns the current rowdata if rowdata is present - */ - data(rowdata?: Array<unknown[]>): Izuku | unknown[][] { - if (rowdata) { - this.rowdata = rowdata; - return new Izuku(rowdata, this.header); - } else if (this.rowdata) { - return this.rowdata; - } else { - throw new Error('Frame has no rowdata.'); - } - } - - /** - * columns sets the header of the frame, it creates a new frame if the frame is undefined - * @param header: the header to be sent to the frame - * @returns a new frame with the header or updates the current frame with new header or returns the current header if header is present - */ - columns(header?: Array<string>): Izuku | Array<string> { - if (header) { - this.header = header; - return new Izuku(this.rowdata, header); - } else if (this.header) { - return this.header; - } else { - throw new Error('Frame has no header.'); - } - } -} +export { Frame }; diff --git a/src/interface/frameInterface.ts b/src/interface/frameInterface.ts new file mode 100644 index 0000000..bc61c90 --- /dev/null +++ b/src/interface/frameInterface.ts @@ -0,0 +1,4 @@ +export interface FrameInterface { + rowdata: Array<unknown[]>; + columns: Array<string>; +} diff --git a/src/lib/display.ts b/src/lib/display.ts new file mode 100644 index 0000000..2247938 --- /dev/null +++ b/src/lib/display.ts @@ -0,0 +1,20 @@ +import { FrameInterface } from '../interface/frameInterface'; + +export class Display implements FrameInterface { + rowdata: unknown[][] = []; + columns!: string[]; + table(frame: FrameInterface): void { + const maxSizedArrayLength = frame.rowdata.reduce((acc, curr) => { + return acc.length > curr.length ? acc : curr; + }).length; + console.table( + frame.rowdata.map((row) => { + const rowobj: any = {}; + for (let i = 0; i < maxSizedArrayLength; i++) { + rowobj[frame.columns[i]] = row[i] ? row[i] : null; + } + return rowobj; + }) + ); + } +} diff --git a/src/lib/frame.ts b/src/lib/frame.ts new file mode 100644 index 0000000..dc93a2c --- /dev/null +++ b/src/lib/frame.ts @@ -0,0 +1,72 @@ +import { FrameInterface } from '../interface/frameInterface'; +import { Display } from './display'; + +export class Frame implements FrameInterface { + rowdata: unknown[][] = []; + columns!: string[]; + + constructor(rowdata?: Array<unknown[]>, header?: Array<string>) { + this.rowdata = rowdata || []; + this.columns = header || []; + } + /** + * data prints the data of the frame in console.table format. It also sets the new data to the frame if data is passed as a parameter + * @param rowdata: the rowdata to be sent to the frame + * @returns the current frame + */ + data(rowdata?: Array<unknown[]>): this | unknown[][] { + if (rowdata) { + this.rowdata = rowdata; + } else { + new Display().table(this); + return this; + } + + return this; + } + + /** + * header sets the names of the columns of the frame + * @param header: the header to be attached to the frame + * @returns the current frame + */ + header(header: Array<string>): this | Array<string> { + if (!this.rowdata.length) { + throw new Error('Set data before setting header'); + } else { + const passedHeaderLength = header.length; + const maxSizedArrayLength = this.rowdata.reduce((acc, curr) => { + return acc.length > curr.length ? acc : curr; + }).length; + if (passedHeaderLength !== maxSizedArrayLength) { + throw new Error('Header length does not match data length'); + } else { + this.columns = header; + return this; + } + } + } + + /** + * column returns a single column of the frame, option is either the column name or the column index + * @param column: the column to be returned + * @returns a single column of the frame + * @example + * const frame = new Izuku([ + * ['a', 'b', 'c'], + * ['d', 'e', 'f'], + * ['g', 'h', 'i'] + * ]); + * frame.setheader(['a', 'b', 'c']); + * console.log(frame.column('a')); + * // ['a', 'd', 'g'] + * console.log(frame.column(1)); + * // ['b', 'e', 'h'] + */ + public column(column: string | number): Array<unknown> { + if (typeof column === 'string') { + return this.rowdata.map((row) => row[this.columns.indexOf(column)]); + } + return this.rowdata.map((row) => row[column]); + } +} diff --git a/tests/frames.test.ts b/tests/frames.test.ts new file mode 100644 index 0000000..b643292 --- /dev/null +++ b/tests/frames.test.ts @@ -0,0 +1,61 @@ +import { expect } from 'chai'; +import { Frame } from '../src/index'; + +describe('frames.ts', () => { + describe('Create a new frame with column names', () => { + it('should create a new frame', () => { + const newframe = new Frame([ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ['g', 'h', 'i'] + ]); + expect(newframe.rowdata).to.deep.equal([ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ['g', 'h', 'i'] + ]); + newframe.header(['a', 'b', 'c']); + expect(newframe.columns).to.deep.equal(['a', 'b', 'c']); + }); + }); + describe('Update a frame and column names', () => { + it('should update a frame', () => { + const newframe = new Frame([ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ['g', 'h', 'i'] + ]); + newframe.header(['a', 'b', 'c']); + expect(newframe.rowdata).to.deep.equal([ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ['g', 'h', 'i'] + ]); + expect(newframe.columns).to.deep.equal(['a', 'b', 'c']); + newframe.data([ + ['j', 'k', 'l'], + ['m', 'n', 'o'], + ['p', 'q', 'r'] + ]); + newframe.header(['j', 'k', 'l']); + expect(newframe.rowdata).to.deep.equal([ + ['j', 'k', 'l'], + ['m', 'n', 'o'], + ['p', 'q', 'r'] + ]); + expect(newframe.columns).to.deep.equal(['j', 'k', 'l']); + }); + }); + describe('Print a frame', () => { + it('should print a frame', () => { + const header = ['Name', 'Age', 'Gender', 'Country']; + const data = [ + ['Arthur', 21, 'Male', 'USA'], + ['Betty', 20, 'Female', 'Canada'], + ['Victor', 25, 'Male'] + ]; + const newframe = new Frame(data, header); + newframe.data(); + }); + }); +}); diff --git a/tests/frames.ts b/tests/frames.ts deleted file mode 100644 index ff778c3..0000000 --- a/tests/frames.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { expect } from 'chai'; -import Izuku from '../src/index'; - -describe('frames.ts', () => { - describe('Create a new frame with column names', () => { - it('should create a new frame', () => { - const newframe = new Izuku([ - ['a', 'b', 'c'], - ['d', 'e', 'f'], - ['g', 'h', 'i'] - ]); - expect(newframe.data()).to.deep.equal([ - ['a', 'b', 'c'], - ['d', 'e', 'f'], - ['g', 'h', 'i'] - ]); - newframe.columns(['a', 'b', 'c']); - expect(newframe.columns()).to.deep.equal(['a', 'b', 'c']); - }); - }); - describe('Update a frame and column names', () => { - it('should update a frame', () => { - const newframe = new Izuku([ - ['a', 'b', 'c'], - ['d', 'e', 'f'], - ['g', 'h', 'i'] - ]); - newframe.columns(['a', 'b', 'c']); - expect(newframe.data()).to.deep.equal([ - ['a', 'b', 'c'], - ['d', 'e', 'f'], - ['g', 'h', 'i'] - ]); - expect(newframe.columns()).to.deep.equal(['a', 'b', 'c']); - newframe.data([ - ['j', 'k', 'l'], - ['m', 'n', 'o'], - ['p', 'q', 'r'] - ]); - newframe.columns(['j', 'k', 'l']); - expect(newframe.data()).to.deep.equal([ - ['j', 'k', 'l'], - ['m', 'n', 'o'], - ['p', 'q', 'r'] - ]); - expect(newframe.columns()).to.deep.equal(['j', 'k', 'l']); - }); - }); -}); diff --git a/tsconfig.json b/tsconfig.json index 1e9205d..66353cc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,8 +11,8 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - "lib": ["es6"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "target": "es5", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": ["es6"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ @@ -26,14 +26,14 @@ /* Modules */ "module": "commonjs", /* Specify what module code is generated. */ "rootDir": "src", /* Specify the root folder within your source files. */ - // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ // "types": [], /* Specify type package names to be included without being referenced in a source file. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - "resolveJsonModule": true, /* Enable importing .json files */ + // "resolveJsonModule": true, /* Enable importing .json files */ // "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */ /* JavaScript Support */ @@ -101,6 +101,7 @@ "exclude": [ "./tests/", "./node_modules/", - "./dist/" + "./dist/", + "./test/" ], } |
