24 Commits

Author SHA1 Message Date
85ed6e8172 2.0.0 2022-08-06 18:38:54 +02:00
d7c1677c9d BREAKING CHANGE(core): switch to esm and enable white space trimming. 2022-08-06 18:38:53 +02:00
c4194bf037 1.0.23 2022-01-03 17:37:45 +01:00
fd0abaeb47 fix(bom markers): now handles bom markers correctly 2022-01-03 17:37:44 +01:00
ab1c84f41f 1.0.22 2019-12-15 18:30:47 +00:00
6f575e8516 fix(core): update 2019-12-15 18:30:46 +00:00
d11f237221 1.0.21 2019-12-15 18:18:40 +00:00
16826ed337 fix(core): update 2019-12-15 18:18:39 +00:00
c49b518b8a 1.0.20 2019-12-15 18:15:04 +00:00
5f49532fc2 fix(core): update 2019-12-15 18:15:03 +00:00
e7f06a7f44 1.0.19 2019-10-11 15:48:23 +02:00
491477da82 fix(core): update 2019-10-11 15:48:23 +02:00
935109abb6 1.0.18 2019-10-10 18:30:29 +02:00
ea26a1d8ef fix(core): update 2019-10-10 18:30:29 +02:00
c7324f0240 1.0.17 2019-07-08 16:57:46 +02:00
be44a1354b fix(core): update 2019-07-08 16:57:45 +02:00
13f3f7b2f6 1.0.16 2019-05-23 17:28:21 +02:00
94f2620161 fix(core): update 2019-05-23 17:28:21 +02:00
bdebb3308c 1.0.15 2018-10-14 23:30:19 +02:00
cb5ac7618b fix(snyk): add snyk policy 2018-10-14 23:30:19 +02:00
00aed79e18 1.0.14 2018-10-14 23:28:38 +02:00
438053a2f9 fix(structure): run gitzone format 2018-10-14 23:28:38 +02:00
7479328e13 1.0.13 2018-10-14 23:26:54 +02:00
56d7ae8952 fix(refactor): update static function/constructor responsibilities 2018-10-14 23:26:54 +02:00
15 changed files with 13729 additions and 557 deletions

16
.gitignore vendored
View File

@@ -1,6 +1,20 @@
.nogit/ .nogit/
node_modules/
# artifacts
coverage/ coverage/
public/ public/
pages/ pages/
# installs
node_modules/
# caches
.yarn/ .yarn/
.cache/
.rpt2_cache
# builds
dist/
dist_*/
# custom

View File

@@ -1,74 +1,72 @@
# gitzone standard # gitzone ci_default
image: hosttoday/ht-docker-node:npmci image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache: cache:
paths: paths:
- .npmci_cache/ - .npmci_cache/
key: "$CI_BUILD_STAGE" key: '$CI_BUILD_STAGE'
stages: stages:
- security - security
- test - test
- release - release
- metadata - metadata
before_script:
- npm install -g @shipzone/npmci
# ==================== # ====================
# security stage # security stage
# ==================== # ====================
mirror: auditProductionDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security stage: security
script: script:
- npmci git mirror - npmci npm prepare
- npmci command npm install --production --ignore-scripts
- npmci command npm config set registry https://registry.npmjs.org
- npmci command npm audit --audit-level=high --only=prod --production
tags: tags:
- docker - docker
- notpriv allow_failure: true
snyk: auditDevDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security stage: security
script: script:
- npmci command npm install -g snyk - npmci npm prepare
- npmci command npm install --ignore-scripts - npmci command npm install --ignore-scripts
- npmci command snyk test - npmci command npm config set registry https://registry.npmjs.org
- npmci command npm audit --audit-level=high --only=dev
tags: tags:
- docker - docker
- notpriv allow_failure: true
# ==================== # ====================
# test stage # test stage
# ==================== # ====================
testLEGACY:
stage: test
script:
- npmci node install legacy
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
allow_failure: true
testLTS: testStable:
stage: test
script:
- npmci node install lts
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
testSTABLE:
stage: test stage: test
script: script:
- npmci npm prepare
- npmci node install stable - npmci node install stable
- npmci npm install - npmci npm install
- npmci npm test - npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- notpriv
testBuild:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
release: release:
stage: release stage: release
@@ -78,6 +76,7 @@ release:
only: only:
- tags - tags
tags: tags:
- lossless
- docker - docker
- notpriv - notpriv
@@ -86,20 +85,15 @@ release:
# ==================== # ====================
codequality: codequality:
stage: metadata stage: metadata
image: docker:stable
allow_failure: true allow_failure: true
services: only:
- docker:stable-dind - tags
script: script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') - npmci command npm install -g typescript
- docker run - npmci npm prepare
--env SOURCE_CODE="$PWD" - npmci npm install
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
tags: tags:
- lossless
- docker - docker
- priv - priv
@@ -110,17 +104,19 @@ trigger:
only: only:
- tags - tags
tags: tags:
- lossless
- docker - docker
- notpriv - notpriv
pages: pages:
image: hosttoday/ht-docker-node:npmci
stage: metadata stage: metadata
script: script:
- npmci command npm install -g typedoc typescript - npmci node install stable
- npmci npm prepare
- npmci npm install - npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/ - npmci command npm run buildDocs
tags: tags:
- lossless
- docker - docker
- notpriv - notpriv
only: only:
@@ -130,13 +126,3 @@ pages:
paths: paths:
- public - public
allow_failure: true allow_failure: true
windowsCompatibility:
image: stefanscherer/node-windows:10-build-tools
stage: metadata
script:
- npm install & npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- windows
allow_failure: true

11
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "npm test",
"name": "Run npm test",
"request": "launch",
"type": "node-terminal"
}
]
}

26
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,26 @@
{
"json.schemas": [
{
"fileMatch": ["/npmextra.json"],
"schema": {
"type": "object",
"properties": {
"npmci": {
"type": "object",
"description": "settings for npmci"
},
"gitzone": {
"type": "object",
"description": "settings for gitzone",
"properties": {
"projectType": {
"type": "string",
"enum": ["website", "element", "service", "npm", "wcc"]
}
}
}
}
}
}
]
}

View File

@@ -2,5 +2,16 @@
"npmci": { "npmci": {
"npmGlobalTools": [], "npmGlobalTools": [],
"npmAccessLevel": "public" "npmAccessLevel": "public"
},
"gitzone": {
"projectType": "npm",
"module": {
"githost": "gitlab.com",
"gitscope": "pushrocks",
"gitrepo": "smartcsv",
"description": "handle csv data | gitzone standard compliant",
"npmPackagename": "@pushrocks/smartcsv",
"license": "MIT"
}
} }
} }

13795
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +1,45 @@
{ {
"name": "@pushrocks/smartcsv", "name": "@pushrocks/smartcsv",
"version": "1.0.12", "version": "2.0.0",
"private": false, "private": false,
"description": "handle csv data | gitzone standard compliant", "description": "handle csv data | gitzone standard compliant",
"main": "dist/index.js", "main": "dist_ts/index.js",
"typings": "dist/index.d.ts", "typings": "dist_ts/index.d.ts",
"type": "module",
"author": "Lossless GmbH", "author": "Lossless GmbH",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"test": "(tstest test/)", "test": "(tstest test/)",
"build": "(tsbuild)", "build": "(tsbuild)",
"format": "(gitzone format)" "buildDocs": "tsdoc"
}, },
"devDependencies": { "devDependencies": {
"@gitzone/tsbuild": "^2.0.22", "@gitzone/tsbuild": "^2.1.65",
"@gitzone/tsrun": "^1.1.12", "@gitzone/tsrun": "^1.2.37",
"@gitzone/tstest": "^1.0.15", "@gitzone/tstest": "^1.0.73",
"@pushrocks/smartfile": "^6.0.6", "@pushrocks/smartfile": "^10.0.4",
"@pushrocks/tapbundle": "^3.0.5", "@pushrocks/tapbundle": "^5.0.4",
"@types/node": "^10.7.1" "@types/node": "^18.6.4",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0"
}, },
"dependencies": { "dependencies": {
"@pushrocks/smartpromise": "^2.0.5" "@pushrocks/smartpromise": "^3.1.7",
} "@pushrocks/smartstring": "^4.0.2"
},
"files": [
"ts/**/*",
"ts_web/**/*",
"dist/**/*",
"dist_*/**/*",
"dist_ts/**/*",
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
"readme.md"
],
"browserslist": [
"last 1 chrome versions"
]
} }

