Skip to content

Instantly share code, notes, and snippets.

@egm0121
Last active January 15, 2021 14:57
Show Gist options
  • Save egm0121/0913b778953ee16fc67f65e5f389603b to your computer and use it in GitHub Desktop.
Save egm0121/0913b778953ee16fc67f65e5f389603b to your computer and use it in GitHub Desktop.
pipe in a new line delimitated log file serialized using flatten -> get json serialized log file (circular refs discarded)
#!/usr/bin/env node
const Flatted=function(n){"use strict";
/*! (c) 2020 Andrea Giammarchi */var t=JSON.parse,r=JSON.stringify,e=Object.keys,a=String,u="string",f={},i="object",c=function(n,t){return t},l=function(n){return n instanceof a?a(n):n},o=function(n,t){return typeof t===u?new a(t):t},s=function(n,t,r){var e=a(t.push(r)-1);return n.set(r,e),e};return n.parse=function(n,r){var u=t(n,o).map(l),s=u[0],p=r||c,v=typeof s===i&&s?function n(t,r,u,c){for(var l=[],o=e(u),s=o.length,p=0;p<s;p++){var v=o[p],y=u[v];if(y instanceof a){var g=t[y];typeof g!==i||r.has(g)?u[v]=c.call(u,v,g):(r.add(g),u[v]=f,l.push({k:v,a:[t,r,g,c]}))}else u[v]!==f&&(u[v]=c.call(u,v,y))}for(var h=l.length,d=0;d<h;d++){var w=l[d],O=w.k,S=w.a;u[O]=c.call(u,O,n.apply(null,S))}return u}(u,new Set,s,p):s;return p.call({"":v},"",v)},n.stringify=function(n,t,e){for(var a=t&&typeof t===i?function(n,r){return""===n||-1<t.indexOf(n)?r:void 0}:t||c,f=new Map,l=[],o=[],p=+s(f,l,a.call({"":n},"",n)),v=!p;p<l.length;)v=!0,o[p]=r(l[p++],y,e);return"["+o.join(",")+"]";function y(n,t){if(v)return v=!v,t;var r=a.call(this,n,t);switch(typeof r){case i:if(null===r)return r;case u:return f.get(r)||s(f,l,r)}return r}},n}({});
const { Transform } = require('stream');
const os = require('os');
const stringifyCircularSafe = (data) => {
let cache = [];
const str = JSON.stringify(data, function(key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
// preserving the pid key as an empty string will allow buyan cli to
// recognize the log entry as a valid entry if no pid is available, eg. browser env
if (typeof value === 'undefined' && key === 'pid') {
return '';
}
return value;
});
cache = null; // Enable garbage collection
return str;
}
class ByLineTransform extends Transform {
constructor(opts) {
super(opts);
this._brRe = /\r?\n/;
this._buf = null;
}
_transform(chunk, encoding, cb) {
let str;
if (Buffer.isBuffer(chunk) || encoding === 'buffer') {
str = chunk.toString('utf8');
} else {
str = chunk;
}
try {
if (this._buf !== null) {
this._buf += str;
} else {
this._buf = str;
}
const lines = this._buf.split(this._brRe);
const lastIndex = lines.length - 1;
for (let i = 0; i < lastIndex; i++) {
this.push(lines[i]);
}
const lastLine = lines[lastIndex];
if (lastLine.length) {
this._buf = lastLine;
} else {
this._buf = null;
}
cb();
} catch(err) {
console.log('eror on stream')
cb(err); // invalid data type;
}
}
_flush(callback) {
try {
if(this._buf !== null) {
this.push(this._buf);
this._buf = null;
}
} catch (err) {
callback(err);
}
}
};
return process.stdin.pipe(new ByLineTransform({
decodeStrings: false, // Accept string input rather than Buffers
}))
.pipe(new Transform({
construct(callback) {
callback();
},
transform(chunk, encoding, cb) {
const string = chunk.toString();
try {
this.push(stringifyCircularSafe(Flatted.parse(string))+os.EOL);
cb();
} catch(err) {
cb(err); // invalid data type;
}
},
flush(callback) {
}
}))
.pipe(process.stdout);
{
"name": "npx-script-template",
"version": "0.0.0",
"bin": "./deflatten.js"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment