aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc9
-rw-r--r--.vscode/settings.json3
-rw-r--r--package.json1
-rw-r--r--src/index.ts41
-rw-r--r--src/interface/frameInterface.ts4
-rw-r--r--src/lib/display.ts20
-rw-r--r--src/lib/frame.ts72
-rw-r--r--tests/frames.test.ts61
-rw-r--r--tests/frames.ts49
-rw-r--r--tsconfig.json11
10 files changed, 177 insertions, 94 deletions
diff --git a/.eslintrc b/.eslintrc
index 871ae6f..cb3ff95 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -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/"
],
}