41
readme.md Normal file
View File

@@ -0,0 +1,41 @@
# @pushrocks/smartcsv
handle csv data | gitzone standard compliant
## Availabililty and Links
* [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartcsv)
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartcsv)
* [github.com (source mirror)](https://github.com/pushrocks/smartcsv)
* [docs (typedoc)](https://pushrocks.gitlab.io/smartcsv/)
## Status for master
Status Category | Status Badge
-- | --
GitLab Pipelines | [![pipeline status](https://gitlab.com/pushrocks/smartcsv/badges/master/pipeline.svg)](https://lossless.cloud)
GitLab Pipline Test Coverage | [![coverage report](https://gitlab.com/pushrocks/smartcsv/badges/master/coverage.svg)](https://lossless.cloud)
npm | [![npm downloads per month](https://badgen.net/npm/dy/@pushrocks/smartcsv)](https://lossless.cloud)
Snyk | [![Known Vulnerabilities](https://badgen.net/snyk/pushrocks/smartcsv)](https://lossless.cloud)
TypeScript Support | [![TypeScript](https://badgen.net/badge/TypeScript/>=%203.x/blue?icon=typescript)](https://lossless.cloud)
node Support | [![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
Code Style | [![Code Style](https://badgen.net/badge/style/prettier/purple)](https://lossless.cloud)
PackagePhobia (total standalone install weight) | [![PackagePhobia](https://badgen.net/packagephobia/install/@pushrocks/smartcsv)](https://lossless.cloud)
PackagePhobia (package size on registry) | [![PackagePhobia](https://badgen.net/packagephobia/publish/@pushrocks/smartcsv)](https://lossless.cloud)
BundlePhobia (total size when bundled) | [![BundlePhobia](https://badgen.net/bundlephobia/minzip/@pushrocks/smartcsv)](https://lossless.cloud)
Platform support | [![Supports Windows 10](https://badgen.net/badge/supports%20Windows%2010/yes/green?icon=windows)](https://lossless.cloud) [![Supports Mac OS X](https://badgen.net/badge/supports%20Mac%20OS%20X/yes/green?icon=apple)](https://lossless.cloud)
## Usage
## Contribution
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
## Contribution
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
For further information read the linked docs at the top of this readme.
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
[![repo-footer](https://lossless.gitlab.io/publicrelations/repofooter.svg)](https://maintainedby.lossless.com)

View File

@@ -1,3 +1,3 @@
Header 1;Header 2; Header3 Header 1;Header 2;"Header 3"
row1data1; row1data2; row1data3 "row1data1";"row1data2";"row1data3"
row2data1; row2data2; row2data3 "row2data1";row2data2;"row2data3"
1 Header 1 Header 2 Header3 Header 3
2 row1data1 row1data2 row1data3 row1data3
3 row2data1 row2data2 row2data3 row2data3

View File

@@ -1,21 +1,27 @@
// tslint:disable-next-line:no-implicit-dependencies
import { expect, tap } from '@pushrocks/tapbundle'; import { expect, tap } from '@pushrocks/tapbundle';
import * as smartcsv from '../ts/index'; import * as smartcsv from '../ts/index.js';
// tslint:disable-next-line:no-implicit-dependencies
import * as smartfile from '@pushrocks/smartfile'; import * as smartfile from '@pushrocks/smartfile';
let fileString: string; let fileString: string;
let testCsv: smartcsv.Csv; let testCsv: smartcsv.Csv;
tap.test('should read a file', async tools => { tap.test('should read a file', async (tools) => {
fileString = smartfile.fs.toStringSync('./test/sample.csv'); fileString = smartfile.fs.toStringSync('./test/sample.csv');
}); });
tap.test('should create a valid csv', async () => { tap.test('should create a valid csv', async () => {
testCsv = await smartcsv.Csv.createCsvFromString(fileString, { headers: true }); testCsv = await smartcsv.Csv.createCsvFromString(fileString, { headers: true, unquote: true });
const result = await testCsv.exportAsObject(); const result = await testCsv.exportAsObject();
console.log(result); console.log(result);
}); });
tap.test('should create a valid csv string', async () => {
const createdCsvString = await smartcsv.Csv.createCsvStringFromArray([
{ wow: 'hi', wow2: 'there' },
{ wow: 'really', wow3: 'yes' },
]);
console.log(createdCsvString);
});
tap.start(); tap.start();

8
ts/00_commitinfo_data.ts Normal file
View File

@@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @pushrocks/commitinfo
*/
export const commitinfo = {
name: '@pushrocks/smartcsv',
version: '2.0.0',
description: 'handle csv data | gitzone standard compliant'
}

View File

@@ -1,28 +1,102 @@
import * as plugins from './smartcsv.plugins'; import * as plugins from './smartcsv.plugins.js';
export interface ICsvConstructorOptions { export interface ICsvConstructorOptions {
headers: boolean; headers: boolean;
unquote?: boolean;
trimSpace?: boolean;
removeBomMarkers?: boolean;
} }
export class Csv { export class Csv {
// STATIC
/**
* creates a Csv Object from string
* @param csvStringArg
* @param optionsArg
*/
public static async createCsvFromString( public static async createCsvFromString(
csvStringArg: string, csvStringArg: string,
options: ICsvConstructorOptions optionsArg: ICsvConstructorOptions
): Promise<Csv> { ): Promise<Csv> {
const csvInstance = new Csv(); const csvInstance = new Csv(csvStringArg, optionsArg);
csvInstance.csvString = csvStringArg; await csvInstance.exportAsObject();
csvInstance.determineKeyframe();
return csvInstance; return csvInstance;
} }
public static async createCsvStringFromArray(arrayArg: any[]): Promise<string> {
const foundKeys: string[] = [];
// lets deal with the keys
for (const objectArg of arrayArg) {
for (const key of Object.keys(objectArg)) {
foundKeys.includes(key) ? null : foundKeys.push(key);
}
}
// lets deal with the data
const dataRows: string[] = [];
for (const objectArg of arrayArg) {
const dataRowArray: string[] = [];
for (const key of foundKeys) {
dataRowArray.push(objectArg[key]);
}
dataRows.push(dataRowArray.join(','));
}
// lets put togehter the csv string and return it
const headerString = foundKeys.join(',');
const dataString = dataRows.join('\n');
const csvString = `${headerString}\n${dataString}\n`;
return csvString;
}
// INSTANCE
public csvString: string; public csvString: string;
public headers: string[]; public headers: string[];
public keyFrame: string = null; public keyFrame: string = null;
public data: any[];
private base64RecognitionPrefix = '####12345####';
public options: ICsvConstructorOptions = { public options: ICsvConstructorOptions = {
headers: true headers: true,
unquote: true,
trimSpace: true,
removeBomMarkers: true,
}; };
public determineKeyframe() { constructor(csvStringArg: string, optionsArg: ICsvConstructorOptions) {
this.options = {
...this.options,
...optionsArg,
};
let csvStringToParse = csvStringArg;
if (this.options.removeBomMarkers) {
csvStringToParse = csvStringToParse.replace(/^\uFEFF/, '');
}
// Quotes allow separators to be contained in quoted strings.
// To preserve them, when unquoting, we convert everything in between to base64 here
if (this.options.unquote) {
csvStringToParse = csvStringToParse.replace(
/"(.*?)"/gi,
(match, p1, offset, originalString) => {
return this.base64RecognitionPrefix + plugins.smartstring.base64.encode(match);
}
);
}
this.csvString = csvStringToParse;
this.determineKeyframe();
}
/**
* determines the keyframe of the csv string
*/
private determineKeyframe() {
let commaLength = 0; let commaLength = 0;
let semicolonLength = 0; let semicolonLength = 0;
const commaRegexResult = this.csvString.match(/,/g); const commaRegexResult = this.csvString.match(/,/g);
@@ -41,7 +115,10 @@ export class Csv {
} }
} }
public serializeCsvString() { /**
* serializes the csv string
*/
private serializeCsvString() {
const rowArray = this.getRows(); const rowArray = this.getRows();
const resultArray = []; const resultArray = [];
if (this.options.headers) { if (this.options.headers) {
@@ -54,7 +131,10 @@ export class Csv {
return resultArray; return resultArray;
} }
public getRows(): string[] { /**
* gets the rows of the csv
*/
private getRows(): string[] {
const rowsArray = this.csvString.split('\n'); const rowsArray = this.csvString.split('\n');
if (rowsArray[rowsArray.length - 1] === '') { if (rowsArray[rowsArray.length - 1] === '') {
rowsArray.pop(); rowsArray.pop();
@@ -62,20 +142,50 @@ export class Csv {
return rowsArray; return rowsArray;
} }
public getHeaders() { private getHeaders() {
const rowArray = this.getRows(); const rowArray = this.getRows();
if (this.options.headers) { if (this.options.headers) {
let headerRow = rowArray[0]; let headerRow = rowArray[0];
this.headers = headerRow.split(this.keyFrame); this.headers = headerRow.split(this.keyFrame);
if (this.options.unquote) {
const unquotedHeaders: string[] = [];
for (let header of this.headers) {
if (header.startsWith(this.base64RecognitionPrefix)) {
header = header.replace(this.base64RecognitionPrefix, '');
unquotedHeaders.push(plugins.smartstring.base64.decode(header).replace(/['"]+/g, ''));
} else {
unquotedHeaders.push(header);
}
}
this.headers = unquotedHeaders;
}
if (this.options.trimSpace) {
const trimmedHeaders = [];
for (const header of this.headers) {
trimmedHeaders.push(header.trim());
}
this.headers = trimmedHeaders;
}
} }
return this.headers; return this.headers;
} }
public createDataObject(dataArray: string[]) { private createDataObject(dataArray: string[]) {
const neededIterations = dataArray.length; const neededIterations = dataArray.length;
let resultJson: any = {}; let resultJson: any = {};
for (let i = 0; i < neededIterations; i++) { for (let i = 0; i < neededIterations; i++) {
resultJson[this.headers[i]] = dataArray[i]; let value = dataArray[i];
if (this.options.unquote && value.startsWith(this.base64RecognitionPrefix)) {
value = value.replace(this.base64RecognitionPrefix, '');
value = plugins.smartstring.base64
.decode(value)
.replace(/['"]+/g, '')
.replace(/['"]+/g, '');
}
if (this.options.trimSpace) {
value = value.trim();
}
resultJson[this.headers[i]] = value;
} }
return resultJson; return resultJson;
} }
@@ -86,6 +196,7 @@ export class Csv {
for (const dataArray of serializedData) { for (const dataArray of serializedData) {
dataObjects.push(this.createDataObject(dataArray)); dataObjects.push(this.createDataObject(dataArray));
} }
this.data = dataObjects;
return dataObjects; return dataObjects;
} }
} }

View File

@@ -1,3 +1,4 @@
import * as smartq from '@pushrocks/smartpromise'; import * as smartpromise from '@pushrocks/smartpromise';
import * as smartstring from '@pushrocks/smartstring';
export { smartq }; export { smartpromise, smartstring };

10
tsconfig.json Normal file
View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false,
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "nodenext",
"esModuleInterop": true
}
}

View File

@@ -1,13 +0,0 @@
{
"extends": [
"tslint:latest",
"tslint-config-prettier"
],
"rules": {
"semicolon": [
true,
"always"
]
}
}