@@ -10,20 +10,64 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
10
10
var stream__default = /*#__PURE__*/ _interopDefaultLegacy ( stream ) ;
11
11
var util__default = /*#__PURE__*/ _interopDefaultLegacy ( util ) ;
12
12
13
- const Generator = function ( options = { } ) {
13
+ const init_state = ( options ) => {
14
+ // State
15
+ return {
16
+ start_time : options . duration ? Date . now ( ) : null ,
17
+ fixed_size_buffer : '' ,
18
+ count_written : 0 ,
19
+ count_created : 0 ,
20
+ } ;
21
+ } ;
22
+
23
+ // Generate a random number between 0 and 1 with 2 decimals. The function is idempotent if it detect the "seed" option.
24
+ const random = function ( options = { } ) {
25
+ if ( options . seed ) {
26
+ return options . seed = options . seed * Math . PI * 100 % 100 / 100 ;
27
+ } else {
28
+ return Math . random ( ) ;
29
+ }
30
+ } ;
31
+
32
+ const types = {
33
+ // Generate an ASCII value.
34
+ ascii : function ( { options} ) {
35
+ const column = [ ] ;
36
+ const nb_chars = Math . ceil ( random ( options ) * options . maxWordLength ) ;
37
+ for ( let i = 0 ; i < nb_chars ; i ++ ) {
38
+ const char = Math . floor ( random ( options ) * 32 ) ;
39
+ column . push ( String . fromCharCode ( char + ( char < 16 ? 65 : 97 - 16 ) ) ) ;
40
+ }
41
+ return column . join ( '' ) ;
42
+ } ,
43
+ // Generate an integer value.
44
+ int : function ( { options} ) {
45
+ return Math . floor ( random ( options ) * Math . pow ( 2 , 52 ) ) ;
46
+ } ,
47
+ // Generate an boolean value.
48
+ bool : function ( { options} ) {
49
+ return Math . floor ( random ( options ) * 2 ) ;
50
+ }
51
+ } ;
52
+
53
+ const camelize = function ( str ) {
54
+ return str . replace ( / _ ( [ a - z ] ) / gi, function ( _ , match ) {
55
+ return match . toUpperCase ( ) ;
56
+ } ) ;
57
+ } ;
58
+
59
+ const normalize_options = ( opts ) => {
14
60
// Convert Stream Readable options if underscored
15
- if ( options . high_water_mark ) {
16
- options . highWaterMark = options . high_water_mark ;
61
+ if ( opts . high_water_mark ) {
62
+ opts . highWaterMark = opts . high_water_mark ;
17
63
}
18
- if ( options . object_mode ) {
19
- options . objectMode = options . object_mode ;
64
+ if ( opts . object_mode ) {
65
+ opts . objectMode = opts . object_mode ;
20
66
}
21
- // Call parent constructor
22
- stream__default [ "default" ] . Readable . call ( this , options ) ;
23
67
// Clone and camelize options
24
- this . options = { } ;
25
- for ( const k in options ) {
26
- this . options [ Generator . camelize ( k ) ] = options [ k ] ;
68
+ const options = { } ;
69
+ for ( const k in opts ) {
70
+ options [ camelize ( k ) ] = opts [ k ] ;
27
71
}
28
72
// Normalize options
29
73
const dft = {
@@ -41,153 +85,142 @@ const Generator = function(options = {}){
41
85
sleep : 0 ,
42
86
} ;
43
87
for ( const k in dft ) {
44
- if ( this . options [ k ] === undefined ) {
45
- this . options [ k ] = dft [ k ] ;
88
+ if ( options [ k ] === undefined ) {
89
+ options [ k ] = dft [ k ] ;
46
90
}
47
91
}
48
92
// Default values
49
- if ( this . options . eof === true ) {
50
- this . options . eof = this . options . rowDelimiter ;
93
+ if ( options . eof === true ) {
94
+ options . eof = options . rowDelimiter ;
51
95
}
52
- // State
53
- this . _ = {
54
- start_time : this . options . duration ? Date . now ( ) : null ,
55
- fixed_size_buffer : '' ,
56
- count_written : 0 ,
57
- count_created : 0 ,
58
- } ;
59
- if ( typeof this . options . columns === 'number' ) {
60
- this . options . columns = new Array ( this . options . columns ) ;
96
+ if ( typeof options . columns === 'number' ) {
97
+ options . columns = new Array ( options . columns ) ;
61
98
}
62
- const accepted_header_types = Object . keys ( Generator ) . filter ( ( t ) => ( ! [ 'super_' , 'camelize' ] . includes ( t ) ) ) ;
63
- for ( let i = 0 ; i < this . options . columns . length ; i ++ ) {
64
- const v = this . options . columns [ i ] || 'ascii' ;
99
+ const accepted_header_types = Object . keys ( types ) . filter ( ( t ) => ( ! [ 'super_' , 'camelize' ] . includes ( t ) ) ) ;
100
+ for ( let i = 0 ; i < options . columns . length ; i ++ ) {
101
+ const v = options . columns [ i ] || 'ascii' ;
65
102
if ( typeof v === 'string' ) {
66
103
if ( ! accepted_header_types . includes ( v ) ) {
67
104
throw Error ( `Invalid column type: got "${ v } ", default values are ${ JSON . stringify ( accepted_header_types ) } ` ) ;
68
105
}
69
- this . options . columns [ i ] = Generator [ v ] ;
106
+ options . columns [ i ] = types [ v ] ;
70
107
}
71
108
}
72
- return this ;
109
+ return options ;
73
110
} ;
74
- util__default [ "default" ] . inherits ( Generator , stream__default [ "default" ] . Readable ) ;
75
111
76
- // Generate a random number between 0 and 1 with 2 decimals. The function is idempotent if it detect the "seed" option.
77
- Generator . prototype . random = function ( ) {
78
- if ( this . options . seed ) {
79
- return this . options . seed = this . options . seed * Math . PI * 100 % 100 / 100 ;
80
- } else {
81
- return Math . random ( ) ;
82
- }
83
- } ;
84
- // Stop the generation.
85
- Generator . prototype . end = function ( ) {
86
- this . push ( null ) ;
87
- } ;
88
- // Put new data into the read queue.
89
- Generator . prototype . _read = function ( size ) {
112
+ const read = ( options , state , size , push , close ) => {
90
113
// Already started
91
114
const data = [ ] ;
92
- let length = this . _ . fixed_size_buffer . length ;
115
+ let length = state . fixed_size_buffer . length ;
93
116
if ( length !== 0 ) {
94
- data . push ( this . _ . fixed_size_buffer ) ;
117
+ data . push ( state . fixed_size_buffer ) ;
95
118
}
96
119
// eslint-disable-next-line
97
120
while ( true ) {
98
121
// Time for some rest: flush first and stop later
99
- 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 ) ) {
122
+ if ( ( state . count_created === options . length ) || ( options . end && Date . now ( ) > options . end ) || ( options . duration && Date . now ( ) > state . start_time + options . duration ) ) {
100
123
// Flush
101
124
if ( data . length ) {
102
- if ( this . options . objectMode ) {
125
+ if ( options . objectMode ) {
103
126
for ( const record of data ) {
104
- this . __push ( record ) ;
127
+ push ( record ) ;
105
128
}
106
129
} else {
107
- this . __push ( data . join ( '' ) + ( this . options . eof ? this . options . eof : '' ) ) ;
130
+ push ( data . join ( '' ) + ( options . eof ? options . eof : '' ) ) ;
108
131
}
109
- this . _ . end = true ;
132
+ state . end = true ;
110
133
} else {
111
- this . push ( null ) ;
134
+ close ( ) ;
112
135
}
113
136
return ;
114
137
}
115
138
// Create the record
116
139
let record = [ ] ;
117
140
let recordLength ;
118
- this . options . columns . forEach ( ( fn ) => {
119
- record . push ( fn ( this ) ) ;
141
+ options . columns . forEach ( ( fn ) => {
142
+ const result = fn ( { options : options , state : state } ) ;
143
+ const type = typeof result ;
144
+ if ( result !== null && type !== 'string' && type !== 'number' ) {
145
+ throw Error ( [
146
+ 'INVALID_VALUE:' ,
147
+ 'values returned by column function must be' ,
148
+ 'a string, a number or null,' ,
149
+ `got ${ JSON . stringify ( result ) } `
150
+ ] . join ( ' ' ) ) ;
151
+ }
152
+ record . push ( result ) ;
120
153
} ) ;
121
154
// Obtain record length
122
- if ( this . options . objectMode ) {
155
+ if ( options . objectMode ) {
123
156
recordLength = 0 ;
124
157
// recordLength is currently equal to the number of columns
125
158
// This is wrong and shall equal to 1 record only
126
- for ( const column of record )
159
+ for ( const column of record ) {
127
160
recordLength += column . length ;
161
+ }
128
162
} else {
129
163
// Stringify the record
130
- record = ( this . _ . count_created === 0 ? '' : this . options . rowDelimiter ) + record . join ( this . options . delimiter ) ;
164
+ record = ( state . count_created === 0 ? '' : options . rowDelimiter ) + record . join ( options . delimiter ) ;
131
165
recordLength = record . length ;
132
166
}
133
- this . _ . count_created ++ ;
167
+ state . count_created ++ ;
134
168
if ( length + recordLength > size ) {
135
- if ( this . options . objectMode ) {
169
+ if ( options . objectMode ) {
136
170
data . push ( record ) ;
137
171
for ( const record of data ) {
138
- this . __push ( record ) ;
172
+ push ( record ) ;
139
173
}
140
174
} else {
141
- if ( this . options . fixedSize ) {
142
- this . _ . fixed_size_buffer = record . substr ( size - length ) ;
175
+ if ( options . fixedSize ) {
176
+ state . fixed_size_buffer = record . substr ( size - length ) ;
143
177
data . push ( record . substr ( 0 , size - length ) ) ;
144
178
} else {
145
179
data . push ( record ) ;
146
180
}
147
- this . __push ( data . join ( '' ) ) ;
181
+ push ( data . join ( '' ) ) ;
148
182
}
149
183
return ;
150
184
}
151
185
length += recordLength ;
152
186
data . push ( record ) ;
153
187
}
154
188
} ;
189
+
190
+ const Generator = function ( options = { } ) {
191
+ this . options = normalize_options ( options ) ;
192
+ // Call parent constructor
193
+ stream__default [ "default" ] . Readable . call ( this , this . options ) ;
194
+ this . state = init_state ( this . options ) ;
195
+ return this ;
196
+ } ;
197
+ util__default [ "default" ] . inherits ( Generator , stream__default [ "default" ] . Readable ) ;
198
+
199
+ // Stop the generation.
200
+ Generator . prototype . end = function ( ) {
201
+ this . push ( null ) ;
202
+ } ;
203
+ // Put new data into the read queue.
204
+ Generator . prototype . _read = function ( size ) {
205
+ const self = this ;
206
+ read ( this . options , this . state , size , function ( chunk ) {
207
+ self . __push ( chunk ) ;
208
+ } , function ( ) {
209
+ self . push ( null ) ;
210
+ } ) ;
211
+ } ;
155
212
// Put new data into the read queue.
156
213
Generator . prototype . __push = function ( record ) {
214
+ // console.log('push', record)
157
215
const push = ( ) => {
158
- this . _ . count_written ++ ;
216
+ this . state . count_written ++ ;
159
217
this . push ( record ) ;
160
- if ( this . _ . end === true ) {
218
+ if ( this . state . end === true ) {
161
219
return this . push ( null ) ;
162
220
}
163
221
} ;
164
222
this . options . sleep > 0 ? setTimeout ( push , this . options . sleep ) : push ( ) ;
165
223
} ;
166
- // Generate an ASCII value.
167
- Generator . ascii = function ( gen ) {
168
- // Column
169
- const column = [ ] ;
170
- const nb_chars = Math . ceil ( gen . random ( ) * gen . options . maxWordLength ) ;
171
- for ( let i = 0 ; i < nb_chars ; i ++ ) {
172
- const char = Math . floor ( gen . random ( ) * 32 ) ;
173
- column . push ( String . fromCharCode ( char + ( char < 16 ? 65 : 97 - 16 ) ) ) ;
174
- }
175
- return column . join ( '' ) ;
176
- } ;
177
- // Generate an integer value.
178
- Generator . int = function ( gen ) {
179
- return Math . floor ( gen . random ( ) * Math . pow ( 2 , 52 ) ) ;
180
- } ;
181
- // Generate an boolean value.
182
- Generator . bool = function ( gen ) {
183
- return Math . floor ( gen . random ( ) * 2 ) ;
184
- } ;
185
- // Camelize option properties
186
- Generator . camelize = function ( str ) {
187
- return str . replace ( / _ ( [ a - z ] ) / gi, function ( _ , match ) {
188
- return match . toUpperCase ( ) ;
189
- } ) ;
190
- } ;
191
224
192
225
const generate = function ( ) {
193
226
let options ;
0 commit comments