UNPKG

20.5 kBJavaScriptView Raw
1#!/usr/local/bin/node
2
3const NOPE= function (){};
4
5var dyngo= require('./index'),
6 async= require('async'),
7 fs= require('fs'),
8 csv = require('csv'),
9 xlsx = require('./lib/xlsx'),
10 carrier= require('carrier'),
11 util= require('util'),
12 readline= require('readline'),
13 _= require('underscore'),
14 path= require('path').join,
15 colors = require('colors'),
16 GSON = require('gson'),
17 coffee= require('coffee-script'),
18 AWS = require('aws-sdk');
19
20var argv = require('optimist').argv;
21
22var _history= [];
23
24const _json= function (path,content)
25 {
26 try
27 {
28 if (!content)
29 return JSON.parse(fs.readFileSync(path,'utf8'));
30 else
31 {
32 fs.writeFileSync(path,JSON.stringify(content,null,2),'utf8')
33 return { success: function (fn) { process.nextTick(fn); } };
34 }
35 }
36 catch (ex)
37 {
38 console.log((ex+'').red);
39 }
40 },
41 _gson= function (path,content)
42 {
43 try
44 {
45 if (!content)
46 return GSON.parse(fs.readFileSync(path,'utf8'));
47 else
48 {
49 fs.writeFileSync(path,GSON.stringify(content),'utf8')
50 return { success: function (fn) { process.nextTick(fn); } };
51 }
52 }
53 catch (ex)
54 {
55 console.log((ex+'').red);
56 }
57 },
58 _toJSON= function (fields,_transformFnc)
59 {
60 var r= [];
61
62 this.forEach(function (row,idx)
63 {
64 var obj= {},
65 _val= function (field,value)
66 {
67 var r,
68 path= field.split('.'),
69 current= obj;
70
71 for (var i=0;i<path.length-1;i++)
72 current= current[path[i]]= current[path[i]] || {};
73
74 current[path[path.length-1]]= value;
75 };
76
77 for (var i=0;i<fields.length;i++)
78 _val(fields[i],row[i]);
79
80 if (_transformFnc)
81 obj= _transformFnc(obj,idx);
82
83 if (Array.isArray(obj))
84 r.concat(obj);
85 else
86 if (obj)
87 r.push(obj);
88 });
89
90 return r;
91 },
92 _csv= function (dyn, path, opts, cols, tfnc)
93 {
94 var raster= [],
95 promise= dyn.promise(['end','results']),
96 count= 0;
97
98 raster.toJSON= _toJSON;
99
100 csv()
101 .from.path(path, opts)
102 .on('record',function (row,index)
103 {
104 process.stdout.write(('\r'+(count++)).yellow);
105 raster.push(row);
106 })
107 .on('end',function (count)
108 {
109 console.log(('\r'+count).green);
110 promise.trigger.results(raster.toJSON(cols,tfnc));
111 promise.trigger.end();
112 })
113 .on('error', promise.error);
114
115 return promise;
116 },
117 _xlsx= function (src)
118 {
119 var b64= fs.readFileSync(src, "base64"),
120 workbook= xlsx.decode(b64);
121
122 workbook.sheet= function (name)
123 {
124 var worksheet;
125
126 this.worksheets.forEach(function (s)
127 {
128 if (s.name==name)
129 {
130 worksheet= s;
131 return false;
132 }
133 });
134
135 return worksheet;
136 }
137
138 workbook.worksheets.forEach(function (s)
139 {
140 s.toJSON= function (fields,_transformFnc)
141 {
142 var r= [];
143
144 this.data.forEach(function (row,idx)
145 {
146 var obj= {},
147 _nnan= function (v) { return v===0 ? v : (!!v ? v : '') },
148 _value= function (value)
149 {
150 if (value)
151 return _nnan(value.value);
152 else
153 return '';
154 },
155 _val= function (field,value)
156 {
157 var r,
158 path= field.split('.'),
159 current= obj;
160
161 for (var i=0;i<path.length-1;i++)
162 current= current[path[i]]= current[path[i]] || {};
163
164 current[path[path.length-1]]= _value(value);
165 };
166
167 for (var i=0;i<fields.length;i++)
168 _val(fields[i],row[i]);
169
170 if (_transformFnc)
171 obj= _transformFnc(obj,idx);
172
173 if (Array.isArray(obj))
174 r.concat(obj);
175 else
176 if (obj)
177 r.push(obj);
178 });
179
180 return r;
181 }
182 });
183
184 return workbook;
185 },
186 _eval= function (cmd,db,last,tx)
187 {
188 var __csv= function (path, opts, cols, tfnc) { var args= Array.prototype.slice.apply(arguments); args.unshift(db._dyn); return _csv.apply(null,args); };
189
190 try
191 {
192 return eval('(function (db,tx,fs,last,_,json,gson,csv,xlsx,argv){ return '+cmd+'; })')(db,tx,fs,last,_,_json,_gson,__csv,_xlsx,argv);
193 }
194 catch (ex)
195 {
196 if (ex instanceof SyntaxError||ex instanceof ReferenceError)
197 return coffee.eval('((global,db,tx,fs,last,_,json,gson,csv,xlsx,argv) -> '+cmd+')')(global,db,tx,fs,last,_,_json,_gson,__csv,_xlsx,argv);
198 else
199 throw ex;
200 }
201 },
202 _dobatch= function (db,lines,done)
203 {
204 var last, tx;
205
206 return function ()
207 {
208 async.forEachSeries(lines,
209 function (cmd,done)
210 {
211 console.log(cmd);
212
213 var promise= _eval(cmd,db,last,tx);
214
215 if (promise==undefined||!(promise.result||promise.success||promise.error||promise.notfound))
216 done();
217 else
218 {
219 if (promise.notfound)
220 promise.notfound(function ()
221 {
222 last= undefined;
223 done();
224 });
225 else
226 if (promise.error)
227 promise.error(function (err)
228 {
229 console.log((err+'').red,err.stack);
230 done();
231 });
232
233 if (promise.transaction)
234 promise.transaction(function (_tx)
235 {
236 tx= _tx;
237 console.log(('tx: '+tx._id).green);
238 done();
239 });
240 else
241 if (promise.result)
242 promise.result(function (res)
243 {
244 last= res;
245 done();
246 });
247 else
248 if (promise.success)
249 promise.success(function ()
250 {
251 console.log('done!'.green);
252 done();
253 });
254 }
255
256
257 },done);
258 };
259 },
260 _doinput= function (db,cb)
261 {
262 var _lines= [];
263
264 carrier.carry(process.stdin, function (line)
265 {
266 _lines.push(line);
267 },'utf8');
268
269 process.stdin.on('end',function ()
270 {
271 process.nextTick(function ()
272 {
273 _dobatch(db,_lines,
274 function (err)
275 {
276 if (err)
277 {
278 console.log(err.message.red,err.stack);
279 process.exit(1);
280 }
281 else
282 process.exit(0);
283 })();
284 });
285 });
286
287 process.stdin.resume();
288
289 // if we have no input go to interactive mode
290 setTimeout(function () { if (_lines.length==0) cb(); },100);
291 },
292 _dorc= function (db,cb)
293 {
294 var rcFile= path(getUserHome(),'.dyngorc'),
295 localRcFile= '.dyngorc',
296 _file= function (f, done)
297 {
298 var _lines= [];
299
300 if (fs.existsSync(f))
301 {
302 console.log(('executing '+f+'...').green);
303 var rstream= fs.createReadStream(f, { encoding: 'utf8' });
304
305 rstream.on('end',function ()
306 {
307 process.nextTick(function ()
308 {
309 _dobatch(db,_lines,done)();
310 });
311 });
312
313 carrier.carry(rstream,function (line)
314 {
315 _lines.push(line);
316 });
317 }
318 else
319 done();
320 };
321
322 _file(rcFile,function (err)
323 {
324 if (err)
325 {
326 console.log(err.message.red,err.stack);
327 process.exit(1);
328 }
329 else
330 if (localRcFile!=rcFile)
331 _file(localRcFile,function (err)
332 {
333 if (err)
334 {
335 console.log(err.message.red,err.stack);
336 process.exit(1);
337 }
338 else
339 cb();
340 });
341 else
342 cb();
343 });
344 },
345 getUserHome= function()
346 {
347 return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'];
348 },
349 getHistory= function()
350 {
351 var historyFile= path(getUserHome(),'.dyngodb_history');
352
353 try
354 {
355
356 if (fs.existsSync(historyFile))
357 _history.push
358 .apply(_history,JSON.parse(fs.readFileSync(historyFile,'utf8')));
359
360 }
361 catch(ex)
362 {}
363
364 return _history;
365 },
366 saveHistory= function ()
367 {
368 var historyFile= path(getUserHome(),'.dyngodb_history');
369
370 if (_history&&_history.length>0)
371 fs.writeFileSync(historyFile,JSON.stringify(_history),'utf8');
372 },
373 _collect= function (consume)
374 {
375 return function (cons)
376 {
377 _.keys(cons).forEach(function (table)
378 {
379 var c, tcons= cons[table];
380
381 if (!(c=consume[table]))
382 c= consume[table]= { read: 0, write: 0 };
383
384 c.read+= tcons.read;
385 c.write+= tcons.write;
386 });
387 };
388 };
389
390process.on('exit', saveHistory);
391process.on('SIGINT', function () { saveHistory(); process.exit(0); });
392process.stdin.pause();
393
394var args= [function (err,db)
395{
396 var last, tx;
397
398 if (err)
399 console.log(err);
400 else
401 {
402
403 _dorc(db,function ()
404 {
405 _doinput(db,function()
406 {
407 var rl = readline.createInterface
408 ({
409 input: process.stdin,
410 output: process.stdout,
411 completer: function (linePartial, cb)
412 {
413 if (linePartial.indexOf('db.')==0)
414 {
415 var tables= _.collect(_.filter(_.keys(db),
416 function (key) { return key.indexOf(linePartial.replace('db.',''))==0; }),
417 function (res) { return 'db.'+res; });
418 cb(null,[tables, linePartial]);
419 }
420 else
421 cb(null,[[], linePartial]);
422 }
423 });
424
425 rl.history= getHistory();
426
427 (function ask()
428 {
429 var _ask= function (fn)
430 {
431 return function ()
432 {
433 var args= arguments;
434 fn.apply(null,args);
435 ask();
436 };
437 },
438 _print= function (obj,cb)
439 {
440 if (obj._old||(obj[0]&&obj[0]._old))
441 db.cleanup(obj).clean(function (obj)
442 {
443 console.log(util.inspect(obj,{ depth: null }));
444 cb();
445 });
446 else
447 {
448 console.log(util.inspect(obj,{ depth: null }));
449 cb();
450 }
451 };
452
453 rl.question('> ', function (answer)
454 {
455
456 if (!answer) { ask(); return; };
457
458 if (answer.indexOf('clean ')==0)
459 {
460 var target= answer.substring(6);
461
462 answer= 'db.cleanup('+target+')';
463 }
464
465 if (answer.indexOf('show collections') > -1)
466 {
467 _.filter(_.keys(db),function (key) { return !!db[key].find; }).forEach(function (c) { console.log(c); });
468 ask();
469 return;
470 }
471 else
472 if (answer=='clear')
473 {
474 process.stdout.write('\u001B[2J\u001B[0;0f');
475 ask();
476 return;
477 }
478 else
479 if (answer=='exit')
480 {
481 process.exit(0);
482 return;
483 }
484
485 try
486 {
487 var time= process.hrtime(),
488 promise= _eval(answer,db,last,tx),
489 end,
490 printed,
491 chunks= 0,
492 consume= { read: 0, write: 0 },
493 _doneres= function () { elapsed(); ask(); },
494 doneres= _.wrap(_doneres,function (done) { if (printed&&end) done(); }),
495 elapsed= function ()
496 {
497 var diff= process.hrtime(time),
498 secs= (diff[0]*1e9+diff[1])/1e9;
499
500 _.keys(consume).forEach(function (table)
501 {
502 var tcons= consume[table], s= secs<1 ? 1 : secs;
503
504 if (tcons.read)
505 console.log(('consumed read capacity['+table+']: '+tcons.read+' ('+(tcons.read/s)+' read/sec)').green);
506
507 if (tcons.write)
508 console.log(('consumed write capacity['+table+']: '+tcons.write+' ('+(tcons.write/s)+' write/sec)').green);
509 });
510
511 if (chunks) console.log((chunks+' roundtrips').green);
512 console.log((secs+' secs').green);
513 };
514
515 if (promise==_||promise===false||promise===undefined||promise.createCollection)
516 {
517 _ask(function () { console.log(promise); })();
518 return;
519 }
520
521 promise= promise || {};
522
523 if (promise.consumed)
524 promise.consumed(_collect(consume));
525
526 if (promise.error)
527 promise.error(_ask(function (err)
528 {
529 if (!err) return;
530
531 if (err.code=='notfound')
532 console.log('no data found'.yellow);
533 else
534 if (err.code=='exists')
535 console.log('The item already exists'.red);
536 else
537 if (err.code=='updatedsinceread')
538 console.log('The item is changed since you read it'.red);
539 else
540 console.log((err+'').red,err.stack);
541 }));
542
543 if (promise.end)
544 promise.end(function () { end= true; doneres(); });
545
546 if (promise.count)
547 promise.count(_ask(function (count) { console.log(('\r'+count).green); elapsed(); }));
548
549 if (promise.transaction)
550 promise.transaction(function (_tx) { tx= _tx; console.log(('tx: '+tx._id).green); elapsed(); ask(); });
551 else
552 if (promise.committed)
553 promise.committed(function () { tx= undefined; console.log('transaction committed'.green); elapsed(); ask(); });
554 else
555 if (promise.rolledback)
556 promise.rolledback(function (competing) { tx= undefined; if (competing) console.log('transaction rolled back'.red); else console.log('transaction rolled back'.green); elapsed(); ask(); });
557 else
558 if (promise.clean)
559 promise.clean(function (obj) { console.log(util.inspect(obj,{ depth: null })); ask(); });
560 else
561 if (promise.result)
562 {
563 last= undefined;
564 promise.result(function (obj) { last= obj; _print(obj,function () { elapsed(); ask(); }); });
565 }
566 else
567 if (promise.results)
568 {
569 last= [];
570 promise.results(function (items)
571 {
572 chunks++;
573 printed= false;
574
575 last.push.apply(last,items);
576
577 _print(items,function ()
578 {
579 printed= true;
580 doneres();
581 });
582 });
583 }
584 else
585 if (promise.success)
586 promise.success(_ask(function () { console.log('done!'.green); elapsed(); }));
587 else
588 _ask(function () { console.log(util.inspect(promise,{ depth: null })); })();
589 }
590 catch (ex)
591 {
592 console.log('unknown command'.red,ex,ex.stack);
593 ask();
594 }
595
596 //rl.close();
597 });
598 })();
599 });
600 });
601 }
602}];
603
604if (argv.local)
605 args.unshift({ dynamo: { endpoint: new AWS.Endpoint('http://localhost:8000') } });
606
607dyngo.apply(null,args);