diff --git a/VERSION.md b/VERSION.md index afa2b35..abb1658 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.8.0 \ No newline at end of file +1.9.0 \ No newline at end of file diff --git a/libs/browser-id3-writer/README.md b/libs/browser-id3-writer/README.md new file mode 100644 index 0000000..bc1017d --- /dev/null +++ b/libs/browser-id3-writer/README.md @@ -0,0 +1,306 @@ +# Browser ID3 Writer + +[![npm package][npm-badge]][npm] [![Travis][build-badge]][build] + +[build-badge]: https://img.shields.io/travis/egoroof/browser-id3-writer/master.svg?style=flat-square +[build]: https://travis-ci.org/egoroof/browser-id3-writer + +[npm-badge]: https://img.shields.io/npm/v/browser-id3-writer.svg?style=flat-square +[npm]: https://www.npmjs.org/package/browser-id3-writer + +Pure JS library for writing [ID3 (v2.3)](http://id3.org/id3v2.3.0) tag to MP3 files in browsers and Node.js. +It can't read the tag so use another lib to do it. + +**Note**: the library removes existing ID3 tag (v2.2, v2.3 and v2.4). + +Works in Node.js 4+, IE10+ and all modern browsers. + +Here is an online demonstration: [egoroof.ru/browser-id3-writer/](https://egoroof.ru/browser-id3-writer/) + +## Table of Contents + +- [Installation](#installation) +- [Usage](#usage) + - [Browser](#browser) + 1. [Get ArrayBuffer of song](#get-arraybuffer-of-song) + 2. [Add a tag](#add-a-tag) + 3. [Save file](#save-file) + 4. [Memory control](#memory-control) + - [Node.js](#nodejs) +- [Supported frames](#supported-frames) +- [APIC picture types](#apic-picture-types) + +## Installation + +Take latest version [here](https://unpkg.com/browser-id3-writer) or with npm: + +``` +npm install browser-id3-writer --save +``` + +## Usage + +### Browser + +#### Get ArrayBuffer of song + +In browsers you should first get +[ArrayBuffer](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) +of the song you would like to add ID3 tag. + +##### FileReader + +For example you can create file input and use +[FileReader](https://developer.mozilla.org/en/docs/Web/API/FileReader): + +```html + + +``` + +##### XMLHttpRequest + +To get arrayBuffer from remote server you can use +[XMLHttpRequest](https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest): + +```js +const xhr = new XMLHttpRequest(); +xhr.open('GET', urlToSongFile, true); +xhr.responseType = 'arraybuffer'; +xhr.onload = function () { + if (xhr.status === 200) { + const arrayBuffer = xhr.response; + // go next + } else { + // handle error + console.error(xhr.statusText + ' (' + xhr.status + ')'); + } +}; +xhr.onerror = function() { + // handle error + console.error('Network error'); +}; +xhr.send(); +``` + +#### Add a tag + +Create new `ID3Writer` instance with arrayBuffer of your song, set frames and add a tag: + +```js +// arrayBuffer of song or empty arrayBuffer if you just want only id3 tag without song +const writer = new ID3Writer(arrayBuffer); +writer.setFrame('TIT2', 'Home') + .setFrame('TPE1', ['Eminem', '50 Cent']) + .setFrame('TALB', 'Friday Night Lights') + .setFrame('TYER', 2004) + .setFrame('TRCK', '6/8') + .setFrame('TCON', ['Soundtrack']) + .setFrame('TBPM', 128) + .setFrame('WPAY', 'https://google.com') + .setFrame('TKEY', 'Fbm') + .setFrame('APIC', { + type: 3, + data: coverArrayBuffer, + description: 'Super picture' + }); +writer.addTag(); +``` + +#### Save file + +Now you can save it to file as you want: + +```js +const taggedSongBuffer = writer.arrayBuffer; +const blob = writer.getBlob(); +const url = writer.getURL(); +``` + +For example you can save file using [FileSaver.js](https://github.com/eligrey/FileSaver.js/): + +```js +saveAs(blob, 'song with tags.mp3'); +``` + +If you are writing chromium extension you can save file using +[Downloads API](https://developer.chrome.com/extensions/downloads): + +```js +chrome.downloads.download({ + url: url, + filename: 'song with tags.mp3' +}); +``` + +#### Memory control + +When you generate URLs via `writer.getURL()` you should know +that whole file is kept in memory until you close the page or move to another one. +So if you generate lots of URLs in a single page you should manually free memory +after you finish downloading file: + +```js +URL.revokeObjectURL(url); // if you know url or +writer.revokeURL(); // if you have access to writer +``` + +### Node.js + +Simple example with blocking IO: + +```js +const ID3Writer = require('browser-id3-writer'); +const fs = require('fs'); + +const songBuffer = fs.readFileSync('path_to_song.mp3'); +const coverBuffer = fs.readFileSync('path_to_cover.jpg'); + +const writer = new ID3Writer(songBuffer); +writer.setFrame('TIT2', 'Home') + .setFrame('TPE1', ['Eminem', '50 Cent']) + .setFrame('TALB', 'Friday Night Lights') + .setFrame('TYER', 2004) + .setFrame('APIC', { + type: 3, + data: coverBuffer, + description: 'Super picture' + }); +writer.addTag(); + +const taggedSongBuffer = Buffer.from(writer.arrayBuffer); +fs.writeFileSync('song_with_tags.mp3', taggedSongBuffer); +``` + +You can also create only ID3 tag without song and use it as you want: + +```js +const writer = new ID3Writer(Buffer.alloc(0)); +writer.padding = 0; // default 4096 +writer.setFrame('TIT2', 'Home'); +writer.addTag(); +const id3Buffer = Buffer.from(writer.arrayBuffer); +``` + +## Supported frames + +Have not found needed frame? Open a new issue and we'll discuss it. + +**array of strings:** + +- TPE1 (song artists) +- TCOM (song composers) +- TCON (song genres) + +**string** + +- TIT2 (song title) +- TALB (album title) +- TPE2 (album artist) +- TPE3 (conductor/performer refinement) +- TPE4 (interpreted, remixed, or otherwise modified by) +- TRCK (song number in album): '5' or '5/10' +- TPOS (album disc number): '1' or '1/3' +- TPUB (label name) +- TKEY (initial key) +- TMED (media type) +- WCOM (commercial information) +- WCOP (copyright/Legal information) +- WOAF (official audio file webpage) +- WOAR (official artist/performer webpage) +- WOAS (official audio source webpage) +- WORS (official internet radio station homepage) +- WPAY (payment) +- WPUB (publishers official webpage) + +**integer** + +- TLEN (song duration in milliseconds) +- TYER (album release year) +- TBPM (beats per minute) + +**object** + +- COMM (comments): + +```js +writer.setFrame('COMM', { + description: 'description here', + text: 'text here' +}); +``` + +- USLT (unsychronised lyrics): + +```js +writer.setFrame('USLT', { + description: 'description here', + lyrics: 'lyrics here' +}); +``` + +- TXXX (user defined text): + +```js +writer.setFrame('TXXX', { + description: 'description here', + value: 'value here' +}); +``` + +- APIC (attached picture): + +```js +writer.setFrame('APIC', { + type: 3, + data: coverArrayBuffer, + description: 'description here', + useUnicodeEncoding: false +}); +``` + +`useUnicodeEncoding` should only be `true` when description contains non-Western characters. +When it's set to `true` some program might not be able to read the picture correctly. +See [#42](https://github.com/egoroof/browser-id3-writer/issues/42). + +## APIC picture types + +| Type | Name | +|------|-------------------------------------| +| 0 | Other | +| 1 | 32x32 pixels 'file icon' (PNG only) | +| 2 | Other file icon | +| 3 | Cover (front) | +| 4 | Cover (back) | +| 5 | Leaflet page | +| 6 | Media (e.g. lable side of CD) | +| 7 | Lead artist/lead performer/soloist | +| 8 | Artist/performer | +| 9 | Conductor | +| 10 | Band/Orchestra | +| 11 | Composer | +| 12 | Lyricist/text writer | +| 13 | Recording Location | +| 14 | During recording | +| 15 | During performance | +| 16 | Movie/video screen capture | +| 17 | A bright coloured fish | +| 18 | Illustration | +| 19 | Band/artist logotype | +| 20 | Publisher/Studio logotype | diff --git a/libs/browser-id3-writer/index.js b/libs/browser-id3-writer/index.js new file mode 100644 index 0000000..7e11a5e --- /dev/null +++ b/libs/browser-id3-writer/index.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.ID3Writer=t()}(this,function(){"use strict";function r(e){return String(e).split("").map(function(e){return e.charCodeAt(0)})}function u(e){return new Uint8Array(r(e))}function h(e){var t=new Uint8Array(2*e.length);return new Uint16Array(t.buffer).set(r(e)),t}return function(){var e=t.prototype;function t(e){if(!(e&&"object"==typeof e&&"byteLength"in e))throw new Error("First argument should be an instance of ArrayBuffer or Buffer");this.arrayBuffer=e,this.padding=4096,this.frames=[],this.url=""}return e._setIntegerFrame=function(e,t){var r,n=parseInt(t,10);this.frames.push({name:e,value:n,size:(r=n.toString().length,11+r)})},e._setStringFrame=function(e,t){var r,n=t.toString();this.frames.push({name:e,value:n,size:(r=n.length,13+2*r)})},e._setPictureFrame=function(e,t,r,n){var a,s,i,c,o=function(e){if(!e||!e.length)return null;if(255===e[0]&&216===e[1]&&255===e[2])return"image/jpeg";if(137===e[0]&&80===e[1]&&78===e[2]&&71===e[3])return"image/png";if(71===e[0]&&73===e[1]&&70===e[2])return"image/gif";if(87===e[8]&&69===e[9]&&66===e[10]&&80===e[11])return"image/webp";var t=73===e[0]&&73===e[1]&&42===e[2]&&0===e[3],r=77===e[0]&&77===e[1]&&0===e[2]&&42===e[3];return t||r?"image/tiff":66===e[0]&&77===e[1]?"image/bmp":0===e[0]&&0===e[1]&&1===e[2]&&0===e[3]?"image/x-icon":null}(new Uint8Array(t)),u=r.toString();if(!o)throw new Error("Unknown picture MIME type");r||(n=!1),this.frames.push({name:"APIC",value:t,pictureType:e,mimeType:o,useUnicodeEncoding:n,description:u,size:(a=t.byteLength,s=o.length,i=u.length,c=n,11+s+1+1+(c?2+2*(i+1):i+1)+a)})},e._setLyricsFrame=function(e,t){var r,n,a=e.toString(),s=t.toString();this.frames.push({name:"USLT",value:s,description:a,size:(r=a.length,n=s.length,16+2*r+2+2+2*n)})},e._setCommentFrame=function(e,t){var r,n,a=e.toString(),s=t.toString();this.frames.push({name:"COMM",value:s,description:a,size:(r=a.length,n=s.length,16+2*r+2+2+2*n)})},e._setUserStringFrame=function(e,t){var r,n,a=e.toString(),s=t.toString();this.frames.push({name:"TXXX",description:a,value:s,size:(r=a.length,n=s.length,13+2*r+2+2+2*n)})},e._setUrlLinkFrame=function(e,t){var r,n=t.toString();this.frames.push({name:e,value:n,size:(r=n.length,10+r)})},e.setFrame=function(e,t){switch(e){case"TPE1":case"TCOM":case"TCON":if(!Array.isArray(t))throw new Error(e+" frame value should be an array of strings");var r="TCON"===e?";":"/",n=t.join(r);this._setStringFrame(e,n);break;case"TIT2":case"TALB":case"TPE2":case"TPE3":case"TPE4":case"TRCK":case"TPOS":case"TMED":case"TSRC":case"TDAT":case"TCOP":case"TPUB":this._setStringFrame(e,t);break;case"TBPM":case"TLEN":case"TYER":this._setIntegerFrame(e,t);break;case"USLT":if(!("object"==typeof t&&"description"in t&&"lyrics"in t))throw new Error("USLT frame value should be an object with keys description and lyrics");this._setLyricsFrame(t.description,t.lyrics);break;case"APIC":if(!("object"==typeof t&&"type"in t&&"data"in t&&"description"in t))throw new Error("APIC frame value should be an object with keys type, data and description");if(t.type<0||20>>21&(t=127),e>>>14&t,e>>>7&t,e&t],i.set(o,c),c+=o.length,this.frames.forEach(function(e){var t,r;switch(o=u(e.name),i.set(o,c),c+=o.length,t=e.size-10,o=[t>>>24&(r=255),t>>>16&r,t>>>8&r,t&r],i.set(o,c),c+=o.length,c+=2,e.name){case"WCOM":case"WCOP":case"WOAF":case"WOAR":case"WOAS":case"WORS":case"WPAY":case"WPUB":o=u(e.value),i.set(o,c),c+=o.length;break;case"TPE1":case"TCOM":case"TCOP":case"TCON":case"TIT2":case"TALB":case"TPE2":case"TPE3":case"TPE4":case"TRCK":case"TPOS":case"TKEY":case"TMED":case"TSRC":case"TDAT":case"TPUB":o=[1].concat(n),i.set(o,c),c+=o.length,o=h(e.value),i.set(o,c),c+=o.length;break;case"TXXX":case"USLT":case"COMM":o=[1],"USLT"!==e.name&&"COMM"!==e.name||(o=o.concat(a)),o=o.concat(n),i.set(o,c),c+=o.length,o=h(e.description),i.set(o,c),c+=o.length,o=[0,0].concat(n),i.set(o,c),c+=o.length,o=h(e.value),i.set(o,c),c+=o.length;break;case"TBPM":case"TLEN":case"TYER":c++,o=u(e.value),i.set(o,c),c+=o.length;break;case"APIC":o=[e.useUnicodeEncoding?1:0],i.set(o,c),c+=o.length,o=u(e.mimeType),i.set(o,c),c+=o.length,o=[0,e.pictureType],i.set(o,c),c+=o.length,e.useUnicodeEncoding?(o=[].concat(n),i.set(o,c),c+=o.length,o=h(e.description),i.set(o,c),c+=o.length,c+=2):(o=u(e.description),i.set(o,c),c+=o.length,c++),i.set(new Uint8Array(e.value),c),c+=e.value.byteLength}}),c+=this.padding,i.set(new Uint8Array(this.arrayBuffer),c),this.arrayBuffer=s},e.getBlob=function(){return new Blob([this.arrayBuffer],{type:"audio/mpeg"})},e.getURL=function(){return this.url||(this.url=URL.createObjectURL(this.getBlob())),this.url},e.revokeURL=function(){URL.revokeObjectURL(this.url)},t}()}); \ No newline at end of file diff --git a/libs/flac-metadata/.gitignore b/libs/flac-metadata/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/libs/flac-metadata/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/libs/flac-metadata/README.md b/libs/flac-metadata/README.md new file mode 100644 index 0000000..dc27500 --- /dev/null +++ b/libs/flac-metadata/README.md @@ -0,0 +1,143 @@ +# flac-metadata + +A FLAC metadata processor for Node.js, implemented as Transform stream. + +## Installation + +```npm install flac-metadata``` + +## Usage Examples + +Some simple examples to get you started: + +#### Noop + +Does nothing, just pipes a source FLAC through the Processor into a target FLAC. + +```js +var fs = require("fs"); +var flac = require("flac-metadata"); + +var reader = fs.createReadStream("source.flac"); +var writer = fs.createWriteStream("target.flac"); +var processor = new flac.Processor(); + +reader.pipe(processor).pipe(writer); +``` + +#### Trace Metadata + +Traces out the metadata from a FLAC file. + +```js +var fs = require("fs"); +var flac = require("flac-metadata"); + +var reader = fs.createReadStream("source.flac"); +var processor = new flac.Processor({ parseMetaDataBlocks: true }); +processor.on("postprocess", function(mdb) { + console.log(mdb.toString()); +}); + +reader.pipe(processor); +``` + +The output should be something like this: + +``` +[MetaDataBlockStreamInfo] type: 0, isLast: false + minBlockSize: 4096 + maxBlockSize: 4096 + minFrameSize: 14 + maxFrameSize: 12389 + samples: 9750804 + sampleRate: 44100 + channels: 2 + bitsPerSample: 16 + duration: 3:41.107 + checksum: 1746dff27beb6d1875a88cfeed8a576b + +[MetaDataBlockVorbisComment] type: 4, isLast: false + vendor: reference libFLAC 1.2.1 20070917 + comments: + ALBUM: Close to the Glass + ARTIST: The Notwist + GENRE: Rock + DATE: 2014 + TITLE: Signals + +[MetaDataBlockPicture] type: 6, isLast: true + pictureType: 3 + mimeType: image/png + description: + width: 120 + height: 120 + bitsPerPixel: 32 + colors: 0 + pictureData: 391383 +``` + +#### Strip All Metadata + +Pipes a source FLAC through the Processor into a target FLAC, removing all metadata. + +```js +var fs = require("fs"); +var flac = require("flac-metadata"); + +var reader = fs.createReadStream("source.flac"); +var writer = fs.createWriteStream("target.flac"); +var processor = new flac.Processor(); + +processor.on("preprocess", function(mdb) { + // STREAMINFO is always the first (and only mandatory) metadata block. + if (mdb.type === flac.Processor.MDB_TYPE_STREAMINFO) { + // When a metadata block's isLast flag is set to true in preprocess, + // subsequent blocks are automatically discarded. + mdb.isLast = true; + } +}); + +reader.pipe(processor).pipe(writer); +``` + +#### Inject Metadata + +Injects a VORBIS_COMMENT block (and removes the existing one, if any). + +```js +var fs = require("fs"); +var flac = require("flac-metadata"); + +var reader = fs.createReadStream("source.flac"); +var writer = fs.createWriteStream("target.flac"); +var processor = new flac.Processor(); + +var vendor = "reference libFLAC 1.2.1 20070917"; +var comments = [ + "ARTIST=Boyracer", + "TITLE=I've Got It And It's Not Worth Having", + "ALBUM=B Is For Boyracer", + "TRACKNUMBER=A1", + "DATE=1993", + "DISCOGS=22379" +]; + +processor.on("preprocess", function(mdb) { + // Remove existing VORBIS_COMMENT block, if any. + if (mdb.type === flac.Processor.MDB_TYPE_VORBIS_COMMENT) { + mdb.remove(); + } + // Inject new VORBIS_COMMENT block. + if (mdb.removed || mdb.isLast) { + var mdbVorbis = flac.data.MetaDataBlockVorbisComment.create(mdb.isLast, vendor, comments); + this.push(mdbVorbis.publish()); + } +}); + +reader.pipe(processor).pipe(writer); +``` + +## License + +MIT diff --git a/libs/flac-metadata/index.js b/libs/flac-metadata/index.js new file mode 100644 index 0000000..9d72b14 --- /dev/null +++ b/libs/flac-metadata/index.js @@ -0,0 +1,8 @@ +module.exports.Processor = require("./lib/Processor"); + +module.exports.data = { + MetaDataBlock: require("./lib/data/MetaDataBlock"), + MetaDataBlockStreamInfo: require("./lib/data/MetaDataBlockStreamInfo"), + MetaDataBlockVorbisComment: require("./lib/data/MetaDataBlockVorbisComment"), + MetaDataBlockPicture: require("./lib/data/MetaDataBlockPicture") +}; diff --git a/libs/flac-metadata/lib/Processor.js b/libs/flac-metadata/lib/Processor.js new file mode 100644 index 0000000..f0a54c2 --- /dev/null +++ b/libs/flac-metadata/lib/Processor.js @@ -0,0 +1,218 @@ +var util = require("util"); +var stream = require('stream'); +var Transform = stream.Transform || require('readable-stream').Transform; + +var MetaDataBlock = require("./data/MetaDataBlock"); +var MetaDataBlockStreamInfo = require("./data/MetaDataBlockStreamInfo"); +var MetaDataBlockVorbisComment = require("./data/MetaDataBlockVorbisComment"); +var MetaDataBlockPicture = require("./data/MetaDataBlockPicture"); + +const STATE_IDLE = 0; +const STATE_MARKER = 1; +const STATE_MDB_HEADER = 2; +const STATE_MDB = 3; +const STATE_PASS_THROUGH = 4; + + +var Processor = function (options) { + + this.state = STATE_IDLE; + + this.isFlac = false; + + this.buf; + this.bufPos = 0; + + this.mdb; + this.mdbLen = 0; + this.mdbLast = false; + this.mdbPush = false; + this.mdbLastWritten = false; + + this.parseMetaDataBlocks = false; + + if (!(this instanceof Processor)) return new Processor(options); + if (options && !!options.parseMetaDataBlocks) { this.parseMetaDataBlocks = true; } + Transform.call(this, options); +} + +util.inherits(Processor, Transform); + +// MDB types +Processor.MDB_TYPE_STREAMINFO = 0; +Processor.MDB_TYPE_PADDING = 1; +Processor.MDB_TYPE_APPLICATION = 2; +Processor.MDB_TYPE_SEEKTABLE = 3; +Processor.MDB_TYPE_VORBIS_COMMENT = 4; +Processor.MDB_TYPE_CUESHEET = 5; +Processor.MDB_TYPE_PICTURE = 6; +Processor.MDB_TYPE_INVALID = 127; + +Processor.prototype._transform = function (chunk, enc, done) { + var chunkPos = 0; + var chunkLen = chunk.length; + var isChunkProcessed = false; + var _this = this; + + function _safePush (minCapacity, persist, validate) { + var slice; + var chunkAvailable = chunkLen - chunkPos; + var isDone = (chunkAvailable + this.bufPos >= minCapacity); + validate = (typeof validate === "function") ? validate : function() { return true; }; + if (isDone) { + // Enough data available + if (persist) { + // Persist the entire block so it can be parsed + if (this.bufPos > 0) { + // Part of this block's data is in backup buffer, copy rest over + chunk.copy(this.buf, this.bufPos, chunkPos, chunkPos + minCapacity - this.bufPos); + slice = this.buf.slice(0, minCapacity); + } else { + // Entire block fits in current chunk + slice = chunk.slice(chunkPos, chunkPos + minCapacity); + } + } else { + slice = chunk.slice(chunkPos, chunkPos + minCapacity - this.bufPos); + } + // Push block after validation + validate(slice, isDone) && _this.push(slice); + chunkPos += minCapacity - this.bufPos; + this.bufPos = 0; + this.buf = null; + } else { + // Not enough data available + if (persist) { + // Copy/append incomplete block to backup buffer + this.buf = this.buf || new Buffer(minCapacity); + chunk.copy(this.buf, this.bufPos, chunkPos, chunkLen); + } else { + // Push incomplete block after validation + slice = chunk.slice(chunkPos, chunkLen); + validate(slice, isDone) && _this.push(slice); + } + this.bufPos += chunkLen - chunkPos; + } + return isDone; + }; + var safePush = _safePush.bind(this); + + while (!isChunkProcessed) { + switch (this.state) { + case STATE_IDLE: + this.state = STATE_MARKER; + break; + case STATE_MARKER: + if (safePush(4, true, this._validateMarker.bind(this))) { + this.state = this.isFlac ? STATE_MDB_HEADER : STATE_PASS_THROUGH; + } else { + isChunkProcessed = true; + } + break; + case STATE_MDB_HEADER: + if (safePush(4, true, this._validateMDBHeader.bind(this))) { + this.state = STATE_MDB; + } else { + isChunkProcessed = true; + } + break; + case STATE_MDB: + if (safePush(this.mdbLen, this.parseMetaDataBlocks, this._validateMDB.bind(this))) { + if (this.mdb.isLast) { + // This MDB has the isLast flag set to true. + // Ignore all following MDBs. + this.mdbLastWritten = true; + } + this.emit("postprocess", this.mdb); + this.state = this.mdbLast ? STATE_PASS_THROUGH : STATE_MDB_HEADER; + } else { + isChunkProcessed = true; + } + break; + case STATE_PASS_THROUGH: + safePush(chunkLen - chunkPos, false); + isChunkProcessed = true; + break; + } + } + + done(); +} + +Processor.prototype._validateMarker = function(slice, isDone) { + this.isFlac = (slice.toString("utf8", 0) === "fLaC"); + // TODO: completely bail out if file is not a FLAC? + return true; +} + +Processor.prototype._validateMDBHeader = function(slice, isDone) { + // Parse MDB header + var header = slice.readUInt32BE(0); + var type = (header >>> 24) & 0x7f; + this.mdbLast = (((header >>> 24) & 0x80) !== 0); + this.mdbLen = header & 0xffffff; + + // Create appropriate MDB object + // (data is injected later in _validateMDB, if parseMetaDataBlocks option is set to true) + switch (type) { + case Processor.MDB_TYPE_STREAMINFO: + this.mdb = new MetaDataBlockStreamInfo(this.mdbLast); + break; + case Processor.MDB_TYPE_VORBIS_COMMENT: + this.mdb = new MetaDataBlockVorbisComment(this.mdbLast); + break; + case Processor.MDB_TYPE_PICTURE: + this.mdb = new MetaDataBlockPicture(this.mdbLast); + break; + case Processor.MDB_TYPE_PADDING: + case Processor.MDB_TYPE_APPLICATION: + case Processor.MDB_TYPE_SEEKTABLE: + case Processor.MDB_TYPE_CUESHEET: + case Processor.MDB_TYPE_INVALID: + default: + this.mdb = new MetaDataBlock(this.mdbLast, type); + break + } + + this.emit("preprocess", this.mdb); + + if (this.mdbLastWritten) { + // A previous MDB had the isLast flag set to true. + // Ignore all following MDBs. + this.mdb.remove(); + } else { + // The consumer may change the MDB's isLast flag in the preprocess handler. + // Here that flag is updated in the MDB header. + if (this.mdbLast !== this.mdb.isLast) { + if (this.mdb.isLast) { + header |= 0x80000000; + } else { + header &= 0x7fffffff; + } + slice.writeUInt32BE(header >>> 0, 0); + } + } + this.mdbPush = !this.mdb.removed; + return this.mdbPush; +} + +Processor.prototype._validateMDB = function(slice, isDone) { + // Parse the MDB if parseMetaDataBlocks option is set to true + if (this.parseMetaDataBlocks && isDone) { + this.mdb.parse(slice); + } + return this.mdbPush; +} + +Processor.prototype._flush = function(done) { + // All chunks have been processed + // Clean up + this.state = STATE_IDLE; + this.mdbLastWritten = false; + this.isFlac = false; + this.bufPos = 0; + this.buf = null; + this.mdb = null; + done(); +} + +module.exports = Processor; diff --git a/libs/flac-metadata/lib/data/MetaDataBlock.js b/libs/flac-metadata/lib/data/MetaDataBlock.js new file mode 100644 index 0000000..cc1421d --- /dev/null +++ b/libs/flac-metadata/lib/data/MetaDataBlock.js @@ -0,0 +1,21 @@ +var MetaDataBlock = module.exports = function(isLast, type) { + this.isLast = isLast; + this.type = type; + this.error = null; + this.hasData = false; + this.removed = false; +} + +MetaDataBlock.prototype.remove = function() { + this.removed = true; +} + +MetaDataBlock.prototype.parse = function(buffer) { +} + +MetaDataBlock.prototype.toString = function() { + var str = "[MetaDataBlock]"; + str += " type: " + this.type; + str += ", isLast: " + this.isLast; + return str; +} diff --git a/libs/flac-metadata/lib/data/MetaDataBlockPicture.js b/libs/flac-metadata/lib/data/MetaDataBlockPicture.js new file mode 100644 index 0000000..5694664 --- /dev/null +++ b/libs/flac-metadata/lib/data/MetaDataBlockPicture.js @@ -0,0 +1,131 @@ +var util = require("util"); +var MetaDataBlock = require("./MetaDataBlock"); + +var MetaDataBlockPicture = module.exports = function(isLast) { + MetaDataBlock.call(this, isLast, 6); + + this.pictureType = 0; + this.mimeType = ""; + this.description = ""; + this.width = 0; + this.height = 0; + this.bitsPerPixel = 0; + this.colors = 0; + this.pictureData = null; +} + +util.inherits(MetaDataBlockPicture, MetaDataBlock); + +MetaDataBlockPicture.create = function(isLast, pictureType, mimeType, description, width, height, bitsPerPixel, colors, pictureData) { + var mdb = new MetaDataBlockPicture(isLast); + mdb.pictureType = pictureType; + mdb.mimeType = mimeType; + mdb.description = description; + mdb.width = width; + mdb.height = height; + mdb.bitsPerPixel = bitsPerPixel; + mdb.colors = colors; + mdb.pictureData = pictureData; + mdb.hasData = true; + return mdb; +} + +MetaDataBlockPicture.prototype.parse = function(buffer) { + try { + + var pos = 0; + + this.pictureType = buffer.readUInt32BE(pos); + pos += 4; + + var mimeTypeLength = buffer.readUInt32BE(pos); + this.mimeType = buffer.toString("utf8", pos + 4, pos + 4 + mimeTypeLength); + pos += 4 + mimeTypeLength; + + var descriptionLength = buffer.readUInt32BE(pos); + this.description = buffer.toString("utf8", pos + 4, pos + 4 + descriptionLength); + pos += 4 + descriptionLength; + + this.width = buffer.readUInt32BE(pos); + this.height = buffer.readUInt32BE(pos + 4); + this.bitsPerPixel = buffer.readUInt32BE(pos + 8); + this.colors = buffer.readUInt32BE(pos + 12); + pos += 16; + + var pictureDataLength = buffer.readUInt32BE(pos); + this.pictureData = new Buffer(pictureDataLength); + buffer.copy(this.pictureData, 0, pos + 4, pictureDataLength); + + this.hasData = true; + + } + catch (e) { + this.error = e; + this.hasData = false; + } +} + +MetaDataBlockPicture.prototype.publish = function() { + var pos = 0; + var size = this.getSize(); + var buffer = new Buffer(4 + size); + + var header = size; + header |= (this.type << 24); + header |= (this.isLast ? 0x80000000 : 0); + buffer.writeUInt32BE(header >>> 0, pos); + pos += 4; + + buffer.writeUInt32BE(this.pictureType, pos); + pos += 4; + + var mimeTypeLen = Buffer.byteLength(this.mimeType); + buffer.writeUInt32BE(mimeTypeLen, pos); + buffer.write(this.mimeType, pos + 4); + pos += 4 + mimeTypeLen; + + var descriptionLen = Buffer.byteLength(this.description); + buffer.writeUInt32BE(descriptionLen, pos); + buffer.write(this.description, pos + 4); + pos += 4 + descriptionLen; + + buffer.writeUInt32BE(this.width, pos); + buffer.writeUInt32BE(this.height, pos + 4); + buffer.writeUInt32BE(this.bitsPerPixel, pos + 8); + buffer.writeUInt32BE(this.colors, pos + 12); + pos += 16; + + buffer.writeUInt32BE(this.pictureData.length, pos); + this.pictureData.copy(buffer, pos + 4); + + return buffer; +} + +MetaDataBlockPicture.prototype.getSize = function() { + var size = 4; + size += 4 + Buffer.byteLength(this.mimeType); + size += 4 + Buffer.byteLength(this.description); + size += 16; + size += 4 + this.pictureData.length; + return size; +} + +MetaDataBlockPicture.prototype.toString = function() { + var str = "[MetaDataBlockPicture]"; + str += " type: " + this.type; + str += ", isLast: " + this.isLast; + if (this.error) { + str += "\n ERROR: " + this.error; + } + if (this.hasData) { + str += "\n pictureType: " + this.pictureType; + str += "\n mimeType: " + this.mimeType; + str += "\n description: " + this.description; + str += "\n width: " + this.width; + str += "\n height: " + this.height; + str += "\n bitsPerPixel: " + this.bitsPerPixel; + str += "\n colors: " + this.colors; + str += "\n pictureData: " + (this.pictureData ? this.pictureData.length : ""); + } + return str; +} diff --git a/libs/flac-metadata/lib/data/MetaDataBlockStreamInfo.js b/libs/flac-metadata/lib/data/MetaDataBlockStreamInfo.js new file mode 100644 index 0000000..c178a06 --- /dev/null +++ b/libs/flac-metadata/lib/data/MetaDataBlockStreamInfo.js @@ -0,0 +1,86 @@ +var util = require("util"); +var MetaDataBlock = require("./MetaDataBlock"); + +var MetaDataBlockStreamInfo = module.exports = function(isLast) { + MetaDataBlock.call(this, isLast, 0); + + this.minBlockSize = 0; + this.maxBlockSize = 0; + this.minFrameSize = 0; + this.maxFrameSize = 0; + this.sampleRate = 0; + this.channels = 0; + this.bitsPerSample = 0; + this.samples = 0; + this.checksum = null; + this.duration = 0; + this.durationStr = "0:00.000"; +} + +util.inherits(MetaDataBlockStreamInfo, MetaDataBlock); + +MetaDataBlockStreamInfo.prototype.remove = function() { + console.error("WARNING: Can't remove StreamInfo block!"); +} + +MetaDataBlockStreamInfo.prototype.parse = function(buffer) { + try { + + var pos = 0; + + this.minBlockSize = buffer.readUInt16BE(pos); + this.maxBlockSize = buffer.readUInt16BE(pos + 2); + this.minFrameSize = (buffer.readUInt8(pos + 4) << 16) | buffer.readUInt16BE(pos + 5); + this.maxFrameSize = (buffer.readUInt8(pos + 7) << 16) | buffer.readUInt16BE(pos + 8); + + var tmp = buffer.readUInt32BE(pos + 10); + this.sampleRate = tmp >>> 12; + this.channels = (tmp >>> 9) & 0x07; + this.bitsPerSample = (tmp >>> 4) & 0x1f; + this.samples = +((tmp & 0x0f) << 4) + buffer.readUInt32BE(pos + 14); + + this.checksum = new Buffer(16); + buffer.copy(this.checksum, 0, 18, 34); + + this.duration = this.samples / this.sampleRate; + + var minutes = "" + Math.floor(this.duration / 60); + var seconds = pad(Math.floor(this.duration % 60), 2); + var milliseconds = pad(Math.round(((this.duration % 60) - Math.floor(this.duration % 60)) * 1000), 3); + this.durationStr = minutes + ":" + seconds + "." + milliseconds; + + this.hasData = true; + + } + catch (e) { + this.error = e; + this.hasData = false; + } +} + +MetaDataBlockStreamInfo.prototype.toString = function() { + var str = "[MetaDataBlockStreamInfo]"; + str += " type: " + this.type; + str += ", isLast: " + this.isLast; + if (this.error) { + str += "\n ERROR: " + this.error; + } + if (this.hasData) { + str += "\n minBlockSize: " + this.minBlockSize; + str += "\n maxBlockSize: " + this.maxBlockSize; + str += "\n minFrameSize: " + this.minFrameSize; + str += "\n maxFrameSize: " + this.maxFrameSize; + str += "\n samples: " + this.samples; + str += "\n sampleRate: " + this.sampleRate; + str += "\n channels: " + (this.channels + 1); + str += "\n bitsPerSample: " + (this.bitsPerSample + 1); + str += "\n duration: " + this.durationStr; + str += "\n checksum: " + (this.checksum ? this.checksum.toString("hex") : ""); + } + return str; +} + +function pad(n, width) { + n = "" + n; + return (n.length >= width) ? n : new Array(width - n.length + 1).join("0") + n; +} diff --git a/libs/flac-metadata/lib/data/MetaDataBlockVorbisComment.js b/libs/flac-metadata/lib/data/MetaDataBlockVorbisComment.js new file mode 100644 index 0000000..bd82f8a --- /dev/null +++ b/libs/flac-metadata/lib/data/MetaDataBlockVorbisComment.js @@ -0,0 +1,108 @@ +var util = require("util"); +var MetaDataBlock = require("./MetaDataBlock"); + +var MetaDataBlockVorbisComment = module.exports = function(isLast) { + MetaDataBlock.call(this, isLast, 4); + + this.vendor = ""; + this.comments = []; +} + +util.inherits(MetaDataBlockVorbisComment, MetaDataBlock); + +MetaDataBlockVorbisComment.create = function(isLast, vendor, comments) { + var mdb = new MetaDataBlockVorbisComment(isLast); + mdb.vendor = vendor; + mdb.comments = comments; + mdb.hasData = true; + return mdb; +} + +MetaDataBlockVorbisComment.prototype.parse = function(buffer) { + try { + + var pos = 0; + + var vendorLen = buffer.readUInt32LE(pos); + var vendor = buffer.toString("utf8", pos + 4, pos + 4 + vendorLen); + this.vendor = vendor; + pos += 4 + vendorLen; + + var commentCount = buffer.readUInt32LE(pos); + pos += 4; + + while (commentCount-- > 0) { + var commentLen = buffer.readUInt32LE(pos); + var comment = buffer.toString("utf8", pos + 4, pos + 4 + commentLen); + this.comments.push(comment); + pos += 4 + commentLen; + } + + this.hasData = true; + + } + catch (e) { + this.error = e; + this.hasData = false; + } +} + +MetaDataBlockVorbisComment.prototype.publish = function() { + var pos = 0; + var size = this.getSize(); + var buffer = new Buffer(4 + size); + + var header = size; + header |= (this.type << 24); + header |= (this.isLast ? 0x80000000 : 0); + buffer.writeUInt32BE(header >>> 0, pos); + pos += 4; + + var vendorLen = Buffer.byteLength(this.vendor); + buffer.writeUInt32LE(vendorLen, pos); + buffer.write(this.vendor, pos + 4); + pos += 4 + vendorLen; + + var commentCount = this.comments.length; + buffer.writeUInt32LE(commentCount, pos); + pos += 4; + + for (var i = 0; i < commentCount; i++) { + var comment = this.comments[i]; + var commentLen = Buffer.byteLength(comment); + buffer.writeUInt32LE(commentLen, pos); + buffer.write(comment, pos + 4); + pos += 4 + commentLen; + } + + return buffer; +} + +MetaDataBlockVorbisComment.prototype.getSize = function() { + var size = 8 + Buffer.byteLength(this.vendor); + for (var i = 0; i < this.comments.length; i++) { + size += 4 + Buffer.byteLength(this.comments[i]); + } + return size; +} + +MetaDataBlockVorbisComment.prototype.toString = function() { + var str = "[MetaDataBlockVorbisComment]"; + str += " type: " + this.type; + str += ", isLast: " + this.isLast; + if (this.error) { + str += "\n ERROR: " + this.error; + } + if (this.hasData) { + str += "\n vendor: " + this.vendor; + if (this.comments.length) { + str += "\n comments:"; + for (var i = 0; i < this.comments.length; i++) { + str += "\n " + this.comments[i].split("=").join(": "); + } + } else { + str += "\n comments: none"; + } + } + return str; +} diff --git a/libs/flac-metadata/package.json b/libs/flac-metadata/package.json new file mode 100644 index 0000000..e45c0cc --- /dev/null +++ b/libs/flac-metadata/package.json @@ -0,0 +1,24 @@ +{ + "name": "flac-metadata", + "description": "FLAC metadata processor implemented as Transform stream", + "keywords": ["flac", "metadata", "audio"], + "author": "Claus Wahlers (http://wahlers.com.br/claus/)", + "homepage": "https://github.com/claus/flac-metadata", + "version": "0.1.1", + "license": "MIT", + "main": "index.js", + "directories": { + "lib": "./lib" + }, + "repository": { + "type": "git", + "url": "https://github.com/claus/flac-metadata.git" + }, + "bugs": { + "url": "https://github.com/claus/flac-metadata/issues", + "email": "claus@codeazur.com.br" + }, + "engines": { + "node": ">=0.8" + } +} diff --git a/libs/node-memory-stats/index.js b/libs/node-memory-stats/index.js new file mode 100644 index 0000000..7dec6c0 --- /dev/null +++ b/libs/node-memory-stats/index.js @@ -0,0 +1,31 @@ +const WindowsPlatform = require('./platforms/windows'); +const LinuxPlatform = require('./platforms/linux'); +const DarwinPlatform = require('./platforms/darwin'); + + +function getMethods() { + const classes = { + 'win32': WindowsPlatform, + 'linux': LinuxPlatform, + 'darwin': DarwinPlatform + }; + + return classes[process.platform]; +} + +const methods = getMethods(); + +function total() { + return methods.getTotalMemory(); +} + +function used() { + return methods.getUsedMemory(); +} + +function free() { + return methods.getFreeMemory(); +} + + +module.exports = {total, used, free}; diff --git a/libs/node-memory-stats/platforms/darwin.js b/libs/node-memory-stats/platforms/darwin.js new file mode 100644 index 0000000..0e65d8d --- /dev/null +++ b/libs/node-memory-stats/platforms/darwin.js @@ -0,0 +1,37 @@ +const exec = require('child_process').execSync; + +module.exports = class Darwin { + static getTotalMemory() { + return parseInt(exec('sysctl -n hw.memsize', {'encoding': 'utf8'}), 10); + } + + static getUsedMemory() { + const memoryTypes = ['active', 'wired down', 'inactive']; + const pageSize = this.getPageSize(); + let totalMemoryUsed = 0; + + memoryTypes.forEach((memoryType) => { + totalMemoryUsed += this.getMemoryTypeUsage(memoryType); + }); + + return (totalMemoryUsed * pageSize); + } + + static getFreeMemory() { + return this.getTotalMemory() - this.getUsedMemory(); + } + + static getPageSize() { + return parseInt(exec('sysctl -n hw.pagesize', {'encoding': 'utf8'}), 10); + } + + static getMemoryTypeUsage(memoryType) { + let position = 3; + + if (1 < memoryType.split(' ').length) { + position = 4; + } + + return parseInt(exec(`vm_stat | grep 'Pages ${memoryType}:' | awk '{print $${position}}'`, {'encoding': 'utf8'}), 10); + } +}; diff --git a/libs/node-memory-stats/platforms/linux.js b/libs/node-memory-stats/platforms/linux.js new file mode 100644 index 0000000..fae64fa --- /dev/null +++ b/libs/node-memory-stats/platforms/linux.js @@ -0,0 +1,15 @@ +const exec = require('child_process').execSync; + +module.exports = class Linux { + static getTotalMemory() { + return parseInt(exec('free -b | grep "Mem:" | awk \'{print $2}\'', {'encoding': 'utf8'}), 10); + } + + static getUsedMemory() { + return parseInt(exec('free -b | grep "Mem:" | awk \'{print $7}\'', {'encoding': 'utf8'}), 10); + } + + static getFreeMemory() { + return this.getTotalMemory() - this.getUsedMemory(); + } +}; diff --git a/libs/node-memory-stats/platforms/windows.js b/libs/node-memory-stats/platforms/windows.js new file mode 100644 index 0000000..d8c255f --- /dev/null +++ b/libs/node-memory-stats/platforms/windows.js @@ -0,0 +1,15 @@ +const exec = require('child_process').execSync; + +module.exports = class Windows { + static getTotalMemory() { + return parseInt(exec('wmic OS get TotalVisibleMemorySize /value', {'encoding': 'utf8'}).trim().split('=')[1], 10) * 1024; + } + + static getUsedMemory() { + return this.getTotalMemory() - this.getFreeMemory(); + } + + static getFreeMemory() { + return parseInt(exec('wmic OS get FreePhysicalMemory /value', {'encoding': 'utf8'}).trim().split('=')[1], 10) * 1024; + } +}; diff --git a/package-lock.json b/package-lock.json index fc9fd69..91a717b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "SMLoadr", - "version": "1.8.0", + "version": "1.9.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -10,23 +10,15 @@ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { "co": "4.6.0", - "fast-deep-equal": "1.0.0", + "fast-deep-equal": "1.1.0", "fast-json-stable-stringify": "2.0.0", "json-schema-traverse": "0.3.1" } }, - "ansi-escape-sequences": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.0.0.tgz", - "integrity": "sha512-v+0wW9Wezwsyb0uF4aBVCjmSqit3Ru7PZFziGF0o2KwTvN2zWfTi3BRLq9EkJFdg3eBbyERXGTntVpBxH1J68Q==", - "requires": { - "array-back": "2.0.0" - } - }, "ansi-escapes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" }, "ansi-regex": { "version": "3.0.0", @@ -34,9 +26,9 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { "color-convert": "1.9.1" } @@ -68,6 +60,11 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -79,9 +76,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" }, "bcrypt-pbkdf": { "version": "1.0.1", @@ -102,46 +99,31 @@ "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, - "browser-id3-writer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/browser-id3-writer/-/browser-id3-writer-4.0.0.tgz", - "integrity": "sha512-Q8ufttKbt1+vu5giG81o+yvNHg54NdNoWi1sFgCMAsOSKF7XvsjlfRZc4vKzbxP5LTnkoFRY2RusC5mM+Kkq8Q==" - }, - "buffer-alloc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.1.0.tgz", - "integrity": "sha1-BVFNM78WVtNUDGhPZbEgLpDsowM=", + "cache-manager": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-2.9.0.tgz", + "integrity": "sha1-Xh9jF8oaJeQN3zZacWJ1evFSNT4=", "requires": { - "buffer-alloc-unsafe": "0.1.1", - "buffer-fill": "0.1.0" + "async": "1.5.2", + "lru-cache": "4.0.0" } }, - "buffer-alloc-unsafe": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz", - "integrity": "sha1-/+H2dVHdBVc33iUzN7/oU9+rGmo=" - }, - "buffer-fill": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-0.1.0.tgz", - "integrity": "sha1-ypRw6NTRuXf9dUP04qtqfclRAag=" - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "supports-color": "5.3.0" } }, "chardet": { @@ -191,17 +173,17 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { "delayed-stream": "1.0.0" } }, "command-line-args": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.0.1.tgz", - "integrity": "sha512-gRJDcIjFSzMcmG/GrJlgL0wWoAxr11mVzCq32bjka0endupm9meLwvoJUKc4HDeFiEIB2X3GvNrhF5cKO4Bd4A==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.0.2.tgz", + "integrity": "sha512-/qPcbL8zpqg53x4rAaqMFlRV4opN3pbla7I7k9x8kyOBMQoGT6WltjN6sXZuxOXw6DgdK7Ad+ijYS5gjcr7vlA==", "requires": { "argv-tools": "0.1.1", "array-back": "2.0.0", @@ -211,13 +193,13 @@ } }, "command-line-usage": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", - "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-5.0.4.tgz", + "integrity": "sha512-h17lBwC5bl5RdukPbXji75+cg2/Qbny6kGsmLoy34s9DNH90RwRvJKb+VU5j4YY9HzYl7twLaOWDJQ4b9U+p/Q==", "requires": { - "ansi-escape-sequences": "4.0.0", "array-back": "2.0.0", - "table-layout": "0.4.2", + "chalk": "2.3.2", + "table-layout": "0.4.3", "typical": "2.6.1" } }, @@ -239,7 +221,7 @@ "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } } } @@ -279,6 +261,11 @@ "jsbn": "0.1.1" } }, + "escape-regexp": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/escape-regexp/-/escape-regexp-0.0.1.tgz", + "integrity": "sha1-9EvaEtRbvfnLf4Yu5+SCez3TIlQ=" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -290,12 +277,12 @@ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, "external-editor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "requires": { "chardet": "0.4.2", - "iconv-lite": "0.4.19", + "iconv-lite": "0.4.21", "tmp": "0.0.33" } }, @@ -305,9 +292,9 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -331,34 +318,38 @@ "test-value": "3.0.0" } }, - "flac-metadata": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/flac-metadata/-/flac-metadata-0.1.1.tgz", - "integrity": "sha1-wC+KBtJL1bad4rhVEsbkW9j5F2w=" - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "combined-stream": "1.0.6", + "mime-types": "2.1.18" } }, - "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "fs-finder": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/fs-finder/-/fs-finder-1.8.1.tgz", + "integrity": "sha1-EG/qiqidCvNDNgZj1YVYYsrhuHQ=", "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "4.0.0", - "universalify": "0.1.1" + "async": "0.2.10", + "escape-regexp": "0.0.1", + "moment": "2.5.1", + "operator-compare": "1.0.3", + "q": "1.0.1" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + } } }, "getpass": { @@ -372,7 +363,8 @@ "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "optional": true }, "har-schema": { "version": "2.0.0", @@ -389,9 +381,9 @@ } }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "hawk": { "version": "6.0.2", @@ -400,14 +392,14 @@ "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", - "hoek": "4.2.0", + "hoek": "4.2.1", "sntp": "2.1.0" } }, "hoek": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, "http-signature": { "version": "1.2.0", @@ -416,13 +408,16 @@ "requires": { "assert-plus": "1.0.0", "jsprim": "1.4.1", - "sshpk": "1.13.1" + "sshpk": "1.14.1" } }, "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", + "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "requires": { + "safer-buffer": "2.1.2" + } }, "inherits": { "version": "2.0.1", @@ -430,20 +425,20 @@ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" }, "inquirer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.0.1.tgz", - "integrity": "sha512-si5Jmjj6ngjkDSPt/MwuIysUNNKu8SGWnweZE2QXRfd5SKJgDown8IDbHQiS5WLxqEQDQC0Vjcgtpw1XyZJWpw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.0", + "ansi-escapes": "3.1.0", + "chalk": "2.3.2", "cli-cursor": "2.1.0", "cli-width": "2.2.0", - "external-editor": "2.1.0", + "external-editor": "2.2.0", "figures": "2.0.0", - "lodash": "4.17.4", + "lodash": "4.17.5", "mute-stream": "0.0.7", "run-async": "2.3.0", - "rxjs": "5.5.6", + "rxjs": "5.5.8", "string-width": "2.1.1", "strip-ansi": "4.0.0", "through": "2.3.8" @@ -510,9 +505,9 @@ } }, "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" }, "lodash.camelcase": { "version": "4.3.0", @@ -524,33 +519,44 @@ "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" }, + "log": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/log/-/log-1.4.0.tgz", + "integrity": "sha1-S6HYkP3iSbAx3KA7w36q8yVlbxw=" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "requires": { - "chalk": "2.3.0" + "chalk": "2.3.2" + } + }, + "lru-cache": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.0.tgz", + "integrity": "sha1-tcvwFVbBaWb+vlTO7A+03JDfbCg=", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" } }, "md5-file": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.2.3.tgz", - "integrity": "sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==", - "requires": { - "buffer-alloc": "1.1.0" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-4.0.0.tgz", + "integrity": "sha512-UC0qFwyAjn4YdPpKaDNw6gNxRf7Mcx7jC1UGCY4boCzgvU2Aoc1mOGzTtrjjLKhM5ivsnhoKpQVxKPp+1j1qwg==" }, "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" }, "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "requires": { - "mime-db": "1.30.0" + "mime-db": "1.33.0" } }, "mimic-fn": { @@ -558,19 +564,16 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" }, + "moment": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.5.1.tgz", + "integrity": "sha1-cUajkAUzBkynmdXnkvTkgO4Ogrw=" + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, - "nano-cache": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/nano-cache/-/nano-cache-1.1.1.tgz", - "integrity": "sha1-UQbZXzkstENZZU4hzAFa4hjnVGY=", - "requires": { - "extend": "3.0.1" - } - }, "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", @@ -589,6 +592,11 @@ "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=" }, + "operator-compare": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/operator-compare/-/operator-compare-1.0.3.tgz", + "integrity": "sha1-jQbQlLwbg6YH/JyfOABEeIZZGvk=" + }, "ora": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ora/-/ora-2.0.0.tgz", @@ -645,11 +653,21 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, + "q": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", + "integrity": "sha1-EYcq7t7okmgRCxCnGESP+xARKhQ=" + }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", @@ -661,41 +679,58 @@ "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=" }, "request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "requires": { "aws-sign2": "0.7.0", - "aws4": "1.6.0", + "aws4": "1.7.0", "caseless": "0.12.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "2.3.1", + "form-data": "2.3.2", "har-validator": "5.0.3", "hawk": "6.0.2", "http-signature": "1.2.0", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", + "mime-types": "2.1.18", "oauth-sign": "0.8.2", "performance-now": "2.1.0", "qs": "6.5.1", "safe-buffer": "5.1.1", "stringstream": "0.0.5", - "tough-cookie": "2.3.3", + "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", "uuid": "3.2.1" } }, - "request-promise-cache": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/request-promise-cache/-/request-promise-cache-1.0.6.tgz", - "integrity": "sha1-d8opARFlG0UnLzFA6cDoNXCHiMM=", + "request-plus": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/request-plus/-/request-plus-1.0.1.tgz", + "integrity": "sha1-ANlMJReog5qdtP3PCq8WoP30ngs=", "requires": { - "nano-cache": "1.1.1", - "request": "2.83.0" + "request-promise-native": "1.0.5" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "requires": { + "lodash": "4.17.5" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "1.1.1", + "tough-cookie": "2.3.4" } }, "restore-cursor": { @@ -716,9 +751,9 @@ } }, "rxjs": { - "version": "5.5.6", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz", - "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==", + "version": "5.5.8", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.8.tgz", + "integrity": "sha512-Bz7qou7VAIoGiglJZbzbXa4vpX5BmTTN2Dj/se6+SwADtw4SihqBIiEa7VmTXJ8pynvq0iFr5Gx9VLyye1rIxQ==", "requires": { "symbol-observable": "1.0.1" } @@ -728,6 +763,11 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "sanitize-filename": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", @@ -746,13 +786,13 @@ "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "requires": { "asn1": "0.2.3", "assert-plus": "1.0.0", @@ -764,6 +804,11 @@ "tweetnacl": "0.14.5" } }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -787,11 +832,11 @@ } }, "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "requires": { - "has-flag": "2.0.0" + "has-flag": "3.0.0" } }, "symbol-observable": { @@ -800,9 +845,9 @@ "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" }, "table-layout": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.2.tgz", - "integrity": "sha512-tygyl5+eSHj4chpq5Zfy6cpc7MOUBClAW9ozghFH7hg9bAUzShOYn+/vUzTRkKOSLJWKfgYtP2tAU2c0oAD8eg==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.3.tgz", + "integrity": "sha512-MIhflPM38ejKrFwWwC3P9x3eHvMo5G5AmNo29Qtz2HpBl5KD2GCcmOErjgNtUQLv/qaqVDagfJY3rJLPDvEgLg==", "requires": { "array-back": "2.0.0", "deep-extend": "0.5.0", @@ -834,9 +879,9 @@ } }, "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "requires": { "punycode": "1.4.1" } @@ -868,11 +913,6 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" }, - "universalify": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" - }, "utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", @@ -917,6 +957,11 @@ "reduce-flatten": "1.0.1", "typical": "2.6.1" } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" } } } diff --git a/package.json b/package.json index 4f1c7e3..05a0d3f 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,33 @@ { "name": "SMLoadr", - "version": "1.8.0", + "version": "1.9.0", "description": "A streaming music downloader written in NodeJS.", "author": "SMLoadrDev", "license": "Unlicense", "main": "SMLoadr.js", "bin": "SMLoadr.js", + "repository": { + "type": "git", + "url": "https://git.teknik.io/SMLoadrDev/SMLoadr.git" + }, + "engines": { + "node": ">=8.0.0" + }, "dependencies": { "bluebird": "^3.5.1", - "browser-id3-writer": "^4.0.0", - "chalk": "^2.3.0", - "command-line-args": "^5.0.1", - "command-line-usage": "^4.1.0", - "flac-metadata": "^0.1.1", - "fs-extra": "^5.0.0", - "inquirer": "^5.0.1", + "cache-manager": "^2.9.0", + "chalk": "^2.3.2", + "command-line-args": "^5.0.2", + "command-line-usage": "^5.0.4", + "fs-finder": "^1.8.1", + "inquirer": "^5.2.0", "jsonfile": "^4.0.0", - "md5-file": "^3.2.3", + "log": "^1.4.0", + "md5-file": "^4.0.0", "openurl": "^1.1.1", "ora": "^2.0.0", - "request-promise-cache": "^1.0.6", + "request": "^2.85.0", + "request-plus": "^1.0.1", "sanitize-filename": "^1.6.1", "util": "^0.10.3" }