csv-generate
Advanced tools
Comparing version 3.4.3 to 4.0.0
@@ -6,94 +6,77 @@ | ||
export = generate; | ||
type Callback = (err?: Error, records?: any) => void; | ||
declare function generate(options?: generate.Options, callback?: generate.Callback): generate.Generator; | ||
declare function generate(callback?: generate.Callback): generate.Generator; | ||
declare namespace generate { | ||
export class Generator extends stream.Readable { | ||
constructor(options?: Options); | ||
readonly options: Options; | ||
} | ||
type Callback = (err?: Error, records?: any) => void; | ||
export interface Options extends stream.ReadableOptions { | ||
/** | ||
* Define the number of generated fields and the generation method. | ||
*/ | ||
columns?: number | string[]; | ||
/** | ||
* Set the field delimiter. | ||
*/ | ||
delimiter?: string; | ||
/** | ||
* Period to run in milliseconds. | ||
*/ | ||
duration?: number; | ||
/** | ||
* If specified, then buffers will be decoded to strings using the specified encoding. | ||
*/ | ||
encoding?: BufferEncoding | undefined; | ||
/** | ||
* When to stop the generation. | ||
*/ | ||
end?: number | Date; | ||
/** | ||
* One or multiple characters to print at the end of the file; only apply when objectMode is disabled. | ||
*/ | ||
eof?: boolean | string; | ||
/** | ||
* Generate buffers equals length as defined by the `highWaterMark` option. | ||
*/ | ||
fixed_size?: boolean; | ||
fixedSize?: boolean; | ||
/** | ||
* The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. | ||
*/ | ||
high_water_mark?: number; | ||
highWaterMark?: number; | ||
/** | ||
* Number of lines or records to generate. | ||
*/ | ||
length?: number; | ||
/** | ||
* Maximum number of characters per word. | ||
*/ | ||
max_word_length?: number; | ||
maxWordLength?: number; | ||
/** | ||
* Whether this stream should behave as a stream of objects. | ||
*/ | ||
object_mode?: boolean | ||
objectMode?: boolean; | ||
/** | ||
* One or multiple characters used to delimit records. | ||
*/ | ||
row_delimiter?: string; | ||
/** | ||
* Generate idempotent random characters if a number provided. | ||
*/ | ||
seed?: boolean | number; | ||
/** | ||
* The time to wait between the generation of each records | ||
*/ | ||
sleep?: number; | ||
} | ||
type MatcherFunc = (value: any) => boolean; | ||
declare function generate(options?: Options, callback?: Callback): Generator; | ||
declare function generate(callback?: Callback): Generator; | ||
class Generator extends stream.Readable { | ||
constructor(options?: Options); | ||
readonly options: Options; | ||
} | ||
interface Options { | ||
/** | ||
* Define the number of generated fields and the generation method. | ||
*/ | ||
columns?: number | string[]; | ||
/** | ||
* Set the field delimiter. | ||
*/ | ||
delimiter?: string; | ||
/** | ||
* Period to run in milliseconds. | ||
*/ | ||
duration?: number; | ||
/** | ||
* If specified, then buffers will be decoded to strings using the specified encoding. | ||
*/ | ||
encoding?: string; | ||
/** | ||
* When to stop the generation. | ||
*/ | ||
end?: number | Date; | ||
/** | ||
* One or multiple characters to print at the end of the file; only apply when objectMode is disabled. | ||
*/ | ||
eof?: boolean | string; | ||
/** | ||
* Generate buffers equals length as defined by the `highWaterMark` option. | ||
*/ | ||
fixed_size?: boolean; | ||
fixedSize?: boolean; | ||
/** | ||
* The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. | ||
*/ | ||
high_water_mark?: number; | ||
highWaterMark?: number; | ||
/** | ||
* Number of lines or records to generate. | ||
*/ | ||
length?: number; | ||
/** | ||
* Maximum number of characters per word. | ||
*/ | ||
max_word_length?: number; | ||
maxWordLength?: number; | ||
/** | ||
* Whether this stream should behave as a stream of objects. | ||
*/ | ||
object_mode?: boolean | ||
objectMode?: boolean; | ||
/** | ||
* One or multiple characters used to delimit records. | ||
*/ | ||
row_delimiter?: string; | ||
/** | ||
* Generate idempotent random characters if a number provided. | ||
*/ | ||
seed?: boolean | number; | ||
/** | ||
* The time to wait between the generation of each records | ||
*/ | ||
sleep?: number; | ||
} | ||
} | ||
// export default generate; | ||
export {generate}; |
261
lib/index.js
@@ -9,59 +9,19 @@ | ||
const stream = require('stream') | ||
const util = require('util') | ||
import stream from 'stream'; | ||
import util from 'util'; | ||
module.exports = function(){ | ||
let options | ||
let callback | ||
if(arguments.length === 2){ | ||
options = arguments[0] | ||
callback = arguments[1] | ||
}else if(arguments.length === 1){ | ||
if(typeof arguments[0] === 'function'){ | ||
options = {} | ||
callback = arguments[0] | ||
}else{ | ||
options = arguments[0] | ||
} | ||
}else if(arguments.length === 0){ | ||
options = {} | ||
} | ||
const generator = new Generator(options) | ||
if(callback){ | ||
const data = [] | ||
generator.on('readable', function(){ | ||
let d; while(d = generator.read()){ | ||
data.push(d) | ||
} | ||
}) | ||
generator.on('error', callback) | ||
generator.on('end', function(){ | ||
if(generator.options.objectMode){ | ||
callback(null, data) | ||
}else{ | ||
if(generator.options.encoding){ | ||
callback(null, data.join('')) | ||
}else{ | ||
callback(null, Buffer.concat(data)) | ||
} | ||
} | ||
}) | ||
} | ||
return generator | ||
} | ||
Generator = function(options = {}){ | ||
const Generator = function(options = {}){ | ||
// Convert Stream Readable options if underscored | ||
if(options.high_water_mark){ | ||
options.highWaterMark = options.high_water_mark | ||
options.highWaterMark = options.high_water_mark; | ||
} | ||
if(options.object_mode){ | ||
options.objectMode = options.object_mode | ||
options.objectMode = options.object_mode; | ||
} | ||
// Call parent constructor | ||
stream.Readable.call(this, options) | ||
stream.Readable.call(this, options); | ||
// Clone and camelize options | ||
this.options = {} | ||
for(let k in options){ | ||
this.options[Generator.camelize(k)] = options[k] | ||
this.options = {}; | ||
for(const k in options){ | ||
this.options[Generator.camelize(k)] = options[k]; | ||
} | ||
@@ -82,6 +42,6 @@ // Normalize options | ||
sleep: 0, | ||
} | ||
}; | ||
for(const k in dft){ | ||
if(this.options[k] === undefined){ | ||
this.options[k] = dft[k] | ||
this.options[k] = dft[k]; | ||
} | ||
@@ -91,3 +51,3 @@ } | ||
if(this.options.eof === true){ | ||
this.options.eof = this.options.rowDelimiter | ||
this.options.eof = this.options.rowDelimiter; | ||
} | ||
@@ -100,134 +60,177 @@ // State | ||
count_created: 0, | ||
} | ||
}; | ||
if(typeof this.options.columns === 'number'){ | ||
this.options.columns = new Array(this.options.columns) | ||
this.options.columns = new Array(this.options.columns); | ||
} | ||
const accepted_header_types = Object.keys(Generator).filter( (t) => ( !['super_', 'camelize'].includes(t) )) | ||
const accepted_header_types = Object.keys(Generator).filter((t) => (!['super_', 'camelize'].includes(t))); | ||
for(let i = 0; i < this.options.columns.length; i++){ | ||
const v = this.options.columns[i] || 'ascii' | ||
const v = this.options.columns[i] || 'ascii'; | ||
if(typeof v === 'string'){ | ||
if(!accepted_header_types.includes(v)){ | ||
throw Error(`Invalid column type: got "${v}", default values are ${JSON.stringify(accepted_header_types)}`) | ||
throw Error(`Invalid column type: got "${v}", default values are ${JSON.stringify(accepted_header_types)}`); | ||
} | ||
this.options.columns[i] = Generator[v] | ||
this.options.columns[i] = Generator[v]; | ||
} | ||
} | ||
return this | ||
} | ||
util.inherits(Generator, stream.Readable) | ||
// Export the class | ||
module.exports.Generator = Generator | ||
return this; | ||
}; | ||
util.inherits(Generator, stream.Readable); | ||
// Generate a random number between 0 and 1 with 2 decimals. The function is idempotent if it detect the "seed" option. | ||
Generator.prototype.random = function(){ | ||
if(this.options.seed){ | ||
return this.options.seed = this.options.seed * Math.PI * 100 % 100 / 100 | ||
return this.options.seed = this.options.seed * Math.PI * 100 % 100 / 100; | ||
}else{ | ||
return Math.random() | ||
return Math.random(); | ||
} | ||
} | ||
}; | ||
// Stop the generation. | ||
Generator.prototype.end = function(){ | ||
this.push(null) | ||
} | ||
this.push(null); | ||
}; | ||
// Put new data into the read queue. | ||
Generator.prototype._read = function(size){ | ||
// Already started | ||
const data = [] | ||
let length = this._.fixed_size_buffer.length | ||
const data = []; | ||
let length = this._.fixed_size_buffer.length; | ||
if(length !== 0){ | ||
data.push(this._.fixed_size_buffer) | ||
data.push(this._.fixed_size_buffer); | ||
} | ||
// eslint-disable-next-line | ||
while(true){ | ||
// Time for some rest: flush first and stop later | ||
if( (this._.count_created === this.options.length) || (this.options.end && Date.now() > this.options.end) || (this.options.duration && Date.now() > this._.start_time + this.options.duration) ){ | ||
if((this._.count_created === this.options.length) || (this.options.end && Date.now() > this.options.end) || (this.options.duration && Date.now() > this._.start_time + this.options.duration)){ | ||
// Flush | ||
if(data.length){ | ||
if(this.options.objectMode){ | ||
for(const line of data){ | ||
this.__push(line) | ||
for(const record of data){ | ||
this.__push(record); | ||
} | ||
}else{ | ||
this.__push(data.join('') + (this.options.eof ? this.options.eof : '')) | ||
this.__push(data.join('') + (this.options.eof ? this.options.eof : '')); | ||
} | ||
this._.end = true; | ||
}else{ | ||
this.push(null); | ||
} | ||
// Stop | ||
return this.push(null) | ||
return; | ||
} | ||
// Create the line | ||
let line = [] | ||
let lineLength | ||
// Create the record | ||
let record = []; | ||
let recordLength; | ||
this.options.columns.forEach((fn) => { | ||
line.push(fn(this)) | ||
}) | ||
// for(const header in this.options.columns){ | ||
// // Create the field | ||
// line.push(header(this)) | ||
// } | ||
// Obtain line length | ||
record.push(fn(this)); | ||
}); | ||
// Obtain record length | ||
if(this.options.objectMode){ | ||
lineLength = 0 | ||
for(const column of line) | ||
lineLength += column.length | ||
recordLength = 0; | ||
// recordLength is currently equal to the number of columns | ||
// This is wrong and shall equal to 1 record only | ||
for(const column of record) | ||
recordLength += column.length; | ||
}else{ | ||
// Stringify the line | ||
line = (this._.count_created === 0 ? '' : this.options.rowDelimiter)+line.join(this.options.delimiter) | ||
lineLength = line.length | ||
// Stringify the record | ||
record = (this._.count_created === 0 ? '' : this.options.rowDelimiter)+record.join(this.options.delimiter); | ||
recordLength = record.length; | ||
} | ||
this._.count_created++ | ||
if(length + lineLength > size){ | ||
this._.count_created++; | ||
if(length + recordLength > size){ | ||
if(this.options.objectMode){ | ||
data.push(line) | ||
for(const line of data){ | ||
this.__push(line) | ||
data.push(record); | ||
for(const record of data){ | ||
this.__push(record); | ||
} | ||
}else{ | ||
if(this.options.fixedSize){ | ||
this._.fixed_size_buffer = line.substr(size - length) | ||
data.push(line.substr(0, size - length)) | ||
this._.fixed_size_buffer = record.substr(size - length); | ||
data.push(record.substr(0, size - length)); | ||
}else{ | ||
data.push(line) | ||
data.push(record); | ||
} | ||
this.__push(data.join('')) | ||
this.__push(data.join('')); | ||
} | ||
return | ||
return; | ||
} | ||
length += lineLength | ||
data.push(line) | ||
length += recordLength; | ||
data.push(record); | ||
} | ||
} | ||
}; | ||
// Put new data into the read queue. | ||
Generator.prototype.__push = function(record){ | ||
this._.count_written++ | ||
if(this.options.sleep > 0){ | ||
setTimeout( () => { | ||
this.push(record) | ||
}, this.options.sleep) | ||
}else{ | ||
this.push(record) | ||
} | ||
} | ||
const push = () => { | ||
this._.count_written++; | ||
this.push(record); | ||
if(this._.end === true){ | ||
return this.push(null); | ||
} | ||
}; | ||
this.options.sleep > 0 ? setTimeout(push, this.options.sleep) : push(); | ||
}; | ||
// Generate an ASCII value. | ||
Generator.ascii = function(gen){ | ||
// Column | ||
const column = [] | ||
const nb_chars = Math.ceil(gen.random() * gen.options.maxWordLength) | ||
const column = []; | ||
const nb_chars = Math.ceil(gen.random() * gen.options.maxWordLength); | ||
for(let i=0; i<nb_chars; i++){ | ||
const char = Math.floor(gen.random() * 32) | ||
column.push(String.fromCharCode(char + (char < 16 ? 65 : 97 - 16))) | ||
const char = Math.floor(gen.random() * 32); | ||
column.push(String.fromCharCode(char + (char < 16 ? 65 : 97 - 16))); | ||
} | ||
return column.join('') | ||
} | ||
return column.join(''); | ||
}; | ||
// Generate an integer value. | ||
Generator.int = function(gen){ | ||
return Math.floor(gen.random() * Math.pow(2, 52)) | ||
} | ||
return Math.floor(gen.random() * Math.pow(2, 52)); | ||
}; | ||
// Generate an boolean value. | ||
Generator.bool = function(gen){ | ||
return Math.floor(gen.random() * 2) | ||
} | ||
return Math.floor(gen.random() * 2); | ||
}; | ||
// Camelize option properties | ||
Generator.camelize = function(str){ | ||
return str.replace(/_([a-z])/gi, function(_, match, index){ | ||
return match.toUpperCase() | ||
}) | ||
} | ||
return str.replace(/_([a-z])/gi, function(_, match){ | ||
return match.toUpperCase(); | ||
}); | ||
}; | ||
const generate = function(){ | ||
let options; | ||
let callback; | ||
if(arguments.length === 2){ | ||
options = arguments[0]; | ||
callback = arguments[1]; | ||
}else if(arguments.length === 1){ | ||
if(typeof arguments[0] === 'function'){ | ||
options = {}; | ||
callback = arguments[0]; | ||
}else{ | ||
options = arguments[0]; | ||
} | ||
}else if(arguments.length === 0){ | ||
options = {}; | ||
} | ||
const generator = new Generator(options); | ||
if(callback){ | ||
const data = []; | ||
generator.on('readable', function(){ | ||
let d; while((d = generator.read()) !== null){ | ||
data.push(d); | ||
} | ||
}); | ||
generator.on('error', callback); | ||
generator.on('end', function(){ | ||
if(generator.options.objectMode){ | ||
callback(null, data); | ||
}else{ | ||
if(generator.options.encoding){ | ||
callback(null, data.join('')); | ||
}else{ | ||
callback(null, Buffer.concat(data)); | ||
} | ||
} | ||
}); | ||
} | ||
return generator; | ||
}; | ||
// export default generate | ||
export {generate, Generator}; |
@@ -9,39 +9,42 @@ | ||
const generate = require('.') | ||
import { Generator } from './index.js'; | ||
module.exports = function(options){ | ||
const generate = function(options){ | ||
if(typeof options === 'string' && /\d+/.test(options)){ | ||
options = parseInt(options) | ||
options = parseInt(options); | ||
} | ||
if(Number.isInteger(options)){ | ||
options = {length: options} | ||
options = {length: options}; | ||
}else if(typeof options !== 'object' || options === null){ | ||
throw Error('Invalid Argument: options must be an o object or a integer') | ||
throw Error('Invalid Argument: options must be an object or an integer'); | ||
} | ||
if(!Number.isInteger(options.length)){ | ||
throw Error('Invalid Argument: length is not defined') | ||
throw Error('Invalid Argument: length is not defined'); | ||
} | ||
const chunks = [] | ||
let work = true | ||
const chunks = []; | ||
let work = true; | ||
// See https://nodejs.org/api/stream.html#stream_new_stream_readable_options | ||
options.highWaterMark = options.objectMode ? 16 : 16384 | ||
const generator = new generate.Generator(options) | ||
options.highWaterMark = options.objectMode ? 16 : 16384; | ||
const generator = new Generator(options); | ||
generator.push = function(chunk){ | ||
if(chunk === null){ | ||
return work = false | ||
return work = false; | ||
} | ||
if(options.objectMode){ | ||
chunks.push(chunk) | ||
chunks.push(chunk); | ||
}else{ | ||
chunks.push(chunk) | ||
chunks.push(chunk); | ||
} | ||
} | ||
}; | ||
while(work){ | ||
generator._read(options.highWaterMark) | ||
generator._read(options.highWaterMark); | ||
} | ||
if(!options.objectMode){ | ||
return chunks.join('') | ||
return chunks.join(''); | ||
}else{ | ||
return chunks | ||
return chunks; | ||
} | ||
} | ||
}; | ||
// export default generate | ||
export {generate}; |
110
package.json
{ | ||
"version": "3.4.3", | ||
"version": "4.0.0", | ||
"name": "csv-generate", | ||
@@ -11,65 +11,81 @@ "description": "CSV and object generation implementing the Node.js `stream.Readable` API", | ||
], | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "http://www.github.com/adaltas/node-csv-generate" | ||
}, | ||
"homepage": "https://csv.js.org/generate/", | ||
"bugs": "https://github.com/adaltas/node-csv-generate/issues", | ||
"author": "David Worms <david@adaltas.com> (https://www.adaltas.com)", | ||
"coffeelintConfig": { | ||
"indentation": { | ||
"level": "error", | ||
"value": 2 | ||
}, | ||
"line_endings": { | ||
"level": "error", | ||
"value": "unix" | ||
}, | ||
"max_line_length": { | ||
"level": "ignore" | ||
} | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.14.8", | ||
"@babel/core": "^7.15.0", | ||
"@babel/preset-env": "^7.15.0", | ||
"@rollup/plugin-eslint": "^8.0.1", | ||
"@rollup/plugin-node-resolve": "^13.0.6", | ||
"@types/mocha": "^9.0.0", | ||
"@types/node": "^16.7.8", | ||
"@types/node": "^16.11.7", | ||
"@types/should": "^13.0.0", | ||
"babelify": "^10.0.0", | ||
"browserify": "^17.0.0", | ||
"coffeescript": "~2.5.1", | ||
"coffeescript": "~2.6.1", | ||
"each": "^1.2.2", | ||
"mocha": "~9.1.1", | ||
"eslint": "^8.2.0", | ||
"mocha": "~9.1.3", | ||
"rollup": "^2.60.0", | ||
"rollup-plugin-node-builtins": "^2.1.2", | ||
"rollup-plugin-node-globals": "^1.4.0", | ||
"should": "~13.2.3", | ||
"ts-node": "^10.2.1", | ||
"typescript": "^4.4.2" | ||
"ts-node": "^10.4.0", | ||
"typescript": "^4.4.4" | ||
}, | ||
"exports": { | ||
".": { | ||
"import": "./lib/index.js", | ||
"require": "./dist/cjs/index.cjs" | ||
}, | ||
"./sync": { | ||
"import": "./lib/sync.js", | ||
"require": "./dist/cjs/sync.cjs" | ||
} | ||
}, | ||
"files": [ | ||
"/lib" | ||
"dist", | ||
"lib", | ||
"samples" | ||
], | ||
"main": "./lib", | ||
"homepage": "https://csv.js.org/generate/", | ||
"license": "MIT", | ||
"main": "./dist/cjs/index.cjs", | ||
"mocha": { | ||
"throw-deprecation": true, | ||
"inline-diffs": true, | ||
"loader": "./test/loaders/all.mjs", | ||
"recursive": true, | ||
"reporter": "spec", | ||
"require": [ | ||
"should", | ||
"coffeescript/register", | ||
"ts-node/register" | ||
"should" | ||
], | ||
"inline-diffs": true, | ||
"timeout": 40000, | ||
"reporter": "spec", | ||
"recursive": true | ||
"throw-deprecation": true, | ||
"timeout": 40000 | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/adaltas/node-csv.git", | ||
"directory": "packages/csv-generate" | ||
}, | ||
"scripts": { | ||
"build:babel": "cd lib && babel *.js -d es5 && cd ..", | ||
"build:browserify": "browserify lib/index.js --transform babelify --standalone parse > lib/browser/index.js && browserify lib/sync.js --transform babelify --standalone parse > lib/browser/sync.js", | ||
"build": "npm run build:babel && npm run build:browserify", | ||
"preversion": "cp lib/*.ts lib/es5 && git add lib/es5/*.ts", | ||
"build": "npm run build:rollup && npm run build:ts", | ||
"build:rollup": "npx rollup -c", | ||
"build:ts": "cp lib/*.ts dist/cjs && cp lib/*.ts dist/esm", | ||
"lint": "npm run lint:lib && npm run lint:samples && npm run lint:test", | ||
"lint:lib": "eslint --fix lib/*.js", | ||
"lint:samples": "eslint --fix samples/*.js", | ||
"lint:test": "coffeelint --fix test/*.coffee", | ||
"preversion": "npm run build && git add dist", | ||
"pretest": "npm run build", | ||
"test": "mocha test/**/*.{coffee,ts}" | ||
"test": "mocha 'test/**/*.{coffee,ts}'", | ||
"test:legacy": "mocha --loader=./test/loaders/legacy/all.mjs 'test/**/*.{coffee,ts}'" | ||
}, | ||
"types": "./lib/index.d.ts", | ||
"gitHead": "0fd5209b6862655c384cda052abf38019b959e70" | ||
"type": "module", | ||
"types": "dist/esm/index.d.ts", | ||
"typesVersions": { | ||
"*": { | ||
".": [ | ||
"dist/esm/index.d.ts" | ||
], | ||
"sync": [ | ||
"dist/esm/sync.d.ts" | ||
] | ||
} | ||
}, | ||
"gitHead": "d95c35dc7fd698e8e3278f539c8f1d43fb77640b" | ||
} |
[![Build Status](https://api.travis-ci.org/adaltas/node-csv-generate.svg)](https://travis-ci.org/#!/adaltas/node-csv-generate) [![NPM](https://img.shields.io/npm/dm/csv-generate)](https://www.npmjs.com/package/csv-generate) [![NPM](https://img.shields.io/npm/v/csv-generate)](https://www.npmjs.com/package/csv-generate) | ||
# CSV generator for Node.js and the web | ||
# CSV and object generation | ||
[![Build Status](https://img.shields.io/github/workflow/status/adaltas/node-csv/Node.js)](https://github.com/adaltas/node-csv/actions) | ||
[![NPM](https://img.shields.io/npm/dm/csv-generate)](https://www.npmjs.com/package/csv-generate) | ||
[![NPM](https://img.shields.io/npm/v/csv-generate)](https://www.npmjs.com/package/csv-generate) | ||
This package provides a flexible generator of CSV strings and Javascript objects | ||
implementing the Node.js `stream.Readable` API. | ||
The [`csv-generate` package](https://csv.js.org/generate/) provides a flexible generator of random CSV strings and Javascript objects implementing the Node.js `stream.Readable` API. It is part of the [CSV project](https://csv.js.org/). | ||
[Documentation for the "csv-generate" package is available here](https://csv.js.org/generate/). | ||
## Documentation | ||
* [Project homepage](http://csv.js.org/generate/) | ||
* [API](http://csv.js.org/generate/api/) | ||
* [Options](http://csv.js.org/generate/options/) | ||
* [Examples](http://csv.js.org/generate/examples/) | ||
* [Project homepage](https://csv.js.org/generate/) | ||
* [API](https://csv.js.org/generate/api/) | ||
* [Options](https://csv.js.org/generate/options/) | ||
* [Examples](https://csv.js.org/generate/examples/) | ||
@@ -31,4 +30,39 @@ ## Main features | ||
Use the callback style API for simplicity or the stream based API for scalability. | ||
Use the callback and sync APIs for simplicity or the stream based API for scalability. | ||
## Example | ||
The [API](https://csv.js.org/generate/api/) is available in multiple flavors. This example illustrates the stream API. | ||
```js | ||
import { generate } from 'csv-generate'; | ||
import assert from 'assert'; | ||
const records = []; | ||
// Initialize the generator | ||
generate({ | ||
seed: 1, | ||
objectMode: true, | ||
columns: 2, | ||
length: 2 | ||
}) | ||
// Use the readable stream api to consume generated records | ||
.on('readable', function(){ | ||
let record; while((record = this.read()) !== null){ | ||
records.push(record); | ||
} | ||
}) | ||
// Catch any error | ||
.on('error', function(err){ | ||
console.error(err); | ||
}) | ||
// Test that the generated records matched the expected records | ||
.on('end', function(){ | ||
assert.deepEqual(records, [ | ||
[ 'OMH', 'ONKCHhJmjadoA' ], | ||
[ 'D', 'GeACHiN' ] | ||
]); | ||
}); | ||
``` | ||
## Development | ||
@@ -44,2 +78,4 @@ | ||
The project is sponsored by [Adaltas](https://www.adaltas.com), an Big Data consulting firm based in Paris, France. | ||
* David Worms: <https://github.com/wdavidw> |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
1422943
25
36613
80
0
1
Yes
15