Showing
710 changed files
with
4806 additions
and
0 deletions
SpotifyPlaylistExport/getMe.js
0 → 100644
| 1 | +const fs = require('fs') | ||
| 2 | +const SpotifyWebApi = require('spotify-web-api-node'); | ||
| 3 | +const token = "BQCk4W06G09JDWCpyAINItN64VUmsV5K7aVzreODllupHpBeFlv5Q2nMrhpm5dNyiv8fPF_b0iOAi1URFRu0iNZM6NN9EsdoFRezDpv6nm0Kvn_sLwR-ECrW55rGC6PLAnaH2txUBp2EZhk4-APd5RUv3uamnGAaVp1M_2k1_nHlwHyzPRJzeLL-fQTx7Sfgf287qF5lT4FtAhMqTLMnQySlY22UsiaglpulLL32cgLi4Bgn3qA7Ti4_VUPsFOIFK8dGr6LS0B3IvR1_NhZbUcPkwXknZBM3RjKT4zT6aaTxs8uy_HhP"; | ||
| 4 | + | ||
| 5 | +const spotifyApi = new SpotifyWebApi(); | ||
| 6 | +spotifyApi.setAccessToken(token); | ||
| 7 | + | ||
| 8 | +//GET MY PROFILE DATA | ||
| 9 | +function getMyData() { | ||
| 10 | + (async () => { | ||
| 11 | + const me = await spotifyApi.getMe(); | ||
| 12 | + // console.log(me.body); | ||
| 13 | + getUserPlaylists(me.body.id); | ||
| 14 | + })().catch(e => { | ||
| 15 | + console.error(e); | ||
| 16 | + }); | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +//GET MY PLAYLISTS | ||
| 20 | +async function getUserPlaylists(userName) { | ||
| 21 | + const data = await spotifyApi.getUserPlaylists(userName) | ||
| 22 | + | ||
| 23 | + console.log("---------------+++++++++++++++++++++++++") | ||
| 24 | + let playlists = [] | ||
| 25 | + | ||
| 26 | + for (let playlist of data.body.items) { | ||
| 27 | + console.log(playlist.name + " " + playlist.id) | ||
| 28 | + | ||
| 29 | + let tracks = await getPlaylistTracks(playlist.id, playlist.name); | ||
| 30 | + // console.log(tracks); | ||
| 31 | + | ||
| 32 | + const tracksJSON = { tracks } | ||
| 33 | + let data = JSON.stringify(tracksJSON); | ||
| 34 | + fs.writeFileSync(playlist.name+'.json', data); | ||
| 35 | + } | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +//GET SONGS FROM PLAYLIST | ||
| 39 | +async function getPlaylistTracks(playlistId, playlistName) { | ||
| 40 | + | ||
| 41 | + const data = await spotifyApi.getPlaylistTracks(playlistId, { | ||
| 42 | + offset: 1, | ||
| 43 | + limit: 100, | ||
| 44 | + fields: 'items' | ||
| 45 | + }) | ||
| 46 | + | ||
| 47 | + // console.log('The playlist contains these tracks', data.body); | ||
| 48 | + // console.log('The playlist contains these tracks: ', data.body.items[0].track); | ||
| 49 | + // console.log("'" + playlistName + "'" + ' contains these tracks:'); | ||
| 50 | + let tracks = []; | ||
| 51 | + | ||
| 52 | + for (let track_obj of data.body.items) { | ||
| 53 | + const track = track_obj.track | ||
| 54 | + tracks.push(track); | ||
| 55 | + console.log(track.name + " : " + track.artists[0].name) | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + console.log("---------------+++++++++++++++++++++++++") | ||
| 59 | + return tracks; | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +getMyData(); |
SpotifyPlaylistExport/index.js
0 → 100644
| 1 | +var SpotifyWebApi = require('spotify-web-api-node'); | ||
| 2 | +const express = require('express') | ||
| 3 | + | ||
| 4 | +// This file is copied from: https://github.com/thelinmichael/spotify-web-api-node/blob/master/examples/tutorial/00-get-access-token.js | ||
| 5 | + | ||
| 6 | +const scopes = [ | ||
| 7 | + 'ugc-image-upload', | ||
| 8 | + 'user-read-playback-state', | ||
| 9 | + 'user-modify-playback-state', | ||
| 10 | + 'user-read-currently-playing', | ||
| 11 | + 'streaming', | ||
| 12 | + 'app-remote-control', | ||
| 13 | + 'user-read-email', | ||
| 14 | + 'user-read-private', | ||
| 15 | + 'playlist-read-collaborative', | ||
| 16 | + 'playlist-modify-public', | ||
| 17 | + 'playlist-read-private', | ||
| 18 | + 'playlist-modify-private', | ||
| 19 | + 'user-library-modify', | ||
| 20 | + 'user-library-read', | ||
| 21 | + 'user-top-read', | ||
| 22 | + 'user-read-playback-position', | ||
| 23 | + 'user-read-recently-played', | ||
| 24 | + 'user-follow-read', | ||
| 25 | + 'user-follow-modify' | ||
| 26 | + ]; | ||
| 27 | + | ||
| 28 | +// credentials are optional | ||
| 29 | +var spotifyApi = new SpotifyWebApi({ | ||
| 30 | + clientId: "faf7865d62b5488da2f6bca05e63a075", | ||
| 31 | + clientSecret: "b888f07e8986499aa70950b0235d81eb", | ||
| 32 | + redirectUri: 'http://localhost:8888/callback' | ||
| 33 | + }); | ||
| 34 | + | ||
| 35 | + const app = express(); | ||
| 36 | + | ||
| 37 | + app.get('/login', (req, res) => { | ||
| 38 | + res.redirect(spotifyApi.createAuthorizeURL(scopes)); | ||
| 39 | + }); | ||
| 40 | + | ||
| 41 | + app.get('/callback', (req, res) => { | ||
| 42 | + const error = req.query.error; | ||
| 43 | + const code = req.query.code; | ||
| 44 | + const state = req.query.state; | ||
| 45 | + | ||
| 46 | + if (error) { | ||
| 47 | + console.error('Callback Error:', error); | ||
| 48 | + res.send(`Callback Error: ${error}`); | ||
| 49 | + return; | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + spotifyApi | ||
| 53 | + .authorizationCodeGrant(code) | ||
| 54 | + .then(data => { | ||
| 55 | + const access_token = data.body['access_token']; | ||
| 56 | + const refresh_token = data.body['refresh_token']; | ||
| 57 | + const expires_in = data.body['expires_in']; | ||
| 58 | + | ||
| 59 | + spotifyApi.setAccessToken(access_token); | ||
| 60 | + spotifyApi.setRefreshToken(refresh_token); | ||
| 61 | + | ||
| 62 | + console.log('access_token:', access_token); | ||
| 63 | + console.log('refresh_token:', refresh_token); | ||
| 64 | + | ||
| 65 | + console.log( | ||
| 66 | + `Sucessfully retreived access token. Expires in ${expires_in} s.` | ||
| 67 | + ); | ||
| 68 | + res.send('Success! You can now close the window.'); | ||
| 69 | + | ||
| 70 | + setInterval(async () => { | ||
| 71 | + const data = await spotifyApi.refreshAccessToken(); | ||
| 72 | + const access_token = data.body['access_token']; | ||
| 73 | + | ||
| 74 | + console.log('The access token has been refreshed!'); | ||
| 75 | + console.log('access_token:', access_token); | ||
| 76 | + spotifyApi.setAccessToken(access_token); | ||
| 77 | + }, expires_in / 2 * 1000); | ||
| 78 | + }) | ||
| 79 | + .catch(error => { | ||
| 80 | + console.error('Error getting Tokens:', error); | ||
| 81 | + res.send(`Error getting Tokens: ${error}`); | ||
| 82 | + }); | ||
| 83 | + }); | ||
| 84 | + | ||
| 85 | + app.listen(8888, () => | ||
| 86 | + console.log( | ||
| 87 | + 'HTTP Server up. Now go to http://localhost:8888/login in your browser.' | ||
| 88 | + ) | ||
| 89 | + ); | ||
| 90 | + | ||
| 91 | + | ||
| 92 | + | ||
| 93 | + | ||
| 94 | + | ||
| 95 | + |
SpotifyPlaylistExport/node_modules/.bin/mime
0 → 100644
| 1 | +#!/bin/sh | ||
| 2 | +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") | ||
| 3 | + | ||
| 4 | +case `uname` in | ||
| 5 | + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; | ||
| 6 | +esac | ||
| 7 | + | ||
| 8 | +if [ -x "$basedir/node" ]; then | ||
| 9 | + "$basedir/node" "$basedir/../mime/cli.js" "$@" | ||
| 10 | + ret=$? | ||
| 11 | +else | ||
| 12 | + node "$basedir/../mime/cli.js" "$@" | ||
| 13 | + ret=$? | ||
| 14 | +fi | ||
| 15 | +exit $ret |
| 1 | +@ECHO off | ||
| 2 | +SETLOCAL | ||
| 3 | +CALL :find_dp0 | ||
| 4 | + | ||
| 5 | +IF EXIST "%dp0%\node.exe" ( | ||
| 6 | + SET "_prog=%dp0%\node.exe" | ||
| 7 | +) ELSE ( | ||
| 8 | + SET "_prog=node" | ||
| 9 | + SET PATHEXT=%PATHEXT:;.JS;=;% | ||
| 10 | +) | ||
| 11 | + | ||
| 12 | +"%_prog%" "%dp0%\..\mime\cli.js" %* | ||
| 13 | +ENDLOCAL | ||
| 14 | +EXIT /b %errorlevel% | ||
| 15 | +:find_dp0 | ||
| 16 | +SET dp0=%~dp0 | ||
| 17 | +EXIT /b |
| 1 | +#!/usr/bin/env pwsh | ||
| 2 | +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent | ||
| 3 | + | ||
| 4 | +$exe="" | ||
| 5 | +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { | ||
| 6 | + # Fix case when both the Windows and Linux builds of Node | ||
| 7 | + # are installed in the same directory | ||
| 8 | + $exe=".exe" | ||
| 9 | +} | ||
| 10 | +$ret=0 | ||
| 11 | +if (Test-Path "$basedir/node$exe") { | ||
| 12 | + & "$basedir/node$exe" "$basedir/../mime/cli.js" $args | ||
| 13 | + $ret=$LASTEXITCODE | ||
| 14 | +} else { | ||
| 15 | + & "node$exe" "$basedir/../mime/cli.js" $args | ||
| 16 | + $ret=$LASTEXITCODE | ||
| 17 | +} | ||
| 18 | +exit $ret |
| 1 | +#!/bin/sh | ||
| 2 | +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") | ||
| 3 | + | ||
| 4 | +case `uname` in | ||
| 5 | + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; | ||
| 6 | +esac | ||
| 7 | + | ||
| 8 | +if [ -x "$basedir/node" ]; then | ||
| 9 | + "$basedir/node" "$basedir/../semver/bin/semver.js" "$@" | ||
| 10 | + ret=$? | ||
| 11 | +else | ||
| 12 | + node "$basedir/../semver/bin/semver.js" "$@" | ||
| 13 | + ret=$? | ||
| 14 | +fi | ||
| 15 | +exit $ret |
| 1 | +@ECHO off | ||
| 2 | +SETLOCAL | ||
| 3 | +CALL :find_dp0 | ||
| 4 | + | ||
| 5 | +IF EXIST "%dp0%\node.exe" ( | ||
| 6 | + SET "_prog=%dp0%\node.exe" | ||
| 7 | +) ELSE ( | ||
| 8 | + SET "_prog=node" | ||
| 9 | + SET PATHEXT=%PATHEXT:;.JS;=;% | ||
| 10 | +) | ||
| 11 | + | ||
| 12 | +"%_prog%" "%dp0%\..\semver\bin\semver.js" %* | ||
| 13 | +ENDLOCAL | ||
| 14 | +EXIT /b %errorlevel% | ||
| 15 | +:find_dp0 | ||
| 16 | +SET dp0=%~dp0 | ||
| 17 | +EXIT /b |
| 1 | +#!/usr/bin/env pwsh | ||
| 2 | +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent | ||
| 3 | + | ||
| 4 | +$exe="" | ||
| 5 | +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { | ||
| 6 | + # Fix case when both the Windows and Linux builds of Node | ||
| 7 | + # are installed in the same directory | ||
| 8 | + $exe=".exe" | ||
| 9 | +} | ||
| 10 | +$ret=0 | ||
| 11 | +if (Test-Path "$basedir/node$exe") { | ||
| 12 | + & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args | ||
| 13 | + $ret=$LASTEXITCODE | ||
| 14 | +} else { | ||
| 15 | + & "node$exe" "$basedir/../semver/bin/semver.js" $args | ||
| 16 | + $ret=$LASTEXITCODE | ||
| 17 | +} | ||
| 18 | +exit $ret |
| 1 | +1.3.7 / 2019-04-29 | ||
| 2 | +================== | ||
| 3 | + | ||
| 4 | + * deps: negotiator@0.6.2 | ||
| 5 | + - Fix sorting charset, encoding, and language with extra parameters | ||
| 6 | + | ||
| 7 | +1.3.6 / 2019-04-28 | ||
| 8 | +================== | ||
| 9 | + | ||
| 10 | + * deps: mime-types@~2.1.24 | ||
| 11 | + - deps: mime-db@~1.40.0 | ||
| 12 | + | ||
| 13 | +1.3.5 / 2018-02-28 | ||
| 14 | +================== | ||
| 15 | + | ||
| 16 | + * deps: mime-types@~2.1.18 | ||
| 17 | + - deps: mime-db@~1.33.0 | ||
| 18 | + | ||
| 19 | +1.3.4 / 2017-08-22 | ||
| 20 | +================== | ||
| 21 | + | ||
| 22 | + * deps: mime-types@~2.1.16 | ||
| 23 | + - deps: mime-db@~1.29.0 | ||
| 24 | + | ||
| 25 | +1.3.3 / 2016-05-02 | ||
| 26 | +================== | ||
| 27 | + | ||
| 28 | + * deps: mime-types@~2.1.11 | ||
| 29 | + - deps: mime-db@~1.23.0 | ||
| 30 | + * deps: negotiator@0.6.1 | ||
| 31 | + - perf: improve `Accept` parsing speed | ||
| 32 | + - perf: improve `Accept-Charset` parsing speed | ||
| 33 | + - perf: improve `Accept-Encoding` parsing speed | ||
| 34 | + - perf: improve `Accept-Language` parsing speed | ||
| 35 | + | ||
| 36 | +1.3.2 / 2016-03-08 | ||
| 37 | +================== | ||
| 38 | + | ||
| 39 | + * deps: mime-types@~2.1.10 | ||
| 40 | + - Fix extension of `application/dash+xml` | ||
| 41 | + - Update primary extension for `audio/mp4` | ||
| 42 | + - deps: mime-db@~1.22.0 | ||
| 43 | + | ||
| 44 | +1.3.1 / 2016-01-19 | ||
| 45 | +================== | ||
| 46 | + | ||
| 47 | + * deps: mime-types@~2.1.9 | ||
| 48 | + - deps: mime-db@~1.21.0 | ||
| 49 | + | ||
| 50 | +1.3.0 / 2015-09-29 | ||
| 51 | +================== | ||
| 52 | + | ||
| 53 | + * deps: mime-types@~2.1.7 | ||
| 54 | + - deps: mime-db@~1.19.0 | ||
| 55 | + * deps: negotiator@0.6.0 | ||
| 56 | + - Fix including type extensions in parameters in `Accept` parsing | ||
| 57 | + - Fix parsing `Accept` parameters with quoted equals | ||
| 58 | + - Fix parsing `Accept` parameters with quoted semicolons | ||
| 59 | + - Lazy-load modules from main entry point | ||
| 60 | + - perf: delay type concatenation until needed | ||
| 61 | + - perf: enable strict mode | ||
| 62 | + - perf: hoist regular expressions | ||
| 63 | + - perf: remove closures getting spec properties | ||
| 64 | + - perf: remove a closure from media type parsing | ||
| 65 | + - perf: remove property delete from media type parsing | ||
| 66 | + | ||
| 67 | +1.2.13 / 2015-09-06 | ||
| 68 | +=================== | ||
| 69 | + | ||
| 70 | + * deps: mime-types@~2.1.6 | ||
| 71 | + - deps: mime-db@~1.18.0 | ||
| 72 | + | ||
| 73 | +1.2.12 / 2015-07-30 | ||
| 74 | +=================== | ||
| 75 | + | ||
| 76 | + * deps: mime-types@~2.1.4 | ||
| 77 | + - deps: mime-db@~1.16.0 | ||
| 78 | + | ||
| 79 | +1.2.11 / 2015-07-16 | ||
| 80 | +=================== | ||
| 81 | + | ||
| 82 | + * deps: mime-types@~2.1.3 | ||
| 83 | + - deps: mime-db@~1.15.0 | ||
| 84 | + | ||
| 85 | +1.2.10 / 2015-07-01 | ||
| 86 | +=================== | ||
| 87 | + | ||
| 88 | + * deps: mime-types@~2.1.2 | ||
| 89 | + - deps: mime-db@~1.14.0 | ||
| 90 | + | ||
| 91 | +1.2.9 / 2015-06-08 | ||
| 92 | +================== | ||
| 93 | + | ||
| 94 | + * deps: mime-types@~2.1.1 | ||
| 95 | + - perf: fix deopt during mapping | ||
| 96 | + | ||
| 97 | +1.2.8 / 2015-06-07 | ||
| 98 | +================== | ||
| 99 | + | ||
| 100 | + * deps: mime-types@~2.1.0 | ||
| 101 | + - deps: mime-db@~1.13.0 | ||
| 102 | + * perf: avoid argument reassignment & argument slice | ||
| 103 | + * perf: avoid negotiator recursive construction | ||
| 104 | + * perf: enable strict mode | ||
| 105 | + * perf: remove unnecessary bitwise operator | ||
| 106 | + | ||
| 107 | +1.2.7 / 2015-05-10 | ||
| 108 | +================== | ||
| 109 | + | ||
| 110 | + * deps: negotiator@0.5.3 | ||
| 111 | + - Fix media type parameter matching to be case-insensitive | ||
| 112 | + | ||
| 113 | +1.2.6 / 2015-05-07 | ||
| 114 | +================== | ||
| 115 | + | ||
| 116 | + * deps: mime-types@~2.0.11 | ||
| 117 | + - deps: mime-db@~1.9.1 | ||
| 118 | + * deps: negotiator@0.5.2 | ||
| 119 | + - Fix comparing media types with quoted values | ||
| 120 | + - Fix splitting media types with quoted commas | ||
| 121 | + | ||
| 122 | +1.2.5 / 2015-03-13 | ||
| 123 | +================== | ||
| 124 | + | ||
| 125 | + * deps: mime-types@~2.0.10 | ||
| 126 | + - deps: mime-db@~1.8.0 | ||
| 127 | + | ||
| 128 | +1.2.4 / 2015-02-14 | ||
| 129 | +================== | ||
| 130 | + | ||
| 131 | + * Support Node.js 0.6 | ||
| 132 | + * deps: mime-types@~2.0.9 | ||
| 133 | + - deps: mime-db@~1.7.0 | ||
| 134 | + * deps: negotiator@0.5.1 | ||
| 135 | + - Fix preference sorting to be stable for long acceptable lists | ||
| 136 | + | ||
| 137 | +1.2.3 / 2015-01-31 | ||
| 138 | +================== | ||
| 139 | + | ||
| 140 | + * deps: mime-types@~2.0.8 | ||
| 141 | + - deps: mime-db@~1.6.0 | ||
| 142 | + | ||
| 143 | +1.2.2 / 2014-12-30 | ||
| 144 | +================== | ||
| 145 | + | ||
| 146 | + * deps: mime-types@~2.0.7 | ||
| 147 | + - deps: mime-db@~1.5.0 | ||
| 148 | + | ||
| 149 | +1.2.1 / 2014-12-30 | ||
| 150 | +================== | ||
| 151 | + | ||
| 152 | + * deps: mime-types@~2.0.5 | ||
| 153 | + - deps: mime-db@~1.3.1 | ||
| 154 | + | ||
| 155 | +1.2.0 / 2014-12-19 | ||
| 156 | +================== | ||
| 157 | + | ||
| 158 | + * deps: negotiator@0.5.0 | ||
| 159 | + - Fix list return order when large accepted list | ||
| 160 | + - Fix missing identity encoding when q=0 exists | ||
| 161 | + - Remove dynamic building of Negotiator class | ||
| 162 | + | ||
| 163 | +1.1.4 / 2014-12-10 | ||
| 164 | +================== | ||
| 165 | + | ||
| 166 | + * deps: mime-types@~2.0.4 | ||
| 167 | + - deps: mime-db@~1.3.0 | ||
| 168 | + | ||
| 169 | +1.1.3 / 2014-11-09 | ||
| 170 | +================== | ||
| 171 | + | ||
| 172 | + * deps: mime-types@~2.0.3 | ||
| 173 | + - deps: mime-db@~1.2.0 | ||
| 174 | + | ||
| 175 | +1.1.2 / 2014-10-14 | ||
| 176 | +================== | ||
| 177 | + | ||
| 178 | + * deps: negotiator@0.4.9 | ||
| 179 | + - Fix error when media type has invalid parameter | ||
| 180 | + | ||
| 181 | +1.1.1 / 2014-09-28 | ||
| 182 | +================== | ||
| 183 | + | ||
| 184 | + * deps: mime-types@~2.0.2 | ||
| 185 | + - deps: mime-db@~1.1.0 | ||
| 186 | + * deps: negotiator@0.4.8 | ||
| 187 | + - Fix all negotiations to be case-insensitive | ||
| 188 | + - Stable sort preferences of same quality according to client order | ||
| 189 | + | ||
| 190 | +1.1.0 / 2014-09-02 | ||
| 191 | +================== | ||
| 192 | + | ||
| 193 | + * update `mime-types` | ||
| 194 | + | ||
| 195 | +1.0.7 / 2014-07-04 | ||
| 196 | +================== | ||
| 197 | + | ||
| 198 | + * Fix wrong type returned from `type` when match after unknown extension | ||
| 199 | + | ||
| 200 | +1.0.6 / 2014-06-24 | ||
| 201 | +================== | ||
| 202 | + | ||
| 203 | + * deps: negotiator@0.4.7 | ||
| 204 | + | ||
| 205 | +1.0.5 / 2014-06-20 | ||
| 206 | +================== | ||
| 207 | + | ||
| 208 | + * fix crash when unknown extension given | ||
| 209 | + | ||
| 210 | +1.0.4 / 2014-06-19 | ||
| 211 | +================== | ||
| 212 | + | ||
| 213 | + * use `mime-types` | ||
| 214 | + | ||
| 215 | +1.0.3 / 2014-06-11 | ||
| 216 | +================== | ||
| 217 | + | ||
| 218 | + * deps: negotiator@0.4.6 | ||
| 219 | + - Order by specificity when quality is the same | ||
| 220 | + | ||
| 221 | +1.0.2 / 2014-05-29 | ||
| 222 | +================== | ||
| 223 | + | ||
| 224 | + * Fix interpretation when header not in request | ||
| 225 | + * deps: pin negotiator@0.4.5 | ||
| 226 | + | ||
| 227 | +1.0.1 / 2014-01-18 | ||
| 228 | +================== | ||
| 229 | + | ||
| 230 | + * Identity encoding isn't always acceptable | ||
| 231 | + * deps: negotiator@~0.4.0 | ||
| 232 | + | ||
| 233 | +1.0.0 / 2013-12-27 | ||
| 234 | +================== | ||
| 235 | + | ||
| 236 | + * Genesis |
| 1 | +(The MIT License) | ||
| 2 | + | ||
| 3 | +Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> | ||
| 4 | +Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com> | ||
| 5 | + | ||
| 6 | +Permission is hereby granted, free of charge, to any person obtaining | ||
| 7 | +a copy of this software and associated documentation files (the | ||
| 8 | +'Software'), to deal in the Software without restriction, including | ||
| 9 | +without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
| 11 | +permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | +the following conditions: | ||
| 13 | + | ||
| 14 | +The above copyright notice and this permission notice shall be | ||
| 15 | +included in all copies or substantial portions of the Software. | ||
| 16 | + | ||
| 17 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
| 18 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 19 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| 20 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
| 21 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
| 22 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
| 23 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 1 | +# accepts | ||
| 2 | + | ||
| 3 | +[![NPM Version][npm-version-image]][npm-url] | ||
| 4 | +[![NPM Downloads][npm-downloads-image]][npm-url] | ||
| 5 | +[![Node.js Version][node-version-image]][node-version-url] | ||
| 6 | +[![Build Status][travis-image]][travis-url] | ||
| 7 | +[![Test Coverage][coveralls-image]][coveralls-url] | ||
| 8 | + | ||
| 9 | +Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). | ||
| 10 | +Extracted from [koa](https://www.npmjs.com/package/koa) for general use. | ||
| 11 | + | ||
| 12 | +In addition to negotiator, it allows: | ||
| 13 | + | ||
| 14 | +- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` | ||
| 15 | + as well as `('text/html', 'application/json')`. | ||
| 16 | +- Allows type shorthands such as `json`. | ||
| 17 | +- Returns `false` when no types match | ||
| 18 | +- Treats non-existent headers as `*` | ||
| 19 | + | ||
| 20 | +## Installation | ||
| 21 | + | ||
| 22 | +This is a [Node.js](https://nodejs.org/en/) module available through the | ||
| 23 | +[npm registry](https://www.npmjs.com/). Installation is done using the | ||
| 24 | +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): | ||
| 25 | + | ||
| 26 | +```sh | ||
| 27 | +$ npm install accepts | ||
| 28 | +``` | ||
| 29 | + | ||
| 30 | +## API | ||
| 31 | + | ||
| 32 | +<!-- eslint-disable no-unused-vars --> | ||
| 33 | + | ||
| 34 | +```js | ||
| 35 | +var accepts = require('accepts') | ||
| 36 | +``` | ||
| 37 | + | ||
| 38 | +### accepts(req) | ||
| 39 | + | ||
| 40 | +Create a new `Accepts` object for the given `req`. | ||
| 41 | + | ||
| 42 | +#### .charset(charsets) | ||
| 43 | + | ||
| 44 | +Return the first accepted charset. If nothing in `charsets` is accepted, | ||
| 45 | +then `false` is returned. | ||
| 46 | + | ||
| 47 | +#### .charsets() | ||
| 48 | + | ||
| 49 | +Return the charsets that the request accepts, in the order of the client's | ||
| 50 | +preference (most preferred first). | ||
| 51 | + | ||
| 52 | +#### .encoding(encodings) | ||
| 53 | + | ||
| 54 | +Return the first accepted encoding. If nothing in `encodings` is accepted, | ||
| 55 | +then `false` is returned. | ||
| 56 | + | ||
| 57 | +#### .encodings() | ||
| 58 | + | ||
| 59 | +Return the encodings that the request accepts, in the order of the client's | ||
| 60 | +preference (most preferred first). | ||
| 61 | + | ||
| 62 | +#### .language(languages) | ||
| 63 | + | ||
| 64 | +Return the first accepted language. If nothing in `languages` is accepted, | ||
| 65 | +then `false` is returned. | ||
| 66 | + | ||
| 67 | +#### .languages() | ||
| 68 | + | ||
| 69 | +Return the languages that the request accepts, in the order of the client's | ||
| 70 | +preference (most preferred first). | ||
| 71 | + | ||
| 72 | +#### .type(types) | ||
| 73 | + | ||
| 74 | +Return the first accepted type (and it is returned as the same text as what | ||
| 75 | +appears in the `types` array). If nothing in `types` is accepted, then `false` | ||
| 76 | +is returned. | ||
| 77 | + | ||
| 78 | +The `types` array can contain full MIME types or file extensions. Any value | ||
| 79 | +that is not a full MIME types is passed to `require('mime-types').lookup`. | ||
| 80 | + | ||
| 81 | +#### .types() | ||
| 82 | + | ||
| 83 | +Return the types that the request accepts, in the order of the client's | ||
| 84 | +preference (most preferred first). | ||
| 85 | + | ||
| 86 | +## Examples | ||
| 87 | + | ||
| 88 | +### Simple type negotiation | ||
| 89 | + | ||
| 90 | +This simple example shows how to use `accepts` to return a different typed | ||
| 91 | +respond body based on what the client wants to accept. The server lists it's | ||
| 92 | +preferences in order and will get back the best match between the client and | ||
| 93 | +server. | ||
| 94 | + | ||
| 95 | +```js | ||
| 96 | +var accepts = require('accepts') | ||
| 97 | +var http = require('http') | ||
| 98 | + | ||
| 99 | +function app (req, res) { | ||
| 100 | + var accept = accepts(req) | ||
| 101 | + | ||
| 102 | + // the order of this list is significant; should be server preferred order | ||
| 103 | + switch (accept.type(['json', 'html'])) { | ||
| 104 | + case 'json': | ||
| 105 | + res.setHeader('Content-Type', 'application/json') | ||
| 106 | + res.write('{"hello":"world!"}') | ||
| 107 | + break | ||
| 108 | + case 'html': | ||
| 109 | + res.setHeader('Content-Type', 'text/html') | ||
| 110 | + res.write('<b>hello, world!</b>') | ||
| 111 | + break | ||
| 112 | + default: | ||
| 113 | + // the fallback is text/plain, so no need to specify it above | ||
| 114 | + res.setHeader('Content-Type', 'text/plain') | ||
| 115 | + res.write('hello, world!') | ||
| 116 | + break | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + res.end() | ||
| 120 | +} | ||
| 121 | + | ||
| 122 | +http.createServer(app).listen(3000) | ||
| 123 | +``` | ||
| 124 | + | ||
| 125 | +You can test this out with the cURL program: | ||
| 126 | +```sh | ||
| 127 | +curl -I -H'Accept: text/html' http://localhost:3000/ | ||
| 128 | +``` | ||
| 129 | + | ||
| 130 | +## License | ||
| 131 | + | ||
| 132 | +[MIT](LICENSE) | ||
| 133 | + | ||
| 134 | +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master | ||
| 135 | +[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master | ||
| 136 | +[node-version-image]: https://badgen.net/npm/node/accepts | ||
| 137 | +[node-version-url]: https://nodejs.org/en/download | ||
| 138 | +[npm-downloads-image]: https://badgen.net/npm/dm/accepts | ||
| 139 | +[npm-url]: https://npmjs.org/package/accepts | ||
| 140 | +[npm-version-image]: https://badgen.net/npm/v/accepts | ||
| 141 | +[travis-image]: https://badgen.net/travis/jshttp/accepts/master | ||
| 142 | +[travis-url]: https://travis-ci.org/jshttp/accepts |
| 1 | +/*! | ||
| 2 | + * accepts | ||
| 3 | + * Copyright(c) 2014 Jonathan Ong | ||
| 4 | + * Copyright(c) 2015 Douglas Christopher Wilson | ||
| 5 | + * MIT Licensed | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +'use strict' | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * Module dependencies. | ||
| 12 | + * @private | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | +var Negotiator = require('negotiator') | ||
| 16 | +var mime = require('mime-types') | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * Module exports. | ||
| 20 | + * @public | ||
| 21 | + */ | ||
| 22 | + | ||
| 23 | +module.exports = Accepts | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * Create a new Accepts object for the given req. | ||
| 27 | + * | ||
| 28 | + * @param {object} req | ||
| 29 | + * @public | ||
| 30 | + */ | ||
| 31 | + | ||
| 32 | +function Accepts (req) { | ||
| 33 | + if (!(this instanceof Accepts)) { | ||
| 34 | + return new Accepts(req) | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + this.headers = req.headers | ||
| 38 | + this.negotiator = new Negotiator(req) | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +/** | ||
| 42 | + * Check if the given `type(s)` is acceptable, returning | ||
| 43 | + * the best match when true, otherwise `undefined`, in which | ||
| 44 | + * case you should respond with 406 "Not Acceptable". | ||
| 45 | + * | ||
| 46 | + * The `type` value may be a single mime type string | ||
| 47 | + * such as "application/json", the extension name | ||
| 48 | + * such as "json" or an array `["json", "html", "text/plain"]`. When a list | ||
| 49 | + * or array is given the _best_ match, if any is returned. | ||
| 50 | + * | ||
| 51 | + * Examples: | ||
| 52 | + * | ||
| 53 | + * // Accept: text/html | ||
| 54 | + * this.types('html'); | ||
| 55 | + * // => "html" | ||
| 56 | + * | ||
| 57 | + * // Accept: text/*, application/json | ||
| 58 | + * this.types('html'); | ||
| 59 | + * // => "html" | ||
| 60 | + * this.types('text/html'); | ||
| 61 | + * // => "text/html" | ||
| 62 | + * this.types('json', 'text'); | ||
| 63 | + * // => "json" | ||
| 64 | + * this.types('application/json'); | ||
| 65 | + * // => "application/json" | ||
| 66 | + * | ||
| 67 | + * // Accept: text/*, application/json | ||
| 68 | + * this.types('image/png'); | ||
| 69 | + * this.types('png'); | ||
| 70 | + * // => undefined | ||
| 71 | + * | ||
| 72 | + * // Accept: text/*;q=.5, application/json | ||
| 73 | + * this.types(['html', 'json']); | ||
| 74 | + * this.types('html', 'json'); | ||
| 75 | + * // => "json" | ||
| 76 | + * | ||
| 77 | + * @param {String|Array} types... | ||
| 78 | + * @return {String|Array|Boolean} | ||
| 79 | + * @public | ||
| 80 | + */ | ||
| 81 | + | ||
| 82 | +Accepts.prototype.type = | ||
| 83 | +Accepts.prototype.types = function (types_) { | ||
| 84 | + var types = types_ | ||
| 85 | + | ||
| 86 | + // support flattened arguments | ||
| 87 | + if (types && !Array.isArray(types)) { | ||
| 88 | + types = new Array(arguments.length) | ||
| 89 | + for (var i = 0; i < types.length; i++) { | ||
| 90 | + types[i] = arguments[i] | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + // no types, return all requested types | ||
| 95 | + if (!types || types.length === 0) { | ||
| 96 | + return this.negotiator.mediaTypes() | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + // no accept header, return first given type | ||
| 100 | + if (!this.headers.accept) { | ||
| 101 | + return types[0] | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + var mimes = types.map(extToMime) | ||
| 105 | + var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) | ||
| 106 | + var first = accepts[0] | ||
| 107 | + | ||
| 108 | + return first | ||
| 109 | + ? types[mimes.indexOf(first)] | ||
| 110 | + : false | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +/** | ||
| 114 | + * Return accepted encodings or best fit based on `encodings`. | ||
| 115 | + * | ||
| 116 | + * Given `Accept-Encoding: gzip, deflate` | ||
| 117 | + * an array sorted by quality is returned: | ||
| 118 | + * | ||
| 119 | + * ['gzip', 'deflate'] | ||
| 120 | + * | ||
| 121 | + * @param {String|Array} encodings... | ||
| 122 | + * @return {String|Array} | ||
| 123 | + * @public | ||
| 124 | + */ | ||
| 125 | + | ||
| 126 | +Accepts.prototype.encoding = | ||
| 127 | +Accepts.prototype.encodings = function (encodings_) { | ||
| 128 | + var encodings = encodings_ | ||
| 129 | + | ||
| 130 | + // support flattened arguments | ||
| 131 | + if (encodings && !Array.isArray(encodings)) { | ||
| 132 | + encodings = new Array(arguments.length) | ||
| 133 | + for (var i = 0; i < encodings.length; i++) { | ||
| 134 | + encodings[i] = arguments[i] | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + // no encodings, return all requested encodings | ||
| 139 | + if (!encodings || encodings.length === 0) { | ||
| 140 | + return this.negotiator.encodings() | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + return this.negotiator.encodings(encodings)[0] || false | ||
| 144 | +} | ||
| 145 | + | ||
| 146 | +/** | ||
| 147 | + * Return accepted charsets or best fit based on `charsets`. | ||
| 148 | + * | ||
| 149 | + * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` | ||
| 150 | + * an array sorted by quality is returned: | ||
| 151 | + * | ||
| 152 | + * ['utf-8', 'utf-7', 'iso-8859-1'] | ||
| 153 | + * | ||
| 154 | + * @param {String|Array} charsets... | ||
| 155 | + * @return {String|Array} | ||
| 156 | + * @public | ||
| 157 | + */ | ||
| 158 | + | ||
| 159 | +Accepts.prototype.charset = | ||
| 160 | +Accepts.prototype.charsets = function (charsets_) { | ||
| 161 | + var charsets = charsets_ | ||
| 162 | + | ||
| 163 | + // support flattened arguments | ||
| 164 | + if (charsets && !Array.isArray(charsets)) { | ||
| 165 | + charsets = new Array(arguments.length) | ||
| 166 | + for (var i = 0; i < charsets.length; i++) { | ||
| 167 | + charsets[i] = arguments[i] | ||
| 168 | + } | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + // no charsets, return all requested charsets | ||
| 172 | + if (!charsets || charsets.length === 0) { | ||
| 173 | + return this.negotiator.charsets() | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + return this.negotiator.charsets(charsets)[0] || false | ||
| 177 | +} | ||
| 178 | + | ||
| 179 | +/** | ||
| 180 | + * Return accepted languages or best fit based on `langs`. | ||
| 181 | + * | ||
| 182 | + * Given `Accept-Language: en;q=0.8, es, pt` | ||
| 183 | + * an array sorted by quality is returned: | ||
| 184 | + * | ||
| 185 | + * ['es', 'pt', 'en'] | ||
| 186 | + * | ||
| 187 | + * @param {String|Array} langs... | ||
| 188 | + * @return {Array|String} | ||
| 189 | + * @public | ||
| 190 | + */ | ||
| 191 | + | ||
| 192 | +Accepts.prototype.lang = | ||
| 193 | +Accepts.prototype.langs = | ||
| 194 | +Accepts.prototype.language = | ||
| 195 | +Accepts.prototype.languages = function (languages_) { | ||
| 196 | + var languages = languages_ | ||
| 197 | + | ||
| 198 | + // support flattened arguments | ||
| 199 | + if (languages && !Array.isArray(languages)) { | ||
| 200 | + languages = new Array(arguments.length) | ||
| 201 | + for (var i = 0; i < languages.length; i++) { | ||
| 202 | + languages[i] = arguments[i] | ||
| 203 | + } | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + // no languages, return all requested languages | ||
| 207 | + if (!languages || languages.length === 0) { | ||
| 208 | + return this.negotiator.languages() | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + return this.negotiator.languages(languages)[0] || false | ||
| 212 | +} | ||
| 213 | + | ||
| 214 | +/** | ||
| 215 | + * Convert extnames to mime. | ||
| 216 | + * | ||
| 217 | + * @param {String} type | ||
| 218 | + * @return {String} | ||
| 219 | + * @private | ||
| 220 | + */ | ||
| 221 | + | ||
| 222 | +function extToMime (type) { | ||
| 223 | + return type.indexOf('/') === -1 | ||
| 224 | + ? mime.lookup(type) | ||
| 225 | + : type | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | +/** | ||
| 229 | + * Check if mime is valid. | ||
| 230 | + * | ||
| 231 | + * @param {String} type | ||
| 232 | + * @return {String} | ||
| 233 | + * @private | ||
| 234 | + */ | ||
| 235 | + | ||
| 236 | +function validMime (type) { | ||
| 237 | + return typeof type === 'string' | ||
| 238 | +} |
| 1 | +{ | ||
| 2 | + "_from": "accepts@~1.3.7", | ||
| 3 | + "_id": "accepts@1.3.7", | ||
| 4 | + "_inBundle": false, | ||
| 5 | + "_integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", | ||
| 6 | + "_location": "/accepts", | ||
| 7 | + "_phantomChildren": {}, | ||
| 8 | + "_requested": { | ||
| 9 | + "type": "range", | ||
| 10 | + "registry": true, | ||
| 11 | + "raw": "accepts@~1.3.7", | ||
| 12 | + "name": "accepts", | ||
| 13 | + "escapedName": "accepts", | ||
| 14 | + "rawSpec": "~1.3.7", | ||
| 15 | + "saveSpec": null, | ||
| 16 | + "fetchSpec": "~1.3.7" | ||
| 17 | + }, | ||
| 18 | + "_requiredBy": [ | ||
| 19 | + "/express" | ||
| 20 | + ], | ||
| 21 | + "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", | ||
| 22 | + "_shasum": "531bc726517a3b2b41f850021c6cc15eaab507cd", | ||
| 23 | + "_spec": "accepts@~1.3.7", | ||
| 24 | + "_where": "C:\\Users\\SIMBA\\Desktop\\SpotifyPlaylistExport-master\\node_modules\\express", | ||
| 25 | + "bugs": { | ||
| 26 | + "url": "https://github.com/jshttp/accepts/issues" | ||
| 27 | + }, | ||
| 28 | + "bundleDependencies": false, | ||
| 29 | + "contributors": [ | ||
| 30 | + { | ||
| 31 | + "name": "Douglas Christopher Wilson", | ||
| 32 | + "email": "doug@somethingdoug.com" | ||
| 33 | + }, | ||
| 34 | + { | ||
| 35 | + "name": "Jonathan Ong", | ||
| 36 | + "email": "me@jongleberry.com", | ||
| 37 | + "url": "http://jongleberry.com" | ||
| 38 | + } | ||
| 39 | + ], | ||
| 40 | + "dependencies": { | ||
| 41 | + "mime-types": "~2.1.24", | ||
| 42 | + "negotiator": "0.6.2" | ||
| 43 | + }, | ||
| 44 | + "deprecated": false, | ||
| 45 | + "description": "Higher-level content negotiation", | ||
| 46 | + "devDependencies": { | ||
| 47 | + "deep-equal": "1.0.1", | ||
| 48 | + "eslint": "5.16.0", | ||
| 49 | + "eslint-config-standard": "12.0.0", | ||
| 50 | + "eslint-plugin-import": "2.17.2", | ||
| 51 | + "eslint-plugin-markdown": "1.0.0", | ||
| 52 | + "eslint-plugin-node": "8.0.1", | ||
| 53 | + "eslint-plugin-promise": "4.1.1", | ||
| 54 | + "eslint-plugin-standard": "4.0.0", | ||
| 55 | + "mocha": "6.1.4", | ||
| 56 | + "nyc": "14.0.0" | ||
| 57 | + }, | ||
| 58 | + "engines": { | ||
| 59 | + "node": ">= 0.6" | ||
| 60 | + }, | ||
| 61 | + "files": [ | ||
| 62 | + "LICENSE", | ||
| 63 | + "HISTORY.md", | ||
| 64 | + "index.js" | ||
| 65 | + ], | ||
| 66 | + "homepage": "https://github.com/jshttp/accepts#readme", | ||
| 67 | + "keywords": [ | ||
| 68 | + "content", | ||
| 69 | + "negotiation", | ||
| 70 | + "accept", | ||
| 71 | + "accepts" | ||
| 72 | + ], | ||
| 73 | + "license": "MIT", | ||
| 74 | + "name": "accepts", | ||
| 75 | + "repository": { | ||
| 76 | + "type": "git", | ||
| 77 | + "url": "git+https://github.com/jshttp/accepts.git" | ||
| 78 | + }, | ||
| 79 | + "scripts": { | ||
| 80 | + "lint": "eslint --plugin markdown --ext js,md .", | ||
| 81 | + "test": "mocha --reporter spec --check-leaks --bail test/", | ||
| 82 | + "test-cov": "nyc --reporter=html --reporter=text npm test", | ||
| 83 | + "test-travis": "nyc --reporter=text npm test" | ||
| 84 | + }, | ||
| 85 | + "version": "1.3.7" | ||
| 86 | +} |
| 1 | +The MIT License (MIT) | ||
| 2 | + | ||
| 3 | +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) | ||
| 4 | + | ||
| 5 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | +of this software and associated documentation files (the "Software"), to deal | ||
| 7 | +in the Software without restriction, including without limitation the rights | ||
| 8 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | +copies of the Software, and to permit persons to whom the Software is | ||
| 10 | +furnished to do so, subject to the following conditions: | ||
| 11 | + | ||
| 12 | +The above copyright notice and this permission notice shall be included in | ||
| 13 | +all copies or substantial portions of the Software. | ||
| 14 | + | ||
| 15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | +THE SOFTWARE. |
| 1 | +# Array Flatten | ||
| 2 | + | ||
| 3 | +[![NPM version][npm-image]][npm-url] | ||
| 4 | +[![NPM downloads][downloads-image]][downloads-url] | ||
| 5 | +[![Build status][travis-image]][travis-url] | ||
| 6 | +[![Test coverage][coveralls-image]][coveralls-url] | ||
| 7 | + | ||
| 8 | +> Flatten an array of nested arrays into a single flat array. Accepts an optional depth. | ||
| 9 | + | ||
| 10 | +## Installation | ||
| 11 | + | ||
| 12 | +``` | ||
| 13 | +npm install array-flatten --save | ||
| 14 | +``` | ||
| 15 | + | ||
| 16 | +## Usage | ||
| 17 | + | ||
| 18 | +```javascript | ||
| 19 | +var flatten = require('array-flatten') | ||
| 20 | + | ||
| 21 | +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]) | ||
| 22 | +//=> [1, 2, 3, 4, 5, 6, 7, 8, 9] | ||
| 23 | + | ||
| 24 | +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2) | ||
| 25 | +//=> [1, 2, 3, [4, [5], 6], 7, 8, 9] | ||
| 26 | + | ||
| 27 | +(function () { | ||
| 28 | + flatten(arguments) //=> [1, 2, 3] | ||
| 29 | +})(1, [2, 3]) | ||
| 30 | +``` | ||
| 31 | + | ||
| 32 | +## License | ||
| 33 | + | ||
| 34 | +MIT | ||
| 35 | + | ||
| 36 | +[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat | ||
| 37 | +[npm-url]: https://npmjs.org/package/array-flatten | ||
| 38 | +[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat | ||
| 39 | +[downloads-url]: https://npmjs.org/package/array-flatten | ||
| 40 | +[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat | ||
| 41 | +[travis-url]: https://travis-ci.org/blakeembrey/array-flatten | ||
| 42 | +[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat | ||
| 43 | +[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master |
| 1 | +'use strict' | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * Expose `arrayFlatten`. | ||
| 5 | + */ | ||
| 6 | +module.exports = arrayFlatten | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * Recursive flatten function with depth. | ||
| 10 | + * | ||
| 11 | + * @param {Array} array | ||
| 12 | + * @param {Array} result | ||
| 13 | + * @param {Number} depth | ||
| 14 | + * @return {Array} | ||
| 15 | + */ | ||
| 16 | +function flattenWithDepth (array, result, depth) { | ||
| 17 | + for (var i = 0; i < array.length; i++) { | ||
| 18 | + var value = array[i] | ||
| 19 | + | ||
| 20 | + if (depth > 0 && Array.isArray(value)) { | ||
| 21 | + flattenWithDepth(value, result, depth - 1) | ||
| 22 | + } else { | ||
| 23 | + result.push(value) | ||
| 24 | + } | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + return result | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +/** | ||
| 31 | + * Recursive flatten function. Omitting depth is slightly faster. | ||
| 32 | + * | ||
| 33 | + * @param {Array} array | ||
| 34 | + * @param {Array} result | ||
| 35 | + * @return {Array} | ||
| 36 | + */ | ||
| 37 | +function flattenForever (array, result) { | ||
| 38 | + for (var i = 0; i < array.length; i++) { | ||
| 39 | + var value = array[i] | ||
| 40 | + | ||
| 41 | + if (Array.isArray(value)) { | ||
| 42 | + flattenForever(value, result) | ||
| 43 | + } else { | ||
| 44 | + result.push(value) | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + return result | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +/** | ||
| 52 | + * Flatten an array, with the ability to define a depth. | ||
| 53 | + * | ||
| 54 | + * @param {Array} array | ||
| 55 | + * @param {Number} depth | ||
| 56 | + * @return {Array} | ||
| 57 | + */ | ||
| 58 | +function arrayFlatten (array, depth) { | ||
| 59 | + if (depth == null) { | ||
| 60 | + return flattenForever(array, []) | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + return flattenWithDepth(array, [], depth) | ||
| 64 | +} |
| 1 | +{ | ||
| 2 | + "_from": "array-flatten@1.1.1", | ||
| 3 | + "_id": "array-flatten@1.1.1", | ||
| 4 | + "_inBundle": false, | ||
| 5 | + "_integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", | ||
| 6 | + "_location": "/array-flatten", | ||
| 7 | + "_phantomChildren": {}, | ||
| 8 | + "_requested": { | ||
| 9 | + "type": "version", | ||
| 10 | + "registry": true, | ||
| 11 | + "raw": "array-flatten@1.1.1", | ||
| 12 | + "name": "array-flatten", | ||
| 13 | + "escapedName": "array-flatten", | ||
| 14 | + "rawSpec": "1.1.1", | ||
| 15 | + "saveSpec": null, | ||
| 16 | + "fetchSpec": "1.1.1" | ||
| 17 | + }, | ||
| 18 | + "_requiredBy": [ | ||
| 19 | + "/express" | ||
| 20 | + ], | ||
| 21 | + "_resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", | ||
| 22 | + "_shasum": "9a5f699051b1e7073328f2a008968b64ea2955d2", | ||
| 23 | + "_spec": "array-flatten@1.1.1", | ||
| 24 | + "_where": "C:\\Users\\SIMBA\\Desktop\\SpotifyPlaylistExport-master\\node_modules\\express", | ||
| 25 | + "author": { | ||
| 26 | + "name": "Blake Embrey", | ||
| 27 | + "email": "hello@blakeembrey.com", | ||
| 28 | + "url": "http://blakeembrey.me" | ||
| 29 | + }, | ||
| 30 | + "bugs": { | ||
| 31 | + "url": "https://github.com/blakeembrey/array-flatten/issues" | ||
| 32 | + }, | ||
| 33 | + "bundleDependencies": false, | ||
| 34 | + "deprecated": false, | ||
| 35 | + "description": "Flatten an array of nested arrays into a single flat array", | ||
| 36 | + "devDependencies": { | ||
| 37 | + "istanbul": "^0.3.13", | ||
| 38 | + "mocha": "^2.2.4", | ||
| 39 | + "pre-commit": "^1.0.7", | ||
| 40 | + "standard": "^3.7.3" | ||
| 41 | + }, | ||
| 42 | + "files": [ | ||
| 43 | + "array-flatten.js", | ||
| 44 | + "LICENSE" | ||
| 45 | + ], | ||
| 46 | + "homepage": "https://github.com/blakeembrey/array-flatten", | ||
| 47 | + "keywords": [ | ||
| 48 | + "array", | ||
| 49 | + "flatten", | ||
| 50 | + "arguments", | ||
| 51 | + "depth" | ||
| 52 | + ], | ||
| 53 | + "license": "MIT", | ||
| 54 | + "main": "array-flatten.js", | ||
| 55 | + "name": "array-flatten", | ||
| 56 | + "repository": { | ||
| 57 | + "type": "git", | ||
| 58 | + "url": "git://github.com/blakeembrey/array-flatten.git" | ||
| 59 | + }, | ||
| 60 | + "scripts": { | ||
| 61 | + "test": "istanbul cover _mocha -- -R spec" | ||
| 62 | + }, | ||
| 63 | + "version": "1.1.1" | ||
| 64 | +} |
| 1 | +The MIT License (MIT) | ||
| 2 | + | ||
| 3 | +Copyright (c) 2016 Alex Indigo | ||
| 4 | + | ||
| 5 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | +of this software and associated documentation files (the "Software"), to deal | ||
| 7 | +in the Software without restriction, including without limitation the rights | ||
| 8 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | +copies of the Software, and to permit persons to whom the Software is | ||
| 10 | +furnished to do so, subject to the following conditions: | ||
| 11 | + | ||
| 12 | +The above copyright notice and this permission notice shall be included in all | ||
| 13 | +copies or substantial portions of the Software. | ||
| 14 | + | ||
| 15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | +SOFTWARE. |
| 1 | +# asynckit [](https://www.npmjs.com/package/asynckit) | ||
| 2 | + | ||
| 3 | +Minimal async jobs utility library, with streams support. | ||
| 4 | + | ||
| 5 | +[](https://travis-ci.org/alexindigo/asynckit) | ||
| 6 | +[](https://travis-ci.org/alexindigo/asynckit) | ||
| 7 | +[](https://ci.appveyor.com/project/alexindigo/asynckit) | ||
| 8 | + | ||
| 9 | +[](https://coveralls.io/github/alexindigo/asynckit?branch=master) | ||
| 10 | +[](https://david-dm.org/alexindigo/asynckit) | ||
| 11 | +[](https://www.bithound.io/github/alexindigo/asynckit) | ||
| 12 | + | ||
| 13 | +<!-- [](https://www.npmjs.com/package/reamde) --> | ||
| 14 | + | ||
| 15 | +AsyncKit provides harness for `parallel` and `serial` iterators over list of items represented by arrays or objects. | ||
| 16 | +Optionally it accepts abort function (should be synchronously return by iterator for each item), and terminates left over jobs upon an error event. For specific iteration order built-in (`ascending` and `descending`) and custom sort helpers also supported, via `asynckit.serialOrdered` method. | ||
| 17 | + | ||
| 18 | +It ensures async operations to keep behavior more stable and prevent `Maximum call stack size exceeded` errors, from sync iterators. | ||
| 19 | + | ||
| 20 | +| compression | size | | ||
| 21 | +| :----------------- | -------: | | ||
| 22 | +| asynckit.js | 12.34 kB | | ||
| 23 | +| asynckit.min.js | 4.11 kB | | ||
| 24 | +| asynckit.min.js.gz | 1.47 kB | | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +## Install | ||
| 28 | + | ||
| 29 | +```sh | ||
| 30 | +$ npm install --save asynckit | ||
| 31 | +``` | ||
| 32 | + | ||
| 33 | +## Examples | ||
| 34 | + | ||
| 35 | +### Parallel Jobs | ||
| 36 | + | ||
| 37 | +Runs iterator over provided array in parallel. Stores output in the `result` array, | ||
| 38 | +on the matching positions. In unlikely event of an error from one of the jobs, | ||
| 39 | +will terminate rest of the active jobs (if abort function is provided) | ||
| 40 | +and return error along with salvaged data to the main callback function. | ||
| 41 | + | ||
| 42 | +#### Input Array | ||
| 43 | + | ||
| 44 | +```javascript | ||
| 45 | +var parallel = require('asynckit').parallel | ||
| 46 | + , assert = require('assert') | ||
| 47 | + ; | ||
| 48 | + | ||
| 49 | +var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ] | ||
| 50 | + , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ] | ||
| 51 | + , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ] | ||
| 52 | + , target = [] | ||
| 53 | + ; | ||
| 54 | + | ||
| 55 | +parallel(source, asyncJob, function(err, result) | ||
| 56 | +{ | ||
| 57 | + assert.deepEqual(result, expectedResult); | ||
| 58 | + assert.deepEqual(target, expectedTarget); | ||
| 59 | +}); | ||
| 60 | + | ||
| 61 | +// async job accepts one element from the array | ||
| 62 | +// and a callback function | ||
| 63 | +function asyncJob(item, cb) | ||
| 64 | +{ | ||
| 65 | + // different delays (in ms) per item | ||
| 66 | + var delay = item * 25; | ||
| 67 | + | ||
| 68 | + // pretend different jobs take different time to finish | ||
| 69 | + // and not in consequential order | ||
| 70 | + var timeoutId = setTimeout(function() { | ||
| 71 | + target.push(item); | ||
| 72 | + cb(null, item * 2); | ||
| 73 | + }, delay); | ||
| 74 | + | ||
| 75 | + // allow to cancel "leftover" jobs upon error | ||
| 76 | + // return function, invoking of which will abort this job | ||
| 77 | + return clearTimeout.bind(null, timeoutId); | ||
| 78 | +} | ||
| 79 | +``` | ||
| 80 | + | ||
| 81 | +More examples could be found in [test/test-parallel-array.js](test/test-parallel-array.js). | ||
| 82 | + | ||
| 83 | +#### Input Object | ||
| 84 | + | ||
| 85 | +Also it supports named jobs, listed via object. | ||
| 86 | + | ||
| 87 | +```javascript | ||
| 88 | +var parallel = require('asynckit/parallel') | ||
| 89 | + , assert = require('assert') | ||
| 90 | + ; | ||
| 91 | + | ||
| 92 | +var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 } | ||
| 93 | + , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 } | ||
| 94 | + , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ] | ||
| 95 | + , expectedKeys = [ 'first', 'one', 'two', 'four', 'eight', 'sixteen', 'thirtyTwo', 'sixtyFour' ] | ||
| 96 | + , target = [] | ||
| 97 | + , keys = [] | ||
| 98 | + ; | ||
| 99 | + | ||
| 100 | +parallel(source, asyncJob, function(err, result) | ||
| 101 | +{ | ||
| 102 | + assert.deepEqual(result, expectedResult); | ||
| 103 | + assert.deepEqual(target, expectedTarget); | ||
| 104 | + assert.deepEqual(keys, expectedKeys); | ||
| 105 | +}); | ||
| 106 | + | ||
| 107 | +// supports full value, key, callback (shortcut) interface | ||
| 108 | +function asyncJob(item, key, cb) | ||
| 109 | +{ | ||
| 110 | + // different delays (in ms) per item | ||
| 111 | + var delay = item * 25; | ||
| 112 | + | ||
| 113 | + // pretend different jobs take different time to finish | ||
| 114 | + // and not in consequential order | ||
| 115 | + var timeoutId = setTimeout(function() { | ||
| 116 | + keys.push(key); | ||
| 117 | + target.push(item); | ||
| 118 | + cb(null, item * 2); | ||
| 119 | + }, delay); | ||
| 120 | + | ||
| 121 | + // allow to cancel "leftover" jobs upon error | ||
| 122 | + // return function, invoking of which will abort this job | ||
| 123 | + return clearTimeout.bind(null, timeoutId); | ||
| 124 | +} | ||
| 125 | +``` | ||
| 126 | + | ||
| 127 | +More examples could be found in [test/test-parallel-object.js](test/test-parallel-object.js). | ||
| 128 | + | ||
| 129 | +### Serial Jobs | ||
| 130 | + | ||
| 131 | +Runs iterator over provided array sequentially. Stores output in the `result` array, | ||
| 132 | +on the matching positions. In unlikely event of an error from one of the jobs, | ||
| 133 | +will not proceed to the rest of the items in the list | ||
| 134 | +and return error along with salvaged data to the main callback function. | ||
| 135 | + | ||
| 136 | +#### Input Array | ||
| 137 | + | ||
| 138 | +```javascript | ||
| 139 | +var serial = require('asynckit/serial') | ||
| 140 | + , assert = require('assert') | ||
| 141 | + ; | ||
| 142 | + | ||
| 143 | +var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ] | ||
| 144 | + , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ] | ||
| 145 | + , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ] | ||
| 146 | + , target = [] | ||
| 147 | + ; | ||
| 148 | + | ||
| 149 | +serial(source, asyncJob, function(err, result) | ||
| 150 | +{ | ||
| 151 | + assert.deepEqual(result, expectedResult); | ||
| 152 | + assert.deepEqual(target, expectedTarget); | ||
| 153 | +}); | ||
| 154 | + | ||
| 155 | +// extended interface (item, key, callback) | ||
| 156 | +// also supported for arrays | ||
| 157 | +function asyncJob(item, key, cb) | ||
| 158 | +{ | ||
| 159 | + target.push(key); | ||
| 160 | + | ||
| 161 | + // it will be automatically made async | ||
| 162 | + // even it iterator "returns" in the same event loop | ||
| 163 | + cb(null, item * 2); | ||
| 164 | +} | ||
| 165 | +``` | ||
| 166 | + | ||
| 167 | +More examples could be found in [test/test-serial-array.js](test/test-serial-array.js). | ||
| 168 | + | ||
| 169 | +#### Input Object | ||
| 170 | + | ||
| 171 | +Also it supports named jobs, listed via object. | ||
| 172 | + | ||
| 173 | +```javascript | ||
| 174 | +var serial = require('asynckit').serial | ||
| 175 | + , assert = require('assert') | ||
| 176 | + ; | ||
| 177 | + | ||
| 178 | +var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ] | ||
| 179 | + , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ] | ||
| 180 | + , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ] | ||
| 181 | + , target = [] | ||
| 182 | + ; | ||
| 183 | + | ||
| 184 | +var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 } | ||
| 185 | + , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 } | ||
| 186 | + , expectedTarget = [ 1, 1, 4, 16, 64, 32, 8, 2 ] | ||
| 187 | + , target = [] | ||
| 188 | + ; | ||
| 189 | + | ||
| 190 | + | ||
| 191 | +serial(source, asyncJob, function(err, result) | ||
| 192 | +{ | ||
| 193 | + assert.deepEqual(result, expectedResult); | ||
| 194 | + assert.deepEqual(target, expectedTarget); | ||
| 195 | +}); | ||
| 196 | + | ||
| 197 | +// shortcut interface (item, callback) | ||
| 198 | +// works for object as well as for the arrays | ||
| 199 | +function asyncJob(item, cb) | ||
| 200 | +{ | ||
| 201 | + target.push(item); | ||
| 202 | + | ||
| 203 | + // it will be automatically made async | ||
| 204 | + // even it iterator "returns" in the same event loop | ||
| 205 | + cb(null, item * 2); | ||
| 206 | +} | ||
| 207 | +``` | ||
| 208 | + | ||
| 209 | +More examples could be found in [test/test-serial-object.js](test/test-serial-object.js). | ||
| 210 | + | ||
| 211 | +_Note: Since _object_ is an _unordered_ collection of properties, | ||
| 212 | +it may produce unexpected results with sequential iterations. | ||
| 213 | +Whenever order of the jobs' execution is important please use `serialOrdered` method._ | ||
| 214 | + | ||
| 215 | +### Ordered Serial Iterations | ||
| 216 | + | ||
| 217 | +TBD | ||
| 218 | + | ||
| 219 | +For example [compare-property](compare-property) package. | ||
| 220 | + | ||
| 221 | +### Streaming interface | ||
| 222 | + | ||
| 223 | +TBD | ||
| 224 | + | ||
| 225 | +## Want to Know More? | ||
| 226 | + | ||
| 227 | +More examples can be found in [test folder](test/). | ||
| 228 | + | ||
| 229 | +Or open an [issue](https://github.com/alexindigo/asynckit/issues) with questions and/or suggestions. | ||
| 230 | + | ||
| 231 | +## License | ||
| 232 | + | ||
| 233 | +AsyncKit is licensed under the MIT license. |
| 1 | +/* eslint no-console: "off" */ | ||
| 2 | + | ||
| 3 | +var asynckit = require('./') | ||
| 4 | + , async = require('async') | ||
| 5 | + , assert = require('assert') | ||
| 6 | + , expected = 0 | ||
| 7 | + ; | ||
| 8 | + | ||
| 9 | +var Benchmark = require('benchmark'); | ||
| 10 | +var suite = new Benchmark.Suite; | ||
| 11 | + | ||
| 12 | +var source = []; | ||
| 13 | +for (var z = 1; z < 100; z++) | ||
| 14 | +{ | ||
| 15 | + source.push(z); | ||
| 16 | + expected += z; | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +suite | ||
| 20 | +// add tests | ||
| 21 | + | ||
| 22 | +.add('async.map', function(deferred) | ||
| 23 | +{ | ||
| 24 | + var total = 0; | ||
| 25 | + | ||
| 26 | + async.map(source, | ||
| 27 | + function(i, cb) | ||
| 28 | + { | ||
| 29 | + setImmediate(function() | ||
| 30 | + { | ||
| 31 | + total += i; | ||
| 32 | + cb(null, total); | ||
| 33 | + }); | ||
| 34 | + }, | ||
| 35 | + function(err, result) | ||
| 36 | + { | ||
| 37 | + assert.ifError(err); | ||
| 38 | + assert.equal(result[result.length - 1], expected); | ||
| 39 | + deferred.resolve(); | ||
| 40 | + }); | ||
| 41 | +}, {'defer': true}) | ||
| 42 | + | ||
| 43 | + | ||
| 44 | +.add('asynckit.parallel', function(deferred) | ||
| 45 | +{ | ||
| 46 | + var total = 0; | ||
| 47 | + | ||
| 48 | + asynckit.parallel(source, | ||
| 49 | + function(i, cb) | ||
| 50 | + { | ||
| 51 | + setImmediate(function() | ||
| 52 | + { | ||
| 53 | + total += i; | ||
| 54 | + cb(null, total); | ||
| 55 | + }); | ||
| 56 | + }, | ||
| 57 | + function(err, result) | ||
| 58 | + { | ||
| 59 | + assert.ifError(err); | ||
| 60 | + assert.equal(result[result.length - 1], expected); | ||
| 61 | + deferred.resolve(); | ||
| 62 | + }); | ||
| 63 | +}, {'defer': true}) | ||
| 64 | + | ||
| 65 | + | ||
| 66 | +// add listeners | ||
| 67 | +.on('cycle', function(ev) | ||
| 68 | +{ | ||
| 69 | + console.log(String(ev.target)); | ||
| 70 | +}) | ||
| 71 | +.on('complete', function() | ||
| 72 | +{ | ||
| 73 | + console.log('Fastest is ' + this.filter('fastest').map('name')); | ||
| 74 | +}) | ||
| 75 | +// run async | ||
| 76 | +.run({ 'async': true }); |
| 1 | +// API | ||
| 2 | +module.exports = abort; | ||
| 3 | + | ||
| 4 | +/** | ||
| 5 | + * Aborts leftover active jobs | ||
| 6 | + * | ||
| 7 | + * @param {object} state - current state object | ||
| 8 | + */ | ||
| 9 | +function abort(state) | ||
| 10 | +{ | ||
| 11 | + Object.keys(state.jobs).forEach(clean.bind(state)); | ||
| 12 | + | ||
| 13 | + // reset leftover jobs | ||
| 14 | + state.jobs = {}; | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * Cleans up leftover job by invoking abort function for the provided job id | ||
| 19 | + * | ||
| 20 | + * @this state | ||
| 21 | + * @param {string|number} key - job id to abort | ||
| 22 | + */ | ||
| 23 | +function clean(key) | ||
| 24 | +{ | ||
| 25 | + if (typeof this.jobs[key] == 'function') | ||
| 26 | + { | ||
| 27 | + this.jobs[key](); | ||
| 28 | + } | ||
| 29 | +} |
| 1 | +var defer = require('./defer.js'); | ||
| 2 | + | ||
| 3 | +// API | ||
| 4 | +module.exports = async; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * Runs provided callback asynchronously | ||
| 8 | + * even if callback itself is not | ||
| 9 | + * | ||
| 10 | + * @param {function} callback - callback to invoke | ||
| 11 | + * @returns {function} - augmented callback | ||
| 12 | + */ | ||
| 13 | +function async(callback) | ||
| 14 | +{ | ||
| 15 | + var isAsync = false; | ||
| 16 | + | ||
| 17 | + // check if async happened | ||
| 18 | + defer(function() { isAsync = true; }); | ||
| 19 | + | ||
| 20 | + return function async_callback(err, result) | ||
| 21 | + { | ||
| 22 | + if (isAsync) | ||
| 23 | + { | ||
| 24 | + callback(err, result); | ||
| 25 | + } | ||
| 26 | + else | ||
| 27 | + { | ||
| 28 | + defer(function nextTick_callback() | ||
| 29 | + { | ||
| 30 | + callback(err, result); | ||
| 31 | + }); | ||
| 32 | + } | ||
| 33 | + }; | ||
| 34 | +} |
| 1 | +module.exports = defer; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * Runs provided function on next iteration of the event loop | ||
| 5 | + * | ||
| 6 | + * @param {function} fn - function to run | ||
| 7 | + */ | ||
| 8 | +function defer(fn) | ||
| 9 | +{ | ||
| 10 | + var nextTick = typeof setImmediate == 'function' | ||
| 11 | + ? setImmediate | ||
| 12 | + : ( | ||
| 13 | + typeof process == 'object' && typeof process.nextTick == 'function' | ||
| 14 | + ? process.nextTick | ||
| 15 | + : null | ||
| 16 | + ); | ||
| 17 | + | ||
| 18 | + if (nextTick) | ||
| 19 | + { | ||
| 20 | + nextTick(fn); | ||
| 21 | + } | ||
| 22 | + else | ||
| 23 | + { | ||
| 24 | + setTimeout(fn, 0); | ||
| 25 | + } | ||
| 26 | +} |
| 1 | +var async = require('./async.js') | ||
| 2 | + , abort = require('./abort.js') | ||
| 3 | + ; | ||
| 4 | + | ||
| 5 | +// API | ||
| 6 | +module.exports = iterate; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * Iterates over each job object | ||
| 10 | + * | ||
| 11 | + * @param {array|object} list - array or object (named list) to iterate over | ||
| 12 | + * @param {function} iterator - iterator to run | ||
| 13 | + * @param {object} state - current job status | ||
| 14 | + * @param {function} callback - invoked when all elements processed | ||
| 15 | + */ | ||
| 16 | +function iterate(list, iterator, state, callback) | ||
| 17 | +{ | ||
| 18 | + // store current index | ||
| 19 | + var key = state['keyedList'] ? state['keyedList'][state.index] : state.index; | ||
| 20 | + | ||
| 21 | + state.jobs[key] = runJob(iterator, key, list[key], function(error, output) | ||
| 22 | + { | ||
| 23 | + // don't repeat yourself | ||
| 24 | + // skip secondary callbacks | ||
| 25 | + if (!(key in state.jobs)) | ||
| 26 | + { | ||
| 27 | + return; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + // clean up jobs | ||
| 31 | + delete state.jobs[key]; | ||
| 32 | + | ||
| 33 | + if (error) | ||
| 34 | + { | ||
| 35 | + // don't process rest of the results | ||
| 36 | + // stop still active jobs | ||
| 37 | + // and reset the list | ||
| 38 | + abort(state); | ||
| 39 | + } | ||
| 40 | + else | ||
| 41 | + { | ||
| 42 | + state.results[key] = output; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + // return salvaged results | ||
| 46 | + callback(error, state.results); | ||
| 47 | + }); | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +/** | ||
| 51 | + * Runs iterator over provided job element | ||
| 52 | + * | ||
| 53 | + * @param {function} iterator - iterator to invoke | ||
| 54 | + * @param {string|number} key - key/index of the element in the list of jobs | ||
| 55 | + * @param {mixed} item - job description | ||
| 56 | + * @param {function} callback - invoked after iterator is done with the job | ||
| 57 | + * @returns {function|mixed} - job abort function or something else | ||
| 58 | + */ | ||
| 59 | +function runJob(iterator, key, item, callback) | ||
| 60 | +{ | ||
| 61 | + var aborter; | ||
| 62 | + | ||
| 63 | + // allow shortcut if iterator expects only two arguments | ||
| 64 | + if (iterator.length == 2) | ||
| 65 | + { | ||
| 66 | + aborter = iterator(item, async(callback)); | ||
| 67 | + } | ||
| 68 | + // otherwise go with full three arguments | ||
| 69 | + else | ||
| 70 | + { | ||
| 71 | + aborter = iterator(item, key, async(callback)); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + return aborter; | ||
| 75 | +} |
| 1 | +var streamify = require('./streamify.js') | ||
| 2 | + , defer = require('./defer.js') | ||
| 3 | + ; | ||
| 4 | + | ||
| 5 | +// API | ||
| 6 | +module.exports = ReadableAsyncKit; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * Base constructor for all streams | ||
| 10 | + * used to hold properties/methods | ||
| 11 | + */ | ||
| 12 | +function ReadableAsyncKit() | ||
| 13 | +{ | ||
| 14 | + ReadableAsyncKit.super_.apply(this, arguments); | ||
| 15 | + | ||
| 16 | + // list of active jobs | ||
| 17 | + this.jobs = {}; | ||
| 18 | + | ||
| 19 | + // add stream methods | ||
| 20 | + this.destroy = destroy; | ||
| 21 | + this._start = _start; | ||
| 22 | + this._read = _read; | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * Destroys readable stream, | ||
| 27 | + * by aborting outstanding jobs | ||
| 28 | + * | ||
| 29 | + * @returns {void} | ||
| 30 | + */ | ||
| 31 | +function destroy() | ||
| 32 | +{ | ||
| 33 | + if (this.destroyed) | ||
| 34 | + { | ||
| 35 | + return; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + this.destroyed = true; | ||
| 39 | + | ||
| 40 | + if (typeof this.terminator == 'function') | ||
| 41 | + { | ||
| 42 | + this.terminator(); | ||
| 43 | + } | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +/** | ||
| 47 | + * Starts provided jobs in async manner | ||
| 48 | + * | ||
| 49 | + * @private | ||
| 50 | + */ | ||
| 51 | +function _start() | ||
| 52 | +{ | ||
| 53 | + // first argument – runner function | ||
| 54 | + var runner = arguments[0] | ||
| 55 | + // take away first argument | ||
| 56 | + , args = Array.prototype.slice.call(arguments, 1) | ||
| 57 | + // second argument - input data | ||
| 58 | + , input = args[0] | ||
| 59 | + // last argument - result callback | ||
| 60 | + , endCb = streamify.callback.call(this, args[args.length - 1]) | ||
| 61 | + ; | ||
| 62 | + | ||
| 63 | + args[args.length - 1] = endCb; | ||
| 64 | + // third argument - iterator | ||
| 65 | + args[1] = streamify.iterator.call(this, args[1]); | ||
| 66 | + | ||
| 67 | + // allow time for proper setup | ||
| 68 | + defer(function() | ||
| 69 | + { | ||
| 70 | + if (!this.destroyed) | ||
| 71 | + { | ||
| 72 | + this.terminator = runner.apply(null, args); | ||
| 73 | + } | ||
| 74 | + else | ||
| 75 | + { | ||
| 76 | + endCb(null, Array.isArray(input) ? [] : {}); | ||
| 77 | + } | ||
| 78 | + }.bind(this)); | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | + | ||
| 82 | +/** | ||
| 83 | + * Implement _read to comply with Readable streams | ||
| 84 | + * Doesn't really make sense for flowing object mode | ||
| 85 | + * | ||
| 86 | + * @private | ||
| 87 | + */ | ||
| 88 | +function _read() | ||
| 89 | +{ | ||
| 90 | + | ||
| 91 | +} |
| 1 | +var parallel = require('../parallel.js'); | ||
| 2 | + | ||
| 3 | +// API | ||
| 4 | +module.exports = ReadableParallel; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * Streaming wrapper to `asynckit.parallel` | ||
| 8 | + * | ||
| 9 | + * @param {array|object} list - array or object (named list) to iterate over | ||
| 10 | + * @param {function} iterator - iterator to run | ||
| 11 | + * @param {function} callback - invoked when all elements processed | ||
| 12 | + * @returns {stream.Readable#} | ||
| 13 | + */ | ||
| 14 | +function ReadableParallel(list, iterator, callback) | ||
| 15 | +{ | ||
| 16 | + if (!(this instanceof ReadableParallel)) | ||
| 17 | + { | ||
| 18 | + return new ReadableParallel(list, iterator, callback); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + // turn on object mode | ||
| 22 | + ReadableParallel.super_.call(this, {objectMode: true}); | ||
| 23 | + | ||
| 24 | + this._start(parallel, list, iterator, callback); | ||
| 25 | +} |
| 1 | +var serial = require('../serial.js'); | ||
| 2 | + | ||
| 3 | +// API | ||
| 4 | +module.exports = ReadableSerial; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * Streaming wrapper to `asynckit.serial` | ||
| 8 | + * | ||
| 9 | + * @param {array|object} list - array or object (named list) to iterate over | ||
| 10 | + * @param {function} iterator - iterator to run | ||
| 11 | + * @param {function} callback - invoked when all elements processed | ||
| 12 | + * @returns {stream.Readable#} | ||
| 13 | + */ | ||
| 14 | +function ReadableSerial(list, iterator, callback) | ||
| 15 | +{ | ||
| 16 | + if (!(this instanceof ReadableSerial)) | ||
| 17 | + { | ||
| 18 | + return new ReadableSerial(list, iterator, callback); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + // turn on object mode | ||
| 22 | + ReadableSerial.super_.call(this, {objectMode: true}); | ||
| 23 | + | ||
| 24 | + this._start(serial, list, iterator, callback); | ||
| 25 | +} |
| 1 | +var serialOrdered = require('../serialOrdered.js'); | ||
| 2 | + | ||
| 3 | +// API | ||
| 4 | +module.exports = ReadableSerialOrdered; | ||
| 5 | +// expose sort helpers | ||
| 6 | +module.exports.ascending = serialOrdered.ascending; | ||
| 7 | +module.exports.descending = serialOrdered.descending; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * Streaming wrapper to `asynckit.serialOrdered` | ||
| 11 | + * | ||
| 12 | + * @param {array|object} list - array or object (named list) to iterate over | ||
| 13 | + * @param {function} iterator - iterator to run | ||
| 14 | + * @param {function} sortMethod - custom sort function | ||
| 15 | + * @param {function} callback - invoked when all elements processed | ||
| 16 | + * @returns {stream.Readable#} | ||
| 17 | + */ | ||
| 18 | +function ReadableSerialOrdered(list, iterator, sortMethod, callback) | ||
| 19 | +{ | ||
| 20 | + if (!(this instanceof ReadableSerialOrdered)) | ||
| 21 | + { | ||
| 22 | + return new ReadableSerialOrdered(list, iterator, sortMethod, callback); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + // turn on object mode | ||
| 26 | + ReadableSerialOrdered.super_.call(this, {objectMode: true}); | ||
| 27 | + | ||
| 28 | + this._start(serialOrdered, list, iterator, sortMethod, callback); | ||
| 29 | +} |
| 1 | +// API | ||
| 2 | +module.exports = state; | ||
| 3 | + | ||
| 4 | +/** | ||
| 5 | + * Creates initial state object | ||
| 6 | + * for iteration over list | ||
| 7 | + * | ||
| 8 | + * @param {array|object} list - list to iterate over | ||
| 9 | + * @param {function|null} sortMethod - function to use for keys sort, | ||
| 10 | + * or `null` to keep them as is | ||
| 11 | + * @returns {object} - initial state object | ||
| 12 | + */ | ||
| 13 | +function state(list, sortMethod) | ||
| 14 | +{ | ||
| 15 | + var isNamedList = !Array.isArray(list) | ||
| 16 | + , initState = | ||
| 17 | + { | ||
| 18 | + index : 0, | ||
| 19 | + keyedList: isNamedList || sortMethod ? Object.keys(list) : null, | ||
| 20 | + jobs : {}, | ||
| 21 | + results : isNamedList ? {} : [], | ||
| 22 | + size : isNamedList ? Object.keys(list).length : list.length | ||
| 23 | + } | ||
| 24 | + ; | ||
| 25 | + | ||
| 26 | + if (sortMethod) | ||
| 27 | + { | ||
| 28 | + // sort array keys based on it's values | ||
| 29 | + // sort object's keys just on own merit | ||
| 30 | + initState.keyedList.sort(isNamedList ? sortMethod : function(a, b) | ||
| 31 | + { | ||
| 32 | + return sortMethod(list[a], list[b]); | ||
| 33 | + }); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + return initState; | ||
| 37 | +} |
| 1 | +var async = require('./async.js'); | ||
| 2 | + | ||
| 3 | +// API | ||
| 4 | +module.exports = { | ||
| 5 | + iterator: wrapIterator, | ||
| 6 | + callback: wrapCallback | ||
| 7 | +}; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * Wraps iterators with long signature | ||
| 11 | + * | ||
| 12 | + * @this ReadableAsyncKit# | ||
| 13 | + * @param {function} iterator - function to wrap | ||
| 14 | + * @returns {function} - wrapped function | ||
| 15 | + */ | ||
| 16 | +function wrapIterator(iterator) | ||
| 17 | +{ | ||
| 18 | + var stream = this; | ||
| 19 | + | ||
| 20 | + return function(item, key, cb) | ||
| 21 | + { | ||
| 22 | + var aborter | ||
| 23 | + , wrappedCb = async(wrapIteratorCallback.call(stream, cb, key)) | ||
| 24 | + ; | ||
| 25 | + | ||
| 26 | + stream.jobs[key] = wrappedCb; | ||
| 27 | + | ||
| 28 | + // it's either shortcut (item, cb) | ||
| 29 | + if (iterator.length == 2) | ||
| 30 | + { | ||
| 31 | + aborter = iterator(item, wrappedCb); | ||
| 32 | + } | ||
| 33 | + // or long format (item, key, cb) | ||
| 34 | + else | ||
| 35 | + { | ||
| 36 | + aborter = iterator(item, key, wrappedCb); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + return aborter; | ||
| 40 | + }; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +/** | ||
| 44 | + * Wraps provided callback function | ||
| 45 | + * allowing to execute snitch function before | ||
| 46 | + * real callback | ||
| 47 | + * | ||
| 48 | + * @this ReadableAsyncKit# | ||
| 49 | + * @param {function} callback - function to wrap | ||
| 50 | + * @returns {function} - wrapped function | ||
| 51 | + */ | ||
| 52 | +function wrapCallback(callback) | ||
| 53 | +{ | ||
| 54 | + var stream = this; | ||
| 55 | + | ||
| 56 | + var wrapped = function(error, result) | ||
| 57 | + { | ||
| 58 | + return finisher.call(stream, error, result, callback); | ||
| 59 | + }; | ||
| 60 | + | ||
| 61 | + return wrapped; | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +/** | ||
| 65 | + * Wraps provided iterator callback function | ||
| 66 | + * makes sure snitch only called once, | ||
| 67 | + * but passes secondary calls to the original callback | ||
| 68 | + * | ||
| 69 | + * @this ReadableAsyncKit# | ||
| 70 | + * @param {function} callback - callback to wrap | ||
| 71 | + * @param {number|string} key - iteration key | ||
| 72 | + * @returns {function} wrapped callback | ||
| 73 | + */ | ||
| 74 | +function wrapIteratorCallback(callback, key) | ||
| 75 | +{ | ||
| 76 | + var stream = this; | ||
| 77 | + | ||
| 78 | + return function(error, output) | ||
| 79 | + { | ||
| 80 | + // don't repeat yourself | ||
| 81 | + if (!(key in stream.jobs)) | ||
| 82 | + { | ||
| 83 | + callback(error, output); | ||
| 84 | + return; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + // clean up jobs | ||
| 88 | + delete stream.jobs[key]; | ||
| 89 | + | ||
| 90 | + return streamer.call(stream, error, {key: key, value: output}, callback); | ||
| 91 | + }; | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +/** | ||
| 95 | + * Stream wrapper for iterator callback | ||
| 96 | + * | ||
| 97 | + * @this ReadableAsyncKit# | ||
| 98 | + * @param {mixed} error - error response | ||
| 99 | + * @param {mixed} output - iterator output | ||
| 100 | + * @param {function} callback - callback that expects iterator results | ||
| 101 | + */ | ||
| 102 | +function streamer(error, output, callback) | ||
| 103 | +{ | ||
| 104 | + if (error && !this.error) | ||
| 105 | + { | ||
| 106 | + this.error = error; | ||
| 107 | + this.pause(); | ||
| 108 | + this.emit('error', error); | ||
| 109 | + // send back value only, as expected | ||
| 110 | + callback(error, output && output.value); | ||
| 111 | + return; | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + // stream stuff | ||
| 115 | + this.push(output); | ||
| 116 | + | ||
| 117 | + // back to original track | ||
| 118 | + // send back value only, as expected | ||
| 119 | + callback(error, output && output.value); | ||
| 120 | +} | ||
| 121 | + | ||
| 122 | +/** | ||
| 123 | + * Stream wrapper for finishing callback | ||
| 124 | + * | ||
| 125 | + * @this ReadableAsyncKit# | ||
| 126 | + * @param {mixed} error - error response | ||
| 127 | + * @param {mixed} output - iterator output | ||
| 128 | + * @param {function} callback - callback that expects final results | ||
| 129 | + */ | ||
| 130 | +function finisher(error, output, callback) | ||
| 131 | +{ | ||
| 132 | + // signal end of the stream | ||
| 133 | + // only for successfully finished streams | ||
| 134 | + if (!error) | ||
| 135 | + { | ||
| 136 | + this.push(null); | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + // back to original track | ||
| 140 | + callback(error, output); | ||
| 141 | +} |
| 1 | +var abort = require('./abort.js') | ||
| 2 | + , async = require('./async.js') | ||
| 3 | + ; | ||
| 4 | + | ||
| 5 | +// API | ||
| 6 | +module.exports = terminator; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * Terminates jobs in the attached state context | ||
| 10 | + * | ||
| 11 | + * @this AsyncKitState# | ||
| 12 | + * @param {function} callback - final callback to invoke after termination | ||
| 13 | + */ | ||
| 14 | +function terminator(callback) | ||
| 15 | +{ | ||
| 16 | + if (!Object.keys(this.jobs).length) | ||
| 17 | + { | ||
| 18 | + return; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + // fast forward iteration index | ||
| 22 | + this.index = this.size; | ||
| 23 | + | ||
| 24 | + // abort jobs | ||
| 25 | + abort(this); | ||
| 26 | + | ||
| 27 | + // send back results we have so far | ||
| 28 | + async(callback)(null, this.results); | ||
| 29 | +} |
| 1 | +{ | ||
| 2 | + "_from": "asynckit@^0.4.0", | ||
| 3 | + "_id": "asynckit@0.4.0", | ||
| 4 | + "_inBundle": false, | ||
| 5 | + "_integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", | ||
| 6 | + "_location": "/asynckit", | ||
| 7 | + "_phantomChildren": {}, | ||
| 8 | + "_requested": { | ||
| 9 | + "type": "range", | ||
| 10 | + "registry": true, | ||
| 11 | + "raw": "asynckit@^0.4.0", | ||
| 12 | + "name": "asynckit", | ||
| 13 | + "escapedName": "asynckit", | ||
| 14 | + "rawSpec": "^0.4.0", | ||
| 15 | + "saveSpec": null, | ||
| 16 | + "fetchSpec": "^0.4.0" | ||
| 17 | + }, | ||
| 18 | + "_requiredBy": [ | ||
| 19 | + "/form-data" | ||
| 20 | + ], | ||
| 21 | + "_resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", | ||
| 22 | + "_shasum": "c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79", | ||
| 23 | + "_spec": "asynckit@^0.4.0", | ||
| 24 | + "_where": "C:\\Users\\SIMBA\\Desktop\\SpotifyPlaylistExport-master\\node_modules\\form-data", | ||
| 25 | + "author": { | ||
| 26 | + "name": "Alex Indigo", | ||
| 27 | + "email": "iam@alexindigo.com" | ||
| 28 | + }, | ||
| 29 | + "bugs": { | ||
| 30 | + "url": "https://github.com/alexindigo/asynckit/issues" | ||
| 31 | + }, | ||
| 32 | + "bundleDependencies": false, | ||
| 33 | + "dependencies": {}, | ||
| 34 | + "deprecated": false, | ||
| 35 | + "description": "Minimal async jobs utility library, with streams support", | ||
| 36 | + "devDependencies": { | ||
| 37 | + "browserify": "^13.0.0", | ||
| 38 | + "browserify-istanbul": "^2.0.0", | ||
| 39 | + "coveralls": "^2.11.9", | ||
| 40 | + "eslint": "^2.9.0", | ||
| 41 | + "istanbul": "^0.4.3", | ||
| 42 | + "obake": "^0.1.2", | ||
| 43 | + "phantomjs-prebuilt": "^2.1.7", | ||
| 44 | + "pre-commit": "^1.1.3", | ||
| 45 | + "reamde": "^1.1.0", | ||
| 46 | + "rimraf": "^2.5.2", | ||
| 47 | + "size-table": "^0.2.0", | ||
| 48 | + "tap-spec": "^4.1.1", | ||
| 49 | + "tape": "^4.5.1" | ||
| 50 | + }, | ||
| 51 | + "homepage": "https://github.com/alexindigo/asynckit#readme", | ||
| 52 | + "keywords": [ | ||
| 53 | + "async", | ||
| 54 | + "jobs", | ||
| 55 | + "parallel", | ||
| 56 | + "serial", | ||
| 57 | + "iterator", | ||
| 58 | + "array", | ||
| 59 | + "object", | ||
| 60 | + "stream", | ||
| 61 | + "destroy", | ||
| 62 | + "terminate", | ||
| 63 | + "abort" | ||
| 64 | + ], | ||
| 65 | + "license": "MIT", | ||
| 66 | + "main": "index.js", | ||
| 67 | + "name": "asynckit", | ||
| 68 | + "pre-commit": [ | ||
| 69 | + "clean", | ||
| 70 | + "lint", | ||
| 71 | + "test", | ||
| 72 | + "browser", | ||
| 73 | + "report", | ||
| 74 | + "size" | ||
| 75 | + ], | ||
| 76 | + "repository": { | ||
| 77 | + "type": "git", | ||
| 78 | + "url": "git+https://github.com/alexindigo/asynckit.git" | ||
| 79 | + }, | ||
| 80 | + "scripts": { | ||
| 81 | + "browser": "browserify -t browserify-istanbul test/lib/browserify_adjustment.js test/test-*.js | obake --coverage | tap-spec", | ||
| 82 | + "clean": "rimraf coverage", | ||
| 83 | + "debug": "tape test/test-*.js", | ||
| 84 | + "lint": "eslint *.js lib/*.js test/*.js", | ||
| 85 | + "report": "istanbul report", | ||
| 86 | + "size": "browserify index.js | size-table asynckit", | ||
| 87 | + "test": "istanbul cover --reporter=json tape -- 'test/test-*.js' | tap-spec", | ||
| 88 | + "win-test": "tape test/test-*.js" | ||
| 89 | + }, | ||
| 90 | + "version": "0.4.0" | ||
| 91 | +} |
| 1 | +var iterate = require('./lib/iterate.js') | ||
| 2 | + , initState = require('./lib/state.js') | ||
| 3 | + , terminator = require('./lib/terminator.js') | ||
| 4 | + ; | ||
| 5 | + | ||
| 6 | +// Public API | ||
| 7 | +module.exports = parallel; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * Runs iterator over provided array elements in parallel | ||
| 11 | + * | ||
| 12 | + * @param {array|object} list - array or object (named list) to iterate over | ||
| 13 | + * @param {function} iterator - iterator to run | ||
| 14 | + * @param {function} callback - invoked when all elements processed | ||
| 15 | + * @returns {function} - jobs terminator | ||
| 16 | + */ | ||
| 17 | +function parallel(list, iterator, callback) | ||
| 18 | +{ | ||
| 19 | + var state = initState(list); | ||
| 20 | + | ||
| 21 | + while (state.index < (state['keyedList'] || list).length) | ||
| 22 | + { | ||
| 23 | + iterate(list, iterator, state, function(error, result) | ||
| 24 | + { | ||
| 25 | + if (error) | ||
| 26 | + { | ||
| 27 | + callback(error, result); | ||
| 28 | + return; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + // looks like it's the last one | ||
| 32 | + if (Object.keys(state.jobs).length === 0) | ||
| 33 | + { | ||
| 34 | + callback(null, state.results); | ||
| 35 | + return; | ||
| 36 | + } | ||
| 37 | + }); | ||
| 38 | + | ||
| 39 | + state.index++; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + return terminator.bind(state, callback); | ||
| 43 | +} |
| 1 | +var serialOrdered = require('./serialOrdered.js'); | ||
| 2 | + | ||
| 3 | +// Public API | ||
| 4 | +module.exports = serial; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * Runs iterator over provided array elements in series | ||
| 8 | + * | ||
| 9 | + * @param {array|object} list - array or object (named list) to iterate over | ||
| 10 | + * @param {function} iterator - iterator to run | ||
| 11 | + * @param {function} callback - invoked when all elements processed | ||
| 12 | + * @returns {function} - jobs terminator | ||
| 13 | + */ | ||
| 14 | +function serial(list, iterator, callback) | ||
| 15 | +{ | ||
| 16 | + return serialOrdered(list, iterator, null, callback); | ||
| 17 | +} |
| 1 | +var iterate = require('./lib/iterate.js') | ||
| 2 | + , initState = require('./lib/state.js') | ||
| 3 | + , terminator = require('./lib/terminator.js') | ||
| 4 | + ; | ||
| 5 | + | ||
| 6 | +// Public API | ||
| 7 | +module.exports = serialOrdered; | ||
| 8 | +// sorting helpers | ||
| 9 | +module.exports.ascending = ascending; | ||
| 10 | +module.exports.descending = descending; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * Runs iterator over provided sorted array elements in series | ||
| 14 | + * | ||
| 15 | + * @param {array|object} list - array or object (named list) to iterate over | ||
| 16 | + * @param {function} iterator - iterator to run | ||
| 17 | + * @param {function} sortMethod - custom sort function | ||
| 18 | + * @param {function} callback - invoked when all elements processed | ||
| 19 | + * @returns {function} - jobs terminator | ||
| 20 | + */ | ||
| 21 | +function serialOrdered(list, iterator, sortMethod, callback) | ||
| 22 | +{ | ||
| 23 | + var state = initState(list, sortMethod); | ||
| 24 | + | ||
| 25 | + iterate(list, iterator, state, function iteratorHandler(error, result) | ||
| 26 | + { | ||
| 27 | + if (error) | ||
| 28 | + { | ||
| 29 | + callback(error, result); | ||
| 30 | + return; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + state.index++; | ||
| 34 | + | ||
| 35 | + // are we there yet? | ||
| 36 | + if (state.index < (state['keyedList'] || list).length) | ||
| 37 | + { | ||
| 38 | + iterate(list, iterator, state, iteratorHandler); | ||
| 39 | + return; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + // done here | ||
| 43 | + callback(null, state.results); | ||
| 44 | + }); | ||
| 45 | + | ||
| 46 | + return terminator.bind(state, callback); | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +/* | ||
| 50 | + * -- Sort methods | ||
| 51 | + */ | ||
| 52 | + | ||
| 53 | +/** | ||
| 54 | + * sort helper to sort array elements in ascending order | ||
| 55 | + * | ||
| 56 | + * @param {mixed} a - an item to compare | ||
| 57 | + * @param {mixed} b - an item to compare | ||
| 58 | + * @returns {number} - comparison result | ||
| 59 | + */ | ||
| 60 | +function ascending(a, b) | ||
| 61 | +{ | ||
| 62 | + return a < b ? -1 : a > b ? 1 : 0; | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +/** | ||
| 66 | + * sort helper to sort array elements in descending order | ||
| 67 | + * | ||
| 68 | + * @param {mixed} a - an item to compare | ||
| 69 | + * @param {mixed} b - an item to compare | ||
| 70 | + * @returns {number} - comparison result | ||
| 71 | + */ | ||
| 72 | +function descending(a, b) | ||
| 73 | +{ | ||
| 74 | + return -1 * ascending(a, b); | ||
| 75 | +} |
| 1 | +var inherits = require('util').inherits | ||
| 2 | + , Readable = require('stream').Readable | ||
| 3 | + , ReadableAsyncKit = require('./lib/readable_asynckit.js') | ||
| 4 | + , ReadableParallel = require('./lib/readable_parallel.js') | ||
| 5 | + , ReadableSerial = require('./lib/readable_serial.js') | ||
| 6 | + , ReadableSerialOrdered = require('./lib/readable_serial_ordered.js') | ||
| 7 | + ; | ||
| 8 | + | ||
| 9 | +// API | ||
| 10 | +module.exports = | ||
| 11 | +{ | ||
| 12 | + parallel : ReadableParallel, | ||
| 13 | + serial : ReadableSerial, | ||
| 14 | + serialOrdered : ReadableSerialOrdered, | ||
| 15 | +}; | ||
| 16 | + | ||
| 17 | +inherits(ReadableAsyncKit, Readable); | ||
| 18 | + | ||
| 19 | +inherits(ReadableParallel, ReadableAsyncKit); | ||
| 20 | +inherits(ReadableSerial, ReadableAsyncKit); | ||
| 21 | +inherits(ReadableSerialOrdered, ReadableAsyncKit); |
This diff is collapsed. Click to expand it.
| 1 | +(The MIT License) | ||
| 2 | + | ||
| 3 | +Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> | ||
| 4 | +Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com> | ||
| 5 | + | ||
| 6 | +Permission is hereby granted, free of charge, to any person obtaining | ||
| 7 | +a copy of this software and associated documentation files (the | ||
| 8 | +'Software'), to deal in the Software without restriction, including | ||
| 9 | +without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
| 11 | +permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | +the following conditions: | ||
| 13 | + | ||
| 14 | +The above copyright notice and this permission notice shall be | ||
| 15 | +included in all copies or substantial portions of the Software. | ||
| 16 | + | ||
| 17 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
| 18 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 19 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| 20 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
| 21 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
| 22 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
| 23 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This diff is collapsed. Click to expand it.
| 1 | +/*! | ||
| 2 | + * body-parser | ||
| 3 | + * Copyright(c) 2014-2015 Douglas Christopher Wilson | ||
| 4 | + * MIT Licensed | ||
| 5 | + */ | ||
| 6 | + | ||
| 7 | +'use strict' | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * Module dependencies. | ||
| 11 | + * @private | ||
| 12 | + */ | ||
| 13 | + | ||
| 14 | +var deprecate = require('depd')('body-parser') | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * Cache of loaded parsers. | ||
| 18 | + * @private | ||
| 19 | + */ | ||
| 20 | + | ||
| 21 | +var parsers = Object.create(null) | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * @typedef Parsers | ||
| 25 | + * @type {function} | ||
| 26 | + * @property {function} json | ||
| 27 | + * @property {function} raw | ||
| 28 | + * @property {function} text | ||
| 29 | + * @property {function} urlencoded | ||
| 30 | + */ | ||
| 31 | + | ||
| 32 | +/** | ||
| 33 | + * Module exports. | ||
| 34 | + * @type {Parsers} | ||
| 35 | + */ | ||
| 36 | + | ||
| 37 | +exports = module.exports = deprecate.function(bodyParser, | ||
| 38 | + 'bodyParser: use individual json/urlencoded middlewares') | ||
| 39 | + | ||
| 40 | +/** | ||
| 41 | + * JSON parser. | ||
| 42 | + * @public | ||
| 43 | + */ | ||
| 44 | + | ||
| 45 | +Object.defineProperty(exports, 'json', { | ||
| 46 | + configurable: true, | ||
| 47 | + enumerable: true, | ||
| 48 | + get: createParserGetter('json') | ||
| 49 | +}) | ||
| 50 | + | ||
| 51 | +/** | ||
| 52 | + * Raw parser. | ||
| 53 | + * @public | ||
| 54 | + */ | ||
| 55 | + | ||
| 56 | +Object.defineProperty(exports, 'raw', { | ||
| 57 | + configurable: true, | ||
| 58 | + enumerable: true, | ||
| 59 | + get: createParserGetter('raw') | ||
| 60 | +}) | ||
| 61 | + | ||
| 62 | +/** | ||
| 63 | + * Text parser. | ||
| 64 | + * @public | ||
| 65 | + */ | ||
| 66 | + | ||
| 67 | +Object.defineProperty(exports, 'text', { | ||
| 68 | + configurable: true, | ||
| 69 | + enumerable: true, | ||
| 70 | + get: createParserGetter('text') | ||
| 71 | +}) | ||
| 72 | + | ||
| 73 | +/** | ||
| 74 | + * URL-encoded parser. | ||
| 75 | + * @public | ||
| 76 | + */ | ||
| 77 | + | ||
| 78 | +Object.defineProperty(exports, 'urlencoded', { | ||
| 79 | + configurable: true, | ||
| 80 | + enumerable: true, | ||
| 81 | + get: createParserGetter('urlencoded') | ||
| 82 | +}) | ||
| 83 | + | ||
| 84 | +/** | ||
| 85 | + * Create a middleware to parse json and urlencoded bodies. | ||
| 86 | + * | ||
| 87 | + * @param {object} [options] | ||
| 88 | + * @return {function} | ||
| 89 | + * @deprecated | ||
| 90 | + * @public | ||
| 91 | + */ | ||
| 92 | + | ||
| 93 | +function bodyParser (options) { | ||
| 94 | + var opts = {} | ||
| 95 | + | ||
| 96 | + // exclude type option | ||
| 97 | + if (options) { | ||
| 98 | + for (var prop in options) { | ||
| 99 | + if (prop !== 'type') { | ||
| 100 | + opts[prop] = options[prop] | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + var _urlencoded = exports.urlencoded(opts) | ||
| 106 | + var _json = exports.json(opts) | ||
| 107 | + | ||
| 108 | + return function bodyParser (req, res, next) { | ||
| 109 | + _json(req, res, function (err) { | ||
| 110 | + if (err) return next(err) | ||
| 111 | + _urlencoded(req, res, next) | ||
| 112 | + }) | ||
| 113 | + } | ||
| 114 | +} | ||
| 115 | + | ||
| 116 | +/** | ||
| 117 | + * Create a getter for loading a parser. | ||
| 118 | + * @private | ||
| 119 | + */ | ||
| 120 | + | ||
| 121 | +function createParserGetter (name) { | ||
| 122 | + return function get () { | ||
| 123 | + return loadParser(name) | ||
| 124 | + } | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +/** | ||
| 128 | + * Load a parser module. | ||
| 129 | + * @private | ||
| 130 | + */ | ||
| 131 | + | ||
| 132 | +function loadParser (parserName) { | ||
| 133 | + var parser = parsers[parserName] | ||
| 134 | + | ||
| 135 | + if (parser !== undefined) { | ||
| 136 | + return parser | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + // this uses a switch for static require analysis | ||
| 140 | + switch (parserName) { | ||
| 141 | + case 'json': | ||
| 142 | + parser = require('./lib/types/json') | ||
| 143 | + break | ||
| 144 | + case 'raw': | ||
| 145 | + parser = require('./lib/types/raw') | ||
| 146 | + break | ||
| 147 | + case 'text': | ||
| 148 | + parser = require('./lib/types/text') | ||
| 149 | + break | ||
| 150 | + case 'urlencoded': | ||
| 151 | + parser = require('./lib/types/urlencoded') | ||
| 152 | + break | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + // store to prevent invoking require() | ||
| 156 | + return (parsers[parserName] = parser) | ||
| 157 | +} |
| 1 | +/*! | ||
| 2 | + * body-parser | ||
| 3 | + * Copyright(c) 2014-2015 Douglas Christopher Wilson | ||
| 4 | + * MIT Licensed | ||
| 5 | + */ | ||
| 6 | + | ||
| 7 | +'use strict' | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * Module dependencies. | ||
| 11 | + * @private | ||
| 12 | + */ | ||
| 13 | + | ||
| 14 | +var createError = require('http-errors') | ||
| 15 | +var getBody = require('raw-body') | ||
| 16 | +var iconv = require('iconv-lite') | ||
| 17 | +var onFinished = require('on-finished') | ||
| 18 | +var zlib = require('zlib') | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * Module exports. | ||
| 22 | + */ | ||
| 23 | + | ||
| 24 | +module.exports = read | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * Read a request into a buffer and parse. | ||
| 28 | + * | ||
| 29 | + * @param {object} req | ||
| 30 | + * @param {object} res | ||
| 31 | + * @param {function} next | ||
| 32 | + * @param {function} parse | ||
| 33 | + * @param {function} debug | ||
| 34 | + * @param {object} options | ||
| 35 | + * @private | ||
| 36 | + */ | ||
| 37 | + | ||
| 38 | +function read (req, res, next, parse, debug, options) { | ||
| 39 | + var length | ||
| 40 | + var opts = options | ||
| 41 | + var stream | ||
| 42 | + | ||
| 43 | + // flag as parsed | ||
| 44 | + req._body = true | ||
| 45 | + | ||
| 46 | + // read options | ||
| 47 | + var encoding = opts.encoding !== null | ||
| 48 | + ? opts.encoding | ||
| 49 | + : null | ||
| 50 | + var verify = opts.verify | ||
| 51 | + | ||
| 52 | + try { | ||
| 53 | + // get the content stream | ||
| 54 | + stream = contentstream(req, debug, opts.inflate) | ||
| 55 | + length = stream.length | ||
| 56 | + stream.length = undefined | ||
| 57 | + } catch (err) { | ||
| 58 | + return next(err) | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + // set raw-body options | ||
| 62 | + opts.length = length | ||
| 63 | + opts.encoding = verify | ||
| 64 | + ? null | ||
| 65 | + : encoding | ||
| 66 | + | ||
| 67 | + // assert charset is supported | ||
| 68 | + if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) { | ||
| 69 | + return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { | ||
| 70 | + charset: encoding.toLowerCase(), | ||
| 71 | + type: 'charset.unsupported' | ||
| 72 | + })) | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + // read body | ||
| 76 | + debug('read body') | ||
| 77 | + getBody(stream, opts, function (error, body) { | ||
| 78 | + if (error) { | ||
| 79 | + var _error | ||
| 80 | + | ||
| 81 | + if (error.type === 'encoding.unsupported') { | ||
| 82 | + // echo back charset | ||
| 83 | + _error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { | ||
| 84 | + charset: encoding.toLowerCase(), | ||
| 85 | + type: 'charset.unsupported' | ||
| 86 | + }) | ||
| 87 | + } else { | ||
| 88 | + // set status code on error | ||
| 89 | + _error = createError(400, error) | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + // read off entire request | ||
| 93 | + stream.resume() | ||
| 94 | + onFinished(req, function onfinished () { | ||
| 95 | + next(createError(400, _error)) | ||
| 96 | + }) | ||
| 97 | + return | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + // verify | ||
| 101 | + if (verify) { | ||
| 102 | + try { | ||
| 103 | + debug('verify body') | ||
| 104 | + verify(req, res, body, encoding) | ||
| 105 | + } catch (err) { | ||
| 106 | + next(createError(403, err, { | ||
| 107 | + body: body, | ||
| 108 | + type: err.type || 'entity.verify.failed' | ||
| 109 | + })) | ||
| 110 | + return | ||
| 111 | + } | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + // parse | ||
| 115 | + var str = body | ||
| 116 | + try { | ||
| 117 | + debug('parse body') | ||
| 118 | + str = typeof body !== 'string' && encoding !== null | ||
| 119 | + ? iconv.decode(body, encoding) | ||
| 120 | + : body | ||
| 121 | + req.body = parse(str) | ||
| 122 | + } catch (err) { | ||
| 123 | + next(createError(400, err, { | ||
| 124 | + body: str, | ||
| 125 | + type: err.type || 'entity.parse.failed' | ||
| 126 | + })) | ||
| 127 | + return | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + next() | ||
| 131 | + }) | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +/** | ||
| 135 | + * Get the content stream of the request. | ||
| 136 | + * | ||
| 137 | + * @param {object} req | ||
| 138 | + * @param {function} debug | ||
| 139 | + * @param {boolean} [inflate=true] | ||
| 140 | + * @return {object} | ||
| 141 | + * @api private | ||
| 142 | + */ | ||
| 143 | + | ||
| 144 | +function contentstream (req, debug, inflate) { | ||
| 145 | + var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase() | ||
| 146 | + var length = req.headers['content-length'] | ||
| 147 | + var stream | ||
| 148 | + | ||
| 149 | + debug('content-encoding "%s"', encoding) | ||
| 150 | + | ||
| 151 | + if (inflate === false && encoding !== 'identity') { | ||
| 152 | + throw createError(415, 'content encoding unsupported', { | ||
| 153 | + encoding: encoding, | ||
| 154 | + type: 'encoding.unsupported' | ||
| 155 | + }) | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + switch (encoding) { | ||
| 159 | + case 'deflate': | ||
| 160 | + stream = zlib.createInflate() | ||
| 161 | + debug('inflate body') | ||
| 162 | + req.pipe(stream) | ||
| 163 | + break | ||
| 164 | + case 'gzip': | ||
| 165 | + stream = zlib.createGunzip() | ||
| 166 | + debug('gunzip body') | ||
| 167 | + req.pipe(stream) | ||
| 168 | + break | ||
| 169 | + case 'identity': | ||
| 170 | + stream = req | ||
| 171 | + stream.length = length | ||
| 172 | + break | ||
| 173 | + default: | ||
| 174 | + throw createError(415, 'unsupported content encoding "' + encoding + '"', { | ||
| 175 | + encoding: encoding, | ||
| 176 | + type: 'encoding.unsupported' | ||
| 177 | + }) | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + return stream | ||
| 181 | +} |
| 1 | +/*! | ||
| 2 | + * body-parser | ||
| 3 | + * Copyright(c) 2014 Jonathan Ong | ||
| 4 | + * Copyright(c) 2014-2015 Douglas Christopher Wilson | ||
| 5 | + * MIT Licensed | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +'use strict' | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * Module dependencies. | ||
| 12 | + * @private | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | +var bytes = require('bytes') | ||
| 16 | +var contentType = require('content-type') | ||
| 17 | +var createError = require('http-errors') | ||
| 18 | +var debug = require('debug')('body-parser:json') | ||
| 19 | +var read = require('../read') | ||
| 20 | +var typeis = require('type-is') | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * Module exports. | ||
| 24 | + */ | ||
| 25 | + | ||
| 26 | +module.exports = json | ||
| 27 | + | ||
| 28 | +/** | ||
| 29 | + * RegExp to match the first non-space in a string. | ||
| 30 | + * | ||
| 31 | + * Allowed whitespace is defined in RFC 7159: | ||
| 32 | + * | ||
| 33 | + * ws = *( | ||
| 34 | + * %x20 / ; Space | ||
| 35 | + * %x09 / ; Horizontal tab | ||
| 36 | + * %x0A / ; Line feed or New line | ||
| 37 | + * %x0D ) ; Carriage return | ||
| 38 | + */ | ||
| 39 | + | ||
| 40 | +var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*(.)/ // eslint-disable-line no-control-regex | ||
| 41 | + | ||
| 42 | +/** | ||
| 43 | + * Create a middleware to parse JSON bodies. | ||
| 44 | + * | ||
| 45 | + * @param {object} [options] | ||
| 46 | + * @return {function} | ||
| 47 | + * @public | ||
| 48 | + */ | ||
| 49 | + | ||
| 50 | +function json (options) { | ||
| 51 | + var opts = options || {} | ||
| 52 | + | ||
| 53 | + var limit = typeof opts.limit !== 'number' | ||
| 54 | + ? bytes.parse(opts.limit || '100kb') | ||
| 55 | + : opts.limit | ||
| 56 | + var inflate = opts.inflate !== false | ||
| 57 | + var reviver = opts.reviver | ||
| 58 | + var strict = opts.strict !== false | ||
| 59 | + var type = opts.type || 'application/json' | ||
| 60 | + var verify = opts.verify || false | ||
| 61 | + | ||
| 62 | + if (verify !== false && typeof verify !== 'function') { | ||
| 63 | + throw new TypeError('option verify must be function') | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + // create the appropriate type checking function | ||
| 67 | + var shouldParse = typeof type !== 'function' | ||
| 68 | + ? typeChecker(type) | ||
| 69 | + : type | ||
| 70 | + | ||
| 71 | + function parse (body) { | ||
| 72 | + if (body.length === 0) { | ||
| 73 | + // special-case empty json body, as it's a common client-side mistake | ||
| 74 | + // TODO: maybe make this configurable or part of "strict" option | ||
| 75 | + return {} | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + if (strict) { | ||
| 79 | + var first = firstchar(body) | ||
| 80 | + | ||
| 81 | + if (first !== '{' && first !== '[') { | ||
| 82 | + debug('strict violation') | ||
| 83 | + throw createStrictSyntaxError(body, first) | ||
| 84 | + } | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + try { | ||
| 88 | + debug('parse json') | ||
| 89 | + return JSON.parse(body, reviver) | ||
| 90 | + } catch (e) { | ||
| 91 | + throw normalizeJsonSyntaxError(e, { | ||
| 92 | + message: e.message, | ||
| 93 | + stack: e.stack | ||
| 94 | + }) | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + return function jsonParser (req, res, next) { | ||
| 99 | + if (req._body) { | ||
| 100 | + debug('body already parsed') | ||
| 101 | + next() | ||
| 102 | + return | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + req.body = req.body || {} | ||
| 106 | + | ||
| 107 | + // skip requests without bodies | ||
| 108 | + if (!typeis.hasBody(req)) { | ||
| 109 | + debug('skip empty body') | ||
| 110 | + next() | ||
| 111 | + return | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + debug('content-type %j', req.headers['content-type']) | ||
| 115 | + | ||
| 116 | + // determine if request should be parsed | ||
| 117 | + if (!shouldParse(req)) { | ||
| 118 | + debug('skip parsing') | ||
| 119 | + next() | ||
| 120 | + return | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + // assert charset per RFC 7159 sec 8.1 | ||
| 124 | + var charset = getCharset(req) || 'utf-8' | ||
| 125 | + if (charset.substr(0, 4) !== 'utf-') { | ||
| 126 | + debug('invalid charset') | ||
| 127 | + next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { | ||
| 128 | + charset: charset, | ||
| 129 | + type: 'charset.unsupported' | ||
| 130 | + })) | ||
| 131 | + return | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + // read | ||
| 135 | + read(req, res, next, parse, debug, { | ||
| 136 | + encoding: charset, | ||
| 137 | + inflate: inflate, | ||
| 138 | + limit: limit, | ||
| 139 | + verify: verify | ||
| 140 | + }) | ||
| 141 | + } | ||
| 142 | +} | ||
| 143 | + | ||
| 144 | +/** | ||
| 145 | + * Create strict violation syntax error matching native error. | ||
| 146 | + * | ||
| 147 | + * @param {string} str | ||
| 148 | + * @param {string} char | ||
| 149 | + * @return {Error} | ||
| 150 | + * @private | ||
| 151 | + */ | ||
| 152 | + | ||
| 153 | +function createStrictSyntaxError (str, char) { | ||
| 154 | + var index = str.indexOf(char) | ||
| 155 | + var partial = str.substring(0, index) + '#' | ||
| 156 | + | ||
| 157 | + try { | ||
| 158 | + JSON.parse(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation') | ||
| 159 | + } catch (e) { | ||
| 160 | + return normalizeJsonSyntaxError(e, { | ||
| 161 | + message: e.message.replace('#', char), | ||
| 162 | + stack: e.stack | ||
| 163 | + }) | ||
| 164 | + } | ||
| 165 | +} | ||
| 166 | + | ||
| 167 | +/** | ||
| 168 | + * Get the first non-whitespace character in a string. | ||
| 169 | + * | ||
| 170 | + * @param {string} str | ||
| 171 | + * @return {function} | ||
| 172 | + * @private | ||
| 173 | + */ | ||
| 174 | + | ||
| 175 | +function firstchar (str) { | ||
| 176 | + return FIRST_CHAR_REGEXP.exec(str)[1] | ||
| 177 | +} | ||
| 178 | + | ||
| 179 | +/** | ||
| 180 | + * Get the charset of a request. | ||
| 181 | + * | ||
| 182 | + * @param {object} req | ||
| 183 | + * @api private | ||
| 184 | + */ | ||
| 185 | + | ||
| 186 | +function getCharset (req) { | ||
| 187 | + try { | ||
| 188 | + return (contentType.parse(req).parameters.charset || '').toLowerCase() | ||
| 189 | + } catch (e) { | ||
| 190 | + return undefined | ||
| 191 | + } | ||
| 192 | +} | ||
| 193 | + | ||
| 194 | +/** | ||
| 195 | + * Normalize a SyntaxError for JSON.parse. | ||
| 196 | + * | ||
| 197 | + * @param {SyntaxError} error | ||
| 198 | + * @param {object} obj | ||
| 199 | + * @return {SyntaxError} | ||
| 200 | + */ | ||
| 201 | + | ||
| 202 | +function normalizeJsonSyntaxError (error, obj) { | ||
| 203 | + var keys = Object.getOwnPropertyNames(error) | ||
| 204 | + | ||
| 205 | + for (var i = 0; i < keys.length; i++) { | ||
| 206 | + var key = keys[i] | ||
| 207 | + if (key !== 'stack' && key !== 'message') { | ||
| 208 | + delete error[key] | ||
| 209 | + } | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + // replace stack before message for Node.js 0.10 and below | ||
| 213 | + error.stack = obj.stack.replace(error.message, obj.message) | ||
| 214 | + error.message = obj.message | ||
| 215 | + | ||
| 216 | + return error | ||
| 217 | +} | ||
| 218 | + | ||
| 219 | +/** | ||
| 220 | + * Get the simple type checker. | ||
| 221 | + * | ||
| 222 | + * @param {string} type | ||
| 223 | + * @return {function} | ||
| 224 | + */ | ||
| 225 | + | ||
| 226 | +function typeChecker (type) { | ||
| 227 | + return function checkType (req) { | ||
| 228 | + return Boolean(typeis(req, type)) | ||
| 229 | + } | ||
| 230 | +} |
| 1 | +/*! | ||
| 2 | + * body-parser | ||
| 3 | + * Copyright(c) 2014-2015 Douglas Christopher Wilson | ||
| 4 | + * MIT Licensed | ||
| 5 | + */ | ||
| 6 | + | ||
| 7 | +'use strict' | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * Module dependencies. | ||
| 11 | + */ | ||
| 12 | + | ||
| 13 | +var bytes = require('bytes') | ||
| 14 | +var debug = require('debug')('body-parser:raw') | ||
| 15 | +var read = require('../read') | ||
| 16 | +var typeis = require('type-is') | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * Module exports. | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | +module.exports = raw | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * Create a middleware to parse raw bodies. | ||
| 26 | + * | ||
| 27 | + * @param {object} [options] | ||
| 28 | + * @return {function} | ||
| 29 | + * @api public | ||
| 30 | + */ | ||
| 31 | + | ||
| 32 | +function raw (options) { | ||
| 33 | + var opts = options || {} | ||
| 34 | + | ||
| 35 | + var inflate = opts.inflate !== false | ||
| 36 | + var limit = typeof opts.limit !== 'number' | ||
| 37 | + ? bytes.parse(opts.limit || '100kb') | ||
| 38 | + : opts.limit | ||
| 39 | + var type = opts.type || 'application/octet-stream' | ||
| 40 | + var verify = opts.verify || false | ||
| 41 | + | ||
| 42 | + if (verify !== false && typeof verify !== 'function') { | ||
| 43 | + throw new TypeError('option verify must be function') | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + // create the appropriate type checking function | ||
| 47 | + var shouldParse = typeof type !== 'function' | ||
| 48 | + ? typeChecker(type) | ||
| 49 | + : type | ||
| 50 | + | ||
| 51 | + function parse (buf) { | ||
| 52 | + return buf | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + return function rawParser (req, res, next) { | ||
| 56 | + if (req._body) { | ||
| 57 | + debug('body already parsed') | ||
| 58 | + next() | ||
| 59 | + return | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + req.body = req.body || {} | ||
| 63 | + | ||
| 64 | + // skip requests without bodies | ||
| 65 | + if (!typeis.hasBody(req)) { | ||
| 66 | + debug('skip empty body') | ||
| 67 | + next() | ||
| 68 | + return | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + debug('content-type %j', req.headers['content-type']) | ||
| 72 | + | ||
| 73 | + // determine if request should be parsed | ||
| 74 | + if (!shouldParse(req)) { | ||
| 75 | + debug('skip parsing') | ||
| 76 | + next() | ||
| 77 | + return | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + // read | ||
| 81 | + read(req, res, next, parse, debug, { | ||
| 82 | + encoding: null, | ||
| 83 | + inflate: inflate, | ||
| 84 | + limit: limit, | ||
| 85 | + verify: verify | ||
| 86 | + }) | ||
| 87 | + } | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +/** | ||
| 91 | + * Get the simple type checker. | ||
| 92 | + * | ||
| 93 | + * @param {string} type | ||
| 94 | + * @return {function} | ||
| 95 | + */ | ||
| 96 | + | ||
| 97 | +function typeChecker (type) { | ||
| 98 | + return function checkType (req) { | ||
| 99 | + return Boolean(typeis(req, type)) | ||
| 100 | + } | ||
| 101 | +} |
| 1 | +/*! | ||
| 2 | + * body-parser | ||
| 3 | + * Copyright(c) 2014-2015 Douglas Christopher Wilson | ||
| 4 | + * MIT Licensed | ||
| 5 | + */ | ||
| 6 | + | ||
| 7 | +'use strict' | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * Module dependencies. | ||
| 11 | + */ | ||
| 12 | + | ||
| 13 | +var bytes = require('bytes') | ||
| 14 | +var contentType = require('content-type') | ||
| 15 | +var debug = require('debug')('body-parser:text') | ||
| 16 | +var read = require('../read') | ||
| 17 | +var typeis = require('type-is') | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * Module exports. | ||
| 21 | + */ | ||
| 22 | + | ||
| 23 | +module.exports = text | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * Create a middleware to parse text bodies. | ||
| 27 | + * | ||
| 28 | + * @param {object} [options] | ||
| 29 | + * @return {function} | ||
| 30 | + * @api public | ||
| 31 | + */ | ||
| 32 | + | ||
| 33 | +function text (options) { | ||
| 34 | + var opts = options || {} | ||
| 35 | + | ||
| 36 | + var defaultCharset = opts.defaultCharset || 'utf-8' | ||
| 37 | + var inflate = opts.inflate !== false | ||
| 38 | + var limit = typeof opts.limit !== 'number' | ||
| 39 | + ? bytes.parse(opts.limit || '100kb') | ||
| 40 | + : opts.limit | ||
| 41 | + var type = opts.type || 'text/plain' | ||
| 42 | + var verify = opts.verify || false | ||
| 43 | + | ||
| 44 | + if (verify !== false && typeof verify !== 'function') { | ||
| 45 | + throw new TypeError('option verify must be function') | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + // create the appropriate type checking function | ||
| 49 | + var shouldParse = typeof type !== 'function' | ||
| 50 | + ? typeChecker(type) | ||
| 51 | + : type | ||
| 52 | + | ||
| 53 | + function parse (buf) { | ||
| 54 | + return buf | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + return function textParser (req, res, next) { | ||
| 58 | + if (req._body) { | ||
| 59 | + debug('body already parsed') | ||
| 60 | + next() | ||
| 61 | + return | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + req.body = req.body || {} | ||
| 65 | + | ||
| 66 | + // skip requests without bodies | ||
| 67 | + if (!typeis.hasBody(req)) { | ||
| 68 | + debug('skip empty body') | ||
| 69 | + next() | ||
| 70 | + return | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + debug('content-type %j', req.headers['content-type']) | ||
| 74 | + | ||
| 75 | + // determine if request should be parsed | ||
| 76 | + if (!shouldParse(req)) { | ||
| 77 | + debug('skip parsing') | ||
| 78 | + next() | ||
| 79 | + return | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + // get charset | ||
| 83 | + var charset = getCharset(req) || defaultCharset | ||
| 84 | + | ||
| 85 | + // read | ||
| 86 | + read(req, res, next, parse, debug, { | ||
| 87 | + encoding: charset, | ||
| 88 | + inflate: inflate, | ||
| 89 | + limit: limit, | ||
| 90 | + verify: verify | ||
| 91 | + }) | ||
| 92 | + } | ||
| 93 | +} | ||
| 94 | + | ||
| 95 | +/** | ||
| 96 | + * Get the charset of a request. | ||
| 97 | + * | ||
| 98 | + * @param {object} req | ||
| 99 | + * @api private | ||
| 100 | + */ | ||
| 101 | + | ||
| 102 | +function getCharset (req) { | ||
| 103 | + try { | ||
| 104 | + return (contentType.parse(req).parameters.charset || '').toLowerCase() | ||
| 105 | + } catch (e) { | ||
| 106 | + return undefined | ||
| 107 | + } | ||
| 108 | +} | ||
| 109 | + | ||
| 110 | +/** | ||
| 111 | + * Get the simple type checker. | ||
| 112 | + * | ||
| 113 | + * @param {string} type | ||
| 114 | + * @return {function} | ||
| 115 | + */ | ||
| 116 | + | ||
| 117 | +function typeChecker (type) { | ||
| 118 | + return function checkType (req) { | ||
| 119 | + return Boolean(typeis(req, type)) | ||
| 120 | + } | ||
| 121 | +} |
| 1 | +/*! | ||
| 2 | + * body-parser | ||
| 3 | + * Copyright(c) 2014 Jonathan Ong | ||
| 4 | + * Copyright(c) 2014-2015 Douglas Christopher Wilson | ||
| 5 | + * MIT Licensed | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +'use strict' | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * Module dependencies. | ||
| 12 | + * @private | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | +var bytes = require('bytes') | ||
| 16 | +var contentType = require('content-type') | ||
| 17 | +var createError = require('http-errors') | ||
| 18 | +var debug = require('debug')('body-parser:urlencoded') | ||
| 19 | +var deprecate = require('depd')('body-parser') | ||
| 20 | +var read = require('../read') | ||
| 21 | +var typeis = require('type-is') | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * Module exports. | ||
| 25 | + */ | ||
| 26 | + | ||
| 27 | +module.exports = urlencoded | ||
| 28 | + | ||
| 29 | +/** | ||
| 30 | + * Cache of parser modules. | ||
| 31 | + */ | ||
| 32 | + | ||
| 33 | +var parsers = Object.create(null) | ||
| 34 | + | ||
| 35 | +/** | ||
| 36 | + * Create a middleware to parse urlencoded bodies. | ||
| 37 | + * | ||
| 38 | + * @param {object} [options] | ||
| 39 | + * @return {function} | ||
| 40 | + * @public | ||
| 41 | + */ | ||
| 42 | + | ||
| 43 | +function urlencoded (options) { | ||
| 44 | + var opts = options || {} | ||
| 45 | + | ||
| 46 | + // notice because option default will flip in next major | ||
| 47 | + if (opts.extended === undefined) { | ||
| 48 | + deprecate('undefined extended: provide extended option') | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + var extended = opts.extended !== false | ||
| 52 | + var inflate = opts.inflate !== false | ||
| 53 | + var limit = typeof opts.limit !== 'number' | ||
| 54 | + ? bytes.parse(opts.limit || '100kb') | ||
| 55 | + : opts.limit | ||
| 56 | + var type = opts.type || 'application/x-www-form-urlencoded' | ||
| 57 | + var verify = opts.verify || false | ||
| 58 | + | ||
| 59 | + if (verify !== false && typeof verify !== 'function') { | ||
| 60 | + throw new TypeError('option verify must be function') | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + // create the appropriate query parser | ||
| 64 | + var queryparse = extended | ||
| 65 | + ? extendedparser(opts) | ||
| 66 | + : simpleparser(opts) | ||
| 67 | + | ||
| 68 | + // create the appropriate type checking function | ||
| 69 | + var shouldParse = typeof type !== 'function' | ||
| 70 | + ? typeChecker(type) | ||
| 71 | + : type | ||
| 72 | + | ||
| 73 | + function parse (body) { | ||
| 74 | + return body.length | ||
| 75 | + ? queryparse(body) | ||
| 76 | + : {} | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + return function urlencodedParser (req, res, next) { | ||
| 80 | + if (req._body) { | ||
| 81 | + debug('body already parsed') | ||
| 82 | + next() | ||
| 83 | + return | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + req.body = req.body || {} | ||
| 87 | + | ||
| 88 | + // skip requests without bodies | ||
| 89 | + if (!typeis.hasBody(req)) { | ||
| 90 | + debug('skip empty body') | ||
| 91 | + next() | ||
| 92 | + return | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + debug('content-type %j', req.headers['content-type']) | ||
| 96 | + | ||
| 97 | + // determine if request should be parsed | ||
| 98 | + if (!shouldParse(req)) { | ||
| 99 | + debug('skip parsing') | ||
| 100 | + next() | ||
| 101 | + return | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + // assert charset | ||
| 105 | + var charset = getCharset(req) || 'utf-8' | ||
| 106 | + if (charset !== 'utf-8') { | ||
| 107 | + debug('invalid charset') | ||
| 108 | + next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { | ||
| 109 | + charset: charset, | ||
| 110 | + type: 'charset.unsupported' | ||
| 111 | + })) | ||
| 112 | + return | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + // read | ||
| 116 | + read(req, res, next, parse, debug, { | ||
| 117 | + debug: debug, | ||
| 118 | + encoding: charset, | ||
| 119 | + inflate: inflate, | ||
| 120 | + limit: limit, | ||
| 121 | + verify: verify | ||
| 122 | + }) | ||
| 123 | + } | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +/** | ||
| 127 | + * Get the extended query parser. | ||
| 128 | + * | ||
| 129 | + * @param {object} options | ||
| 130 | + */ | ||
| 131 | + | ||
| 132 | +function extendedparser (options) { | ||
| 133 | + var parameterLimit = options.parameterLimit !== undefined | ||
| 134 | + ? options.parameterLimit | ||
| 135 | + : 1000 | ||
| 136 | + var parse = parser('qs') | ||
| 137 | + | ||
| 138 | + if (isNaN(parameterLimit) || parameterLimit < 1) { | ||
| 139 | + throw new TypeError('option parameterLimit must be a positive number') | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + if (isFinite(parameterLimit)) { | ||
| 143 | + parameterLimit = parameterLimit | 0 | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + return function queryparse (body) { | ||
| 147 | + var paramCount = parameterCount(body, parameterLimit) | ||
| 148 | + | ||
| 149 | + if (paramCount === undefined) { | ||
| 150 | + debug('too many parameters') | ||
| 151 | + throw createError(413, 'too many parameters', { | ||
| 152 | + type: 'parameters.too.many' | ||
| 153 | + }) | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + var arrayLimit = Math.max(100, paramCount) | ||
| 157 | + | ||
| 158 | + debug('parse extended urlencoding') | ||
| 159 | + return parse(body, { | ||
| 160 | + allowPrototypes: true, | ||
| 161 | + arrayLimit: arrayLimit, | ||
| 162 | + depth: Infinity, | ||
| 163 | + parameterLimit: parameterLimit | ||
| 164 | + }) | ||
| 165 | + } | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +/** | ||
| 169 | + * Get the charset of a request. | ||
| 170 | + * | ||
| 171 | + * @param {object} req | ||
| 172 | + * @api private | ||
| 173 | + */ | ||
| 174 | + | ||
| 175 | +function getCharset (req) { | ||
| 176 | + try { | ||
| 177 | + return (contentType.parse(req).parameters.charset || '').toLowerCase() | ||
| 178 | + } catch (e) { | ||
| 179 | + return undefined | ||
| 180 | + } | ||
| 181 | +} | ||
| 182 | + | ||
| 183 | +/** | ||
| 184 | + * Count the number of parameters, stopping once limit reached | ||
| 185 | + * | ||
| 186 | + * @param {string} body | ||
| 187 | + * @param {number} limit | ||
| 188 | + * @api private | ||
| 189 | + */ | ||
| 190 | + | ||
| 191 | +function parameterCount (body, limit) { | ||
| 192 | + var count = 0 | ||
| 193 | + var index = 0 | ||
| 194 | + | ||
| 195 | + while ((index = body.indexOf('&', index)) !== -1) { | ||
| 196 | + count++ | ||
| 197 | + index++ | ||
| 198 | + | ||
| 199 | + if (count === limit) { | ||
| 200 | + return undefined | ||
| 201 | + } | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + return count | ||
| 205 | +} | ||
| 206 | + | ||
| 207 | +/** | ||
| 208 | + * Get parser for module name dynamically. | ||
| 209 | + * | ||
| 210 | + * @param {string} name | ||
| 211 | + * @return {function} | ||
| 212 | + * @api private | ||
| 213 | + */ | ||
| 214 | + | ||
| 215 | +function parser (name) { | ||
| 216 | + var mod = parsers[name] | ||
| 217 | + | ||
| 218 | + if (mod !== undefined) { | ||
| 219 | + return mod.parse | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | + // this uses a switch for static require analysis | ||
| 223 | + switch (name) { | ||
| 224 | + case 'qs': | ||
| 225 | + mod = require('qs') | ||
| 226 | + break | ||
| 227 | + case 'querystring': | ||
| 228 | + mod = require('querystring') | ||
| 229 | + break | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + // store to prevent invoking require() | ||
| 233 | + parsers[name] = mod | ||
| 234 | + | ||
| 235 | + return mod.parse | ||
| 236 | +} | ||
| 237 | + | ||
| 238 | +/** | ||
| 239 | + * Get the simple query parser. | ||
| 240 | + * | ||
| 241 | + * @param {object} options | ||
| 242 | + */ | ||
| 243 | + | ||
| 244 | +function simpleparser (options) { | ||
| 245 | + var parameterLimit = options.parameterLimit !== undefined | ||
| 246 | + ? options.parameterLimit | ||
| 247 | + : 1000 | ||
| 248 | + var parse = parser('querystring') | ||
| 249 | + | ||
| 250 | + if (isNaN(parameterLimit) || parameterLimit < 1) { | ||
| 251 | + throw new TypeError('option parameterLimit must be a positive number') | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + if (isFinite(parameterLimit)) { | ||
| 255 | + parameterLimit = parameterLimit | 0 | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + return function queryparse (body) { | ||
| 259 | + var paramCount = parameterCount(body, parameterLimit) | ||
| 260 | + | ||
| 261 | + if (paramCount === undefined) { | ||
| 262 | + debug('too many parameters') | ||
| 263 | + throw createError(413, 'too many parameters', { | ||
| 264 | + type: 'parameters.too.many' | ||
| 265 | + }) | ||
| 266 | + } | ||
| 267 | + | ||
| 268 | + debug('parse urlencoding') | ||
| 269 | + return parse(body, undefined, undefined, { maxKeys: parameterLimit }) | ||
| 270 | + } | ||
| 271 | +} | ||
| 272 | + | ||
| 273 | +/** | ||
| 274 | + * Get the simple type checker. | ||
| 275 | + * | ||
| 276 | + * @param {string} type | ||
| 277 | + * @return {function} | ||
| 278 | + */ | ||
| 279 | + | ||
| 280 | +function typeChecker (type) { | ||
| 281 | + return function checkType (req) { | ||
| 282 | + return Boolean(typeis(req, type)) | ||
| 283 | + } | ||
| 284 | +} |
| 1 | +{ | ||
| 2 | + "_from": "body-parser@1.19.0", | ||
| 3 | + "_id": "body-parser@1.19.0", | ||
| 4 | + "_inBundle": false, | ||
| 5 | + "_integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", | ||
| 6 | + "_location": "/body-parser", | ||
| 7 | + "_phantomChildren": {}, | ||
| 8 | + "_requested": { | ||
| 9 | + "type": "version", | ||
| 10 | + "registry": true, | ||
| 11 | + "raw": "body-parser@1.19.0", | ||
| 12 | + "name": "body-parser", | ||
| 13 | + "escapedName": "body-parser", | ||
| 14 | + "rawSpec": "1.19.0", | ||
| 15 | + "saveSpec": null, | ||
| 16 | + "fetchSpec": "1.19.0" | ||
| 17 | + }, | ||
| 18 | + "_requiredBy": [ | ||
| 19 | + "/express" | ||
| 20 | + ], | ||
| 21 | + "_resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", | ||
| 22 | + "_shasum": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a", | ||
| 23 | + "_spec": "body-parser@1.19.0", | ||
| 24 | + "_where": "C:\\Users\\SIMBA\\Desktop\\SpotifyPlaylistExport-master\\node_modules\\express", | ||
| 25 | + "bugs": { | ||
| 26 | + "url": "https://github.com/expressjs/body-parser/issues" | ||
| 27 | + }, | ||
| 28 | + "bundleDependencies": false, | ||
| 29 | + "contributors": [ | ||
| 30 | + { | ||
| 31 | + "name": "Douglas Christopher Wilson", | ||
| 32 | + "email": "doug@somethingdoug.com" | ||
| 33 | + }, | ||
| 34 | + { | ||
| 35 | + "name": "Jonathan Ong", | ||
| 36 | + "email": "me@jongleberry.com", | ||
| 37 | + "url": "http://jongleberry.com" | ||
| 38 | + } | ||
| 39 | + ], | ||
| 40 | + "dependencies": { | ||
| 41 | + "bytes": "3.1.0", | ||
| 42 | + "content-type": "~1.0.4", | ||
| 43 | + "debug": "2.6.9", | ||
| 44 | + "depd": "~1.1.2", | ||
| 45 | + "http-errors": "1.7.2", | ||
| 46 | + "iconv-lite": "0.4.24", | ||
| 47 | + "on-finished": "~2.3.0", | ||
| 48 | + "qs": "6.7.0", | ||
| 49 | + "raw-body": "2.4.0", | ||
| 50 | + "type-is": "~1.6.17" | ||
| 51 | + }, | ||
| 52 | + "deprecated": false, | ||
| 53 | + "description": "Node.js body parsing middleware", | ||
| 54 | + "devDependencies": { | ||
| 55 | + "eslint": "5.16.0", | ||
| 56 | + "eslint-config-standard": "12.0.0", | ||
| 57 | + "eslint-plugin-import": "2.17.2", | ||
| 58 | + "eslint-plugin-markdown": "1.0.0", | ||
| 59 | + "eslint-plugin-node": "8.0.1", | ||
| 60 | + "eslint-plugin-promise": "4.1.1", | ||
| 61 | + "eslint-plugin-standard": "4.0.0", | ||
| 62 | + "istanbul": "0.4.5", | ||
| 63 | + "methods": "1.1.2", | ||
| 64 | + "mocha": "6.1.4", | ||
| 65 | + "safe-buffer": "5.1.2", | ||
| 66 | + "supertest": "4.0.2" | ||
| 67 | + }, | ||
| 68 | + "engines": { | ||
| 69 | + "node": ">= 0.8" | ||
| 70 | + }, | ||
| 71 | + "files": [ | ||
| 72 | + "lib/", | ||
| 73 | + "LICENSE", | ||
| 74 | + "HISTORY.md", | ||
| 75 | + "index.js" | ||
| 76 | + ], | ||
| 77 | + "homepage": "https://github.com/expressjs/body-parser#readme", | ||
| 78 | + "license": "MIT", | ||
| 79 | + "name": "body-parser", | ||
| 80 | + "repository": { | ||
| 81 | + "type": "git", | ||
| 82 | + "url": "git+https://github.com/expressjs/body-parser.git" | ||
| 83 | + }, | ||
| 84 | + "scripts": { | ||
| 85 | + "lint": "eslint --plugin markdown --ext js,md .", | ||
| 86 | + "test": "mocha --require test/support/env --reporter spec --check-leaks --bail test/", | ||
| 87 | + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/", | ||
| 88 | + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/" | ||
| 89 | + }, | ||
| 90 | + "version": "1.19.0" | ||
| 91 | +} |
| 1 | +3.1.0 / 2019-01-22 | ||
| 2 | +================== | ||
| 3 | + | ||
| 4 | + * Add petabyte (`pb`) support | ||
| 5 | + | ||
| 6 | +3.0.0 / 2017-08-31 | ||
| 7 | +================== | ||
| 8 | + | ||
| 9 | + * Change "kB" to "KB" in format output | ||
| 10 | + * Remove support for Node.js 0.6 | ||
| 11 | + * Remove support for ComponentJS | ||
| 12 | + | ||
| 13 | +2.5.0 / 2017-03-24 | ||
| 14 | +================== | ||
| 15 | + | ||
| 16 | + * Add option "unit" | ||
| 17 | + | ||
| 18 | +2.4.0 / 2016-06-01 | ||
| 19 | +================== | ||
| 20 | + | ||
| 21 | + * Add option "unitSeparator" | ||
| 22 | + | ||
| 23 | +2.3.0 / 2016-02-15 | ||
| 24 | +================== | ||
| 25 | + | ||
| 26 | + * Drop partial bytes on all parsed units | ||
| 27 | + * Fix non-finite numbers to `.format` to return `null` | ||
| 28 | + * Fix parsing byte string that looks like hex | ||
| 29 | + * perf: hoist regular expressions | ||
| 30 | + | ||
| 31 | +2.2.0 / 2015-11-13 | ||
| 32 | +================== | ||
| 33 | + | ||
| 34 | + * add option "decimalPlaces" | ||
| 35 | + * add option "fixedDecimals" | ||
| 36 | + | ||
| 37 | +2.1.0 / 2015-05-21 | ||
| 38 | +================== | ||
| 39 | + | ||
| 40 | + * add `.format` export | ||
| 41 | + * add `.parse` export | ||
| 42 | + | ||
| 43 | +2.0.2 / 2015-05-20 | ||
| 44 | +================== | ||
| 45 | + | ||
| 46 | + * remove map recreation | ||
| 47 | + * remove unnecessary object construction | ||
| 48 | + | ||
| 49 | +2.0.1 / 2015-05-07 | ||
| 50 | +================== | ||
| 51 | + | ||
| 52 | + * fix browserify require | ||
| 53 | + * remove node.extend dependency | ||
| 54 | + | ||
| 55 | +2.0.0 / 2015-04-12 | ||
| 56 | +================== | ||
| 57 | + | ||
| 58 | + * add option "case" | ||
| 59 | + * add option "thousandsSeparator" | ||
| 60 | + * return "null" on invalid parse input | ||
| 61 | + * support proper round-trip: bytes(bytes(num)) === num | ||
| 62 | + * units no longer case sensitive when parsing | ||
| 63 | + | ||
| 64 | +1.0.0 / 2014-05-05 | ||
| 65 | +================== | ||
| 66 | + | ||
| 67 | + * add negative support. fixes #6 | ||
| 68 | + | ||
| 69 | +0.3.0 / 2014-03-19 | ||
| 70 | +================== | ||
| 71 | + | ||
| 72 | + * added terabyte support | ||
| 73 | + | ||
| 74 | +0.2.1 / 2013-04-01 | ||
| 75 | +================== | ||
| 76 | + | ||
| 77 | + * add .component | ||
| 78 | + | ||
| 79 | +0.2.0 / 2012-10-28 | ||
| 80 | +================== | ||
| 81 | + | ||
| 82 | + * bytes(200).should.eql('200b') | ||
| 83 | + | ||
| 84 | +0.1.0 / 2012-07-04 | ||
| 85 | +================== | ||
| 86 | + | ||
| 87 | + * add bytes to string conversion [yields] |
| 1 | +(The MIT License) | ||
| 2 | + | ||
| 3 | +Copyright (c) 2012-2014 TJ Holowaychuk <tj@vision-media.ca> | ||
| 4 | +Copyright (c) 2015 Jed Watson <jed.watson@me.com> | ||
| 5 | + | ||
| 6 | +Permission is hereby granted, free of charge, to any person obtaining | ||
| 7 | +a copy of this software and associated documentation files (the | ||
| 8 | +'Software'), to deal in the Software without restriction, including | ||
| 9 | +without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | +distribute, sublicense, and/or sell copies of the Software, and to | ||
| 11 | +permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | +the following conditions: | ||
| 13 | + | ||
| 14 | +The above copyright notice and this permission notice shall be | ||
| 15 | +included in all copies or substantial portions of the Software. | ||
| 16 | + | ||
| 17 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
| 18 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 19 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| 20 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
| 21 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
| 22 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
| 23 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 1 | +# Bytes utility | ||
| 2 | + | ||
| 3 | +[![NPM Version][npm-image]][npm-url] | ||
| 4 | +[![NPM Downloads][downloads-image]][downloads-url] | ||
| 5 | +[![Build Status][travis-image]][travis-url] | ||
| 6 | +[![Test Coverage][coveralls-image]][coveralls-url] | ||
| 7 | + | ||
| 8 | +Utility to parse a string bytes (ex: `1TB`) to bytes (`1099511627776`) and vice-versa. | ||
| 9 | + | ||
| 10 | +## Installation | ||
| 11 | + | ||
| 12 | +This is a [Node.js](https://nodejs.org/en/) module available through the | ||
| 13 | +[npm registry](https://www.npmjs.com/). Installation is done using the | ||
| 14 | +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): | ||
| 15 | + | ||
| 16 | +```bash | ||
| 17 | +$ npm install bytes | ||
| 18 | +``` | ||
| 19 | + | ||
| 20 | +## Usage | ||
| 21 | + | ||
| 22 | +```js | ||
| 23 | +var bytes = require('bytes'); | ||
| 24 | +``` | ||
| 25 | + | ||
| 26 | +#### bytes.format(number value, [options]): string|null | ||
| 27 | + | ||
| 28 | +Format the given value in bytes into a string. If the value is negative, it is kept as such. If it is a float, it is | ||
| 29 | + rounded. | ||
| 30 | + | ||
| 31 | +**Arguments** | ||
| 32 | + | ||
| 33 | +| Name | Type | Description | | ||
| 34 | +|---------|----------|--------------------| | ||
| 35 | +| value | `number` | Value in bytes | | ||
| 36 | +| options | `Object` | Conversion options | | ||
| 37 | + | ||
| 38 | +**Options** | ||
| 39 | + | ||
| 40 | +| Property | Type | Description | | ||
| 41 | +|-------------------|--------|-----------------------------------------------------------------------------------------| | ||
| 42 | +| decimalPlaces | `number`|`null` | Maximum number of decimal places to include in output. Default value to `2`. | | ||
| 43 | +| fixedDecimals | `boolean`|`null` | Whether to always display the maximum number of decimal places. Default value to `false` | | ||
| 44 | +| thousandsSeparator | `string`|`null` | Example of values: `' '`, `','` and `.`... Default value to `''`. | | ||
| 45 | +| unit | `string`|`null` | The unit in which the result will be returned (B/KB/MB/GB/TB). Default value to `''` (which means auto detect). | | ||
| 46 | +| unitSeparator | `string`|`null` | Separator to use between number and unit. Default value to `''`. | | ||
| 47 | + | ||
| 48 | +**Returns** | ||
| 49 | + | ||
| 50 | +| Name | Type | Description | | ||
| 51 | +|---------|------------------|-------------------------------------------------| | ||
| 52 | +| results | `string`|`null` | Return null upon error. String value otherwise. | | ||
| 53 | + | ||
| 54 | +**Example** | ||
| 55 | + | ||
| 56 | +```js | ||
| 57 | +bytes(1024); | ||
| 58 | +// output: '1KB' | ||
| 59 | + | ||
| 60 | +bytes(1000); | ||
| 61 | +// output: '1000B' | ||
| 62 | + | ||
| 63 | +bytes(1000, {thousandsSeparator: ' '}); | ||
| 64 | +// output: '1 000B' | ||
| 65 | + | ||
| 66 | +bytes(1024 * 1.7, {decimalPlaces: 0}); | ||
| 67 | +// output: '2KB' | ||
| 68 | + | ||
| 69 | +bytes(1024, {unitSeparator: ' '}); | ||
| 70 | +// output: '1 KB' | ||
| 71 | + | ||
| 72 | +``` | ||
| 73 | + | ||
| 74 | +#### bytes.parse(string|number value): number|null | ||
| 75 | + | ||
| 76 | +Parse the string value into an integer in bytes. If no unit is given, or `value` | ||
| 77 | +is a number, it is assumed the value is in bytes. | ||
| 78 | + | ||
| 79 | +Supported units and abbreviations are as follows and are case-insensitive: | ||
| 80 | + | ||
| 81 | + * `b` for bytes | ||
| 82 | + * `kb` for kilobytes | ||
| 83 | + * `mb` for megabytes | ||
| 84 | + * `gb` for gigabytes | ||
| 85 | + * `tb` for terabytes | ||
| 86 | + * `pb` for petabytes | ||
| 87 | + | ||
| 88 | +The units are in powers of two, not ten. This means 1kb = 1024b according to this parser. | ||
| 89 | + | ||
| 90 | +**Arguments** | ||
| 91 | + | ||
| 92 | +| Name | Type | Description | | ||
| 93 | +|---------------|--------|--------------------| | ||
| 94 | +| value | `string`|`number` | String to parse, or number in bytes. | | ||
| 95 | + | ||
| 96 | +**Returns** | ||
| 97 | + | ||
| 98 | +| Name | Type | Description | | ||
| 99 | +|---------|-------------|-------------------------| | ||
| 100 | +| results | `number`|`null` | Return null upon error. Value in bytes otherwise. | | ||
| 101 | + | ||
| 102 | +**Example** | ||
| 103 | + | ||
| 104 | +```js | ||
| 105 | +bytes('1KB'); | ||
| 106 | +// output: 1024 | ||
| 107 | + | ||
| 108 | +bytes('1024'); | ||
| 109 | +// output: 1024 | ||
| 110 | + | ||
| 111 | +bytes(1024); | ||
| 112 | +// output: 1KB | ||
| 113 | +``` | ||
| 114 | + | ||
| 115 | +## License | ||
| 116 | + | ||
| 117 | +[MIT](LICENSE) | ||
| 118 | + | ||
| 119 | +[coveralls-image]: https://badgen.net/coveralls/c/github/visionmedia/bytes.js/master | ||
| 120 | +[coveralls-url]: https://coveralls.io/r/visionmedia/bytes.js?branch=master | ||
| 121 | +[downloads-image]: https://badgen.net/npm/dm/bytes | ||
| 122 | +[downloads-url]: https://npmjs.org/package/bytes | ||
| 123 | +[npm-image]: https://badgen.net/npm/node/bytes | ||
| 124 | +[npm-url]: https://npmjs.org/package/bytes | ||
| 125 | +[travis-image]: https://badgen.net/travis/visionmedia/bytes.js/master | ||
| 126 | +[travis-url]: https://travis-ci.org/visionmedia/bytes.js |
| 1 | +/*! | ||
| 2 | + * bytes | ||
| 3 | + * Copyright(c) 2012-2014 TJ Holowaychuk | ||
| 4 | + * Copyright(c) 2015 Jed Watson | ||
| 5 | + * MIT Licensed | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +'use strict'; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * Module exports. | ||
| 12 | + * @public | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | +module.exports = bytes; | ||
| 16 | +module.exports.format = format; | ||
| 17 | +module.exports.parse = parse; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * Module variables. | ||
| 21 | + * @private | ||
| 22 | + */ | ||
| 23 | + | ||
| 24 | +var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g; | ||
| 25 | + | ||
| 26 | +var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/; | ||
| 27 | + | ||
| 28 | +var map = { | ||
| 29 | + b: 1, | ||
| 30 | + kb: 1 << 10, | ||
| 31 | + mb: 1 << 20, | ||
| 32 | + gb: 1 << 30, | ||
| 33 | + tb: Math.pow(1024, 4), | ||
| 34 | + pb: Math.pow(1024, 5), | ||
| 35 | +}; | ||
| 36 | + | ||
| 37 | +var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i; | ||
| 38 | + | ||
| 39 | +/** | ||
| 40 | + * Convert the given value in bytes into a string or parse to string to an integer in bytes. | ||
| 41 | + * | ||
| 42 | + * @param {string|number} value | ||
| 43 | + * @param {{ | ||
| 44 | + * case: [string], | ||
| 45 | + * decimalPlaces: [number] | ||
| 46 | + * fixedDecimals: [boolean] | ||
| 47 | + * thousandsSeparator: [string] | ||
| 48 | + * unitSeparator: [string] | ||
| 49 | + * }} [options] bytes options. | ||
| 50 | + * | ||
| 51 | + * @returns {string|number|null} | ||
| 52 | + */ | ||
| 53 | + | ||
| 54 | +function bytes(value, options) { | ||
| 55 | + if (typeof value === 'string') { | ||
| 56 | + return parse(value); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + if (typeof value === 'number') { | ||
| 60 | + return format(value, options); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + return null; | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +/** | ||
| 67 | + * Format the given value in bytes into a string. | ||
| 68 | + * | ||
| 69 | + * If the value is negative, it is kept as such. If it is a float, | ||
| 70 | + * it is rounded. | ||
| 71 | + * | ||
| 72 | + * @param {number} value | ||
| 73 | + * @param {object} [options] | ||
| 74 | + * @param {number} [options.decimalPlaces=2] | ||
| 75 | + * @param {number} [options.fixedDecimals=false] | ||
| 76 | + * @param {string} [options.thousandsSeparator=] | ||
| 77 | + * @param {string} [options.unit=] | ||
| 78 | + * @param {string} [options.unitSeparator=] | ||
| 79 | + * | ||
| 80 | + * @returns {string|null} | ||
| 81 | + * @public | ||
| 82 | + */ | ||
| 83 | + | ||
| 84 | +function format(value, options) { | ||
| 85 | + if (!Number.isFinite(value)) { | ||
| 86 | + return null; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + var mag = Math.abs(value); | ||
| 90 | + var thousandsSeparator = (options && options.thousandsSeparator) || ''; | ||
| 91 | + var unitSeparator = (options && options.unitSeparator) || ''; | ||
| 92 | + var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2; | ||
| 93 | + var fixedDecimals = Boolean(options && options.fixedDecimals); | ||
| 94 | + var unit = (options && options.unit) || ''; | ||
| 95 | + | ||
| 96 | + if (!unit || !map[unit.toLowerCase()]) { | ||
| 97 | + if (mag >= map.pb) { | ||
| 98 | + unit = 'PB'; | ||
| 99 | + } else if (mag >= map.tb) { | ||
| 100 | + unit = 'TB'; | ||
| 101 | + } else if (mag >= map.gb) { | ||
| 102 | + unit = 'GB'; | ||
| 103 | + } else if (mag >= map.mb) { | ||
| 104 | + unit = 'MB'; | ||
| 105 | + } else if (mag >= map.kb) { | ||
| 106 | + unit = 'KB'; | ||
| 107 | + } else { | ||
| 108 | + unit = 'B'; | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + var val = value / map[unit.toLowerCase()]; | ||
| 113 | + var str = val.toFixed(decimalPlaces); | ||
| 114 | + | ||
| 115 | + if (!fixedDecimals) { | ||
| 116 | + str = str.replace(formatDecimalsRegExp, '$1'); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + if (thousandsSeparator) { | ||
| 120 | + str = str.replace(formatThousandsRegExp, thousandsSeparator); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + return str + unitSeparator + unit; | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +/** | ||
| 127 | + * Parse the string value into an integer in bytes. | ||
| 128 | + * | ||
| 129 | + * If no unit is given, it is assumed the value is in bytes. | ||
| 130 | + * | ||
| 131 | + * @param {number|string} val | ||
| 132 | + * | ||
| 133 | + * @returns {number|null} | ||
| 134 | + * @public | ||
| 135 | + */ | ||
| 136 | + | ||
| 137 | +function parse(val) { | ||
| 138 | + if (typeof val === 'number' && !isNaN(val)) { | ||
| 139 | + return val; | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + if (typeof val !== 'string') { | ||
| 143 | + return null; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + // Test if the string passed is valid | ||
| 147 | + var results = parseRegExp.exec(val); | ||
| 148 | + var floatValue; | ||
| 149 | + var unit = 'b'; | ||
| 150 | + | ||
| 151 | + if (!results) { | ||
| 152 | + // Nothing could be extracted from the given string | ||
| 153 | + floatValue = parseInt(val, 10); | ||
| 154 | + unit = 'b' | ||
| 155 | + } else { | ||
| 156 | + // Retrieve the value and the unit | ||
| 157 | + floatValue = parseFloat(results[1]); | ||
| 158 | + unit = results[4].toLowerCase(); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + return Math.floor(map[unit] * floatValue); | ||
| 162 | +} |
| 1 | +{ | ||
| 2 | + "_from": "bytes@3.1.0", | ||
| 3 | + "_id": "bytes@3.1.0", | ||
| 4 | + "_inBundle": false, | ||
| 5 | + "_integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", | ||
| 6 | + "_location": "/bytes", | ||
| 7 | + "_phantomChildren": {}, | ||
| 8 | + "_requested": { | ||
| 9 | + "type": "version", | ||
| 10 | + "registry": true, | ||
| 11 | + "raw": "bytes@3.1.0", | ||
| 12 | + "name": "bytes", | ||
| 13 | + "escapedName": "bytes", | ||
| 14 | + "rawSpec": "3.1.0", | ||
| 15 | + "saveSpec": null, | ||
| 16 | + "fetchSpec": "3.1.0" | ||
| 17 | + }, | ||
| 18 | + "_requiredBy": [ | ||
| 19 | + "/body-parser", | ||
| 20 | + "/raw-body" | ||
| 21 | + ], | ||
| 22 | + "_resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", | ||
| 23 | + "_shasum": "f6cf7933a360e0588fa9fde85651cdc7f805d1f6", | ||
| 24 | + "_spec": "bytes@3.1.0", | ||
| 25 | + "_where": "C:\\Users\\SIMBA\\Desktop\\SpotifyPlaylistExport-master\\node_modules\\body-parser", | ||
| 26 | + "author": { | ||
| 27 | + "name": "TJ Holowaychuk", | ||
| 28 | + "email": "tj@vision-media.ca", | ||
| 29 | + "url": "http://tjholowaychuk.com" | ||
| 30 | + }, | ||
| 31 | + "bugs": { | ||
| 32 | + "url": "https://github.com/visionmedia/bytes.js/issues" | ||
| 33 | + }, | ||
| 34 | + "bundleDependencies": false, | ||
| 35 | + "contributors": [ | ||
| 36 | + { | ||
| 37 | + "name": "Jed Watson", | ||
| 38 | + "email": "jed.watson@me.com" | ||
| 39 | + }, | ||
| 40 | + { | ||
| 41 | + "name": "Théo FIDRY", | ||
| 42 | + "email": "theo.fidry@gmail.com" | ||
| 43 | + } | ||
| 44 | + ], | ||
| 45 | + "deprecated": false, | ||
| 46 | + "description": "Utility to parse a string bytes to bytes and vice-versa", | ||
| 47 | + "devDependencies": { | ||
| 48 | + "eslint": "5.12.1", | ||
| 49 | + "mocha": "5.2.0", | ||
| 50 | + "nyc": "13.1.0" | ||
| 51 | + }, | ||
| 52 | + "engines": { | ||
| 53 | + "node": ">= 0.8" | ||
| 54 | + }, | ||
| 55 | + "files": [ | ||
| 56 | + "History.md", | ||
| 57 | + "LICENSE", | ||
| 58 | + "Readme.md", | ||
| 59 | + "index.js" | ||
| 60 | + ], | ||
| 61 | + "homepage": "https://github.com/visionmedia/bytes.js#readme", | ||
| 62 | + "keywords": [ | ||
| 63 | + "byte", | ||
| 64 | + "bytes", | ||
| 65 | + "utility", | ||
| 66 | + "parse", | ||
| 67 | + "parser", | ||
| 68 | + "convert", | ||
| 69 | + "converter" | ||
| 70 | + ], | ||
| 71 | + "license": "MIT", | ||
| 72 | + "name": "bytes", | ||
| 73 | + "repository": { | ||
| 74 | + "type": "git", | ||
| 75 | + "url": "git+https://github.com/visionmedia/bytes.js.git" | ||
| 76 | + }, | ||
| 77 | + "scripts": { | ||
| 78 | + "lint": "eslint .", | ||
| 79 | + "test": "mocha --check-leaks --reporter spec", | ||
| 80 | + "test-ci": "nyc --reporter=text npm test", | ||
| 81 | + "test-cov": "nyc --reporter=html --reporter=text npm test" | ||
| 82 | + }, | ||
| 83 | + "version": "3.1.0" | ||
| 84 | +} |
| 1 | +coverage/ |
| 1 | +# These are supported funding model platforms | ||
| 2 | + | ||
| 3 | +github: [ljharb] | ||
| 4 | +patreon: # Replace with a single Patreon username | ||
| 5 | +open_collective: # Replace with a single Open Collective username | ||
| 6 | +ko_fi: # Replace with a single Ko-fi username | ||
| 7 | +tidelift: npm/call-bind | ||
| 8 | +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry | ||
| 9 | +liberapay: # Replace with a single Liberapay username | ||
| 10 | +issuehunt: # Replace with a single IssueHunt username | ||
| 11 | +otechie: # Replace with a single Otechie username | ||
| 12 | +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] |
| 1 | +# Changelog | ||
| 2 | + | ||
| 3 | +All notable changes to this project will be documented in this file. | ||
| 4 | + | ||
| 5 | +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) | ||
| 6 | +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
| 7 | + | ||
| 8 | +## [v1.0.2](https://github.com/ljharb/call-bind/compare/v1.0.1...v1.0.2) - 2021-01-11 | ||
| 9 | + | ||
| 10 | +### Commits | ||
| 11 | + | ||
| 12 | +- [Fix] properly include the receiver in the bound length [`dbae7bc`](https://github.com/ljharb/call-bind/commit/dbae7bc676c079a0d33c0a43e9ef92cb7b01345d) | ||
| 13 | + | ||
| 14 | +## [v1.0.1](https://github.com/ljharb/call-bind/compare/v1.0.0...v1.0.1) - 2021-01-08 | ||
| 15 | + | ||
| 16 | +### Commits | ||
| 17 | + | ||
| 18 | +- [Tests] migrate tests to Github Actions [`b6db284`](https://github.com/ljharb/call-bind/commit/b6db284c36f8ccd195b88a6764fe84b7223a0da1) | ||
| 19 | +- [meta] do not publish github action workflow files [`ec7fe46`](https://github.com/ljharb/call-bind/commit/ec7fe46e60cfa4764ee943d2755f5e5a366e578e) | ||
| 20 | +- [Fix] preserve original function’s length when possible [`adbceaa`](https://github.com/ljharb/call-bind/commit/adbceaa3cac4b41ea78bb19d7ccdbaaf7e0bdadb) | ||
| 21 | +- [Tests] gather coverage data on every job [`d69e23c`](https://github.com/ljharb/call-bind/commit/d69e23cc65f101ba1d4c19bb07fa8eb0ec624be8) | ||
| 22 | +- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `tape` [`2fd3586`](https://github.com/ljharb/call-bind/commit/2fd3586c5d47b335364c14293114c6b625ae1f71) | ||
| 23 | +- [Deps] update `get-intrinsic` [`f23e931`](https://github.com/ljharb/call-bind/commit/f23e9318cc271c2add8bb38cfded85ee7baf8eee) | ||
| 24 | +- [Deps] update `get-intrinsic` [`72d9f44`](https://github.com/ljharb/call-bind/commit/72d9f44e184465ba8dd3fb48260bbcff234985f2) | ||
| 25 | +- [meta] fix FUNDING.yml [`e723573`](https://github.com/ljharb/call-bind/commit/e723573438c5a68dcec31fb5d96ea6b7e4a93be8) | ||
| 26 | +- [eslint] ignore coverage output [`15e76d2`](https://github.com/ljharb/call-bind/commit/15e76d28a5f43e504696401e5b31ebb78ee1b532) | ||
| 27 | +- [meta] add Automatic Rebase and Require Allow Edits workflows [`8fa4dab`](https://github.com/ljharb/call-bind/commit/8fa4dabb23ba3dd7bb92c9571c1241c08b56e4b6) | ||
| 28 | + | ||
| 29 | +## v1.0.0 - 2020-10-30 | ||
| 30 | + | ||
| 31 | +### Commits | ||
| 32 | + | ||
| 33 | +- Initial commit [`306cf98`](https://github.com/ljharb/call-bind/commit/306cf98c7ec9e7ef66b653ec152277ac1381eb50) | ||
| 34 | +- Tests [`e10d0bb`](https://github.com/ljharb/call-bind/commit/e10d0bbdadc7a10ecedc9a1c035112d3e368b8df) | ||
| 35 | +- Implementation [`43852ed`](https://github.com/ljharb/call-bind/commit/43852eda0f187327b7fad2423ca972149a52bd65) | ||
| 36 | +- npm init [`408f860`](https://github.com/ljharb/call-bind/commit/408f860b773a2f610805fd3613d0d71bac1b6249) | ||
| 37 | +- [meta] add Automatic Rebase and Require Allow Edits workflows [`fb349b2`](https://github.com/ljharb/call-bind/commit/fb349b2e48defbec8b5ec8a8395cc8f69f220b13) | ||
| 38 | +- [meta] add `auto-changelog` [`c4001fc`](https://github.com/ljharb/call-bind/commit/c4001fc43031799ef908211c98d3b0fb2b60fde4) | ||
| 39 | +- [meta] add "funding"; create `FUNDING.yml` [`d4d6d29`](https://github.com/ljharb/call-bind/commit/d4d6d2974a14bc2e98830468eda7fe6d6a776717) | ||
| 40 | +- [Tests] add `npm run lint` [`dedfb98`](https://github.com/ljharb/call-bind/commit/dedfb98bd0ecefb08ddb9a94061bd10cde4332af) | ||
| 41 | +- Only apps should have lockfiles [`54ac776`](https://github.com/ljharb/call-bind/commit/54ac77653db45a7361dc153d2f478e743f110650) | ||
| 42 | +- [meta] add `safe-publish-latest` [`9ea8e43`](https://github.com/ljharb/call-bind/commit/9ea8e435b950ce9b705559cd651039f9bf40140f) |
| 1 | +MIT License | ||
| 2 | + | ||
| 3 | +Copyright (c) 2020 Jordan Harband | ||
| 4 | + | ||
| 5 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | +of this software and associated documentation files (the "Software"), to deal | ||
| 7 | +in the Software without restriction, including without limitation the rights | ||
| 8 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | +copies of the Software, and to permit persons to whom the Software is | ||
| 10 | +furnished to do so, subject to the following conditions: | ||
| 11 | + | ||
| 12 | +The above copyright notice and this permission notice shall be included in all | ||
| 13 | +copies or substantial portions of the Software. | ||
| 14 | + | ||
| 15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | +SOFTWARE. |
| 1 | +'use strict'; | ||
| 2 | + | ||
| 3 | +var GetIntrinsic = require('get-intrinsic'); | ||
| 4 | + | ||
| 5 | +var callBind = require('./'); | ||
| 6 | + | ||
| 7 | +var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf')); | ||
| 8 | + | ||
| 9 | +module.exports = function callBoundIntrinsic(name, allowMissing) { | ||
| 10 | + var intrinsic = GetIntrinsic(name, !!allowMissing); | ||
| 11 | + if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) { | ||
| 12 | + return callBind(intrinsic); | ||
| 13 | + } | ||
| 14 | + return intrinsic; | ||
| 15 | +}; |
| 1 | +'use strict'; | ||
| 2 | + | ||
| 3 | +var bind = require('function-bind'); | ||
| 4 | +var GetIntrinsic = require('get-intrinsic'); | ||
| 5 | + | ||
| 6 | +var $apply = GetIntrinsic('%Function.prototype.apply%'); | ||
| 7 | +var $call = GetIntrinsic('%Function.prototype.call%'); | ||
| 8 | +var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply); | ||
| 9 | + | ||
| 10 | +var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true); | ||
| 11 | +var $defineProperty = GetIntrinsic('%Object.defineProperty%', true); | ||
| 12 | +var $max = GetIntrinsic('%Math.max%'); | ||
| 13 | + | ||
| 14 | +if ($defineProperty) { | ||
| 15 | + try { | ||
| 16 | + $defineProperty({}, 'a', { value: 1 }); | ||
| 17 | + } catch (e) { | ||
| 18 | + // IE 8 has a broken defineProperty | ||
| 19 | + $defineProperty = null; | ||
| 20 | + } | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +module.exports = function callBind(originalFunction) { | ||
| 24 | + var func = $reflectApply(bind, $call, arguments); | ||
| 25 | + if ($gOPD && $defineProperty) { | ||
| 26 | + var desc = $gOPD(func, 'length'); | ||
| 27 | + if (desc.configurable) { | ||
| 28 | + // original length, plus the receiver, minus any additional arguments (after the receiver) | ||
| 29 | + $defineProperty( | ||
| 30 | + func, | ||
| 31 | + 'length', | ||
| 32 | + { value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) } | ||
| 33 | + ); | ||
| 34 | + } | ||
| 35 | + } | ||
| 36 | + return func; | ||
| 37 | +}; | ||
| 38 | + | ||
| 39 | +var applyBind = function applyBind() { | ||
| 40 | + return $reflectApply(bind, $apply, arguments); | ||
| 41 | +}; | ||
| 42 | + | ||
| 43 | +if ($defineProperty) { | ||
| 44 | + $defineProperty(module.exports, 'apply', { value: applyBind }); | ||
| 45 | +} else { | ||
| 46 | + module.exports.apply = applyBind; | ||
| 47 | +} |
| 1 | +{ | ||
| 2 | + "_from": "call-bind@^1.0.0", | ||
| 3 | + "_id": "call-bind@1.0.2", | ||
| 4 | + "_inBundle": false, | ||
| 5 | + "_integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", | ||
| 6 | + "_location": "/call-bind", | ||
| 7 | + "_phantomChildren": {}, | ||
| 8 | + "_requested": { | ||
| 9 | + "type": "range", | ||
| 10 | + "registry": true, | ||
| 11 | + "raw": "call-bind@^1.0.0", | ||
| 12 | + "name": "call-bind", | ||
| 13 | + "escapedName": "call-bind", | ||
| 14 | + "rawSpec": "^1.0.0", | ||
| 15 | + "saveSpec": null, | ||
| 16 | + "fetchSpec": "^1.0.0" | ||
| 17 | + }, | ||
| 18 | + "_requiredBy": [ | ||
| 19 | + "/side-channel" | ||
| 20 | + ], | ||
| 21 | + "_resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", | ||
| 22 | + "_shasum": "b1d4e89e688119c3c9a903ad30abb2f6a919be3c", | ||
| 23 | + "_spec": "call-bind@^1.0.0", | ||
| 24 | + "_where": "C:\\Users\\SIMBA\\Desktop\\SpotifyPlaylistExport-master\\node_modules\\side-channel", | ||
| 25 | + "author": { | ||
| 26 | + "name": "Jordan Harband", | ||
| 27 | + "email": "ljharb@gmail.com" | ||
| 28 | + }, | ||
| 29 | + "auto-changelog": { | ||
| 30 | + "output": "CHANGELOG.md", | ||
| 31 | + "template": "keepachangelog", | ||
| 32 | + "unreleased": false, | ||
| 33 | + "commitLimit": false, | ||
| 34 | + "backfillLimit": false, | ||
| 35 | + "hideCredit": true | ||
| 36 | + }, | ||
| 37 | + "bugs": { | ||
| 38 | + "url": "https://github.com/ljharb/call-bind/issues" | ||
| 39 | + }, | ||
| 40 | + "bundleDependencies": false, | ||
| 41 | + "dependencies": { | ||
| 42 | + "function-bind": "^1.1.1", | ||
| 43 | + "get-intrinsic": "^1.0.2" | ||
| 44 | + }, | ||
| 45 | + "deprecated": false, | ||
| 46 | + "description": "Robustly `.call.bind()` a function", | ||
| 47 | + "devDependencies": { | ||
| 48 | + "@ljharb/eslint-config": "^17.3.0", | ||
| 49 | + "aud": "^1.1.3", | ||
| 50 | + "auto-changelog": "^2.2.1", | ||
| 51 | + "eslint": "^7.17.0", | ||
| 52 | + "nyc": "^10.3.2", | ||
| 53 | + "safe-publish-latest": "^1.1.4", | ||
| 54 | + "tape": "^5.1.1" | ||
| 55 | + }, | ||
| 56 | + "exports": { | ||
| 57 | + ".": [ | ||
| 58 | + { | ||
| 59 | + "default": "./index.js" | ||
| 60 | + }, | ||
| 61 | + "./index.js" | ||
| 62 | + ], | ||
| 63 | + "./callBound": [ | ||
| 64 | + { | ||
| 65 | + "default": "./callBound.js" | ||
| 66 | + }, | ||
| 67 | + "./callBound.js" | ||
| 68 | + ], | ||
| 69 | + "./package.json": "./package.json" | ||
| 70 | + }, | ||
| 71 | + "funding": { | ||
| 72 | + "url": "https://github.com/sponsors/ljharb" | ||
| 73 | + }, | ||
| 74 | + "homepage": "https://github.com/ljharb/call-bind#readme", | ||
| 75 | + "keywords": [ | ||
| 76 | + "javascript", | ||
| 77 | + "ecmascript", | ||
| 78 | + "es", | ||
| 79 | + "js", | ||
| 80 | + "callbind", | ||
| 81 | + "callbound", | ||
| 82 | + "call", | ||
| 83 | + "bind", | ||
| 84 | + "bound", | ||
| 85 | + "call-bind", | ||
| 86 | + "call-bound", | ||
| 87 | + "function", | ||
| 88 | + "es-abstract" | ||
| 89 | + ], | ||
| 90 | + "license": "MIT", | ||
| 91 | + "main": "index.js", | ||
| 92 | + "name": "call-bind", | ||
| 93 | + "repository": { | ||
| 94 | + "type": "git", | ||
| 95 | + "url": "git+https://github.com/ljharb/call-bind.git" | ||
| 96 | + }, | ||
| 97 | + "scripts": { | ||
| 98 | + "lint": "eslint --ext=.js,.mjs .", | ||
| 99 | + "posttest": "aud --production", | ||
| 100 | + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"", | ||
| 101 | + "prepublish": "safe-publish-latest", | ||
| 102 | + "pretest": "npm run lint", | ||
| 103 | + "test": "npm run tests-only", | ||
| 104 | + "tests-only": "nyc tape 'test/*'", | ||
| 105 | + "version": "auto-changelog && git add CHANGELOG.md" | ||
| 106 | + }, | ||
| 107 | + "version": "1.0.2" | ||
| 108 | +} |
| 1 | +'use strict'; | ||
| 2 | + | ||
| 3 | +var test = require('tape'); | ||
| 4 | + | ||
| 5 | +var callBound = require('../callBound'); | ||
| 6 | + | ||
| 7 | +test('callBound', function (t) { | ||
| 8 | + // static primitive | ||
| 9 | + t.equal(callBound('Array.length'), Array.length, 'Array.length yields itself'); | ||
| 10 | + t.equal(callBound('%Array.length%'), Array.length, '%Array.length% yields itself'); | ||
| 11 | + | ||
| 12 | + // static non-function object | ||
| 13 | + t.equal(callBound('Array.prototype'), Array.prototype, 'Array.prototype yields itself'); | ||
| 14 | + t.equal(callBound('%Array.prototype%'), Array.prototype, '%Array.prototype% yields itself'); | ||
| 15 | + t.equal(callBound('Array.constructor'), Array.constructor, 'Array.constructor yields itself'); | ||
| 16 | + t.equal(callBound('%Array.constructor%'), Array.constructor, '%Array.constructor% yields itself'); | ||
| 17 | + | ||
| 18 | + // static function | ||
| 19 | + t.equal(callBound('Date.parse'), Date.parse, 'Date.parse yields itself'); | ||
| 20 | + t.equal(callBound('%Date.parse%'), Date.parse, '%Date.parse% yields itself'); | ||
| 21 | + | ||
| 22 | + // prototype primitive | ||
| 23 | + t.equal(callBound('Error.prototype.message'), Error.prototype.message, 'Error.prototype.message yields itself'); | ||
| 24 | + t.equal(callBound('%Error.prototype.message%'), Error.prototype.message, '%Error.prototype.message% yields itself'); | ||
| 25 | + | ||
| 26 | + // prototype function | ||
| 27 | + t.notEqual(callBound('Object.prototype.toString'), Object.prototype.toString, 'Object.prototype.toString does not yield itself'); | ||
| 28 | + t.notEqual(callBound('%Object.prototype.toString%'), Object.prototype.toString, '%Object.prototype.toString% does not yield itself'); | ||
| 29 | + t.equal(callBound('Object.prototype.toString')(true), Object.prototype.toString.call(true), 'call-bound Object.prototype.toString calls into the original'); | ||
| 30 | + t.equal(callBound('%Object.prototype.toString%')(true), Object.prototype.toString.call(true), 'call-bound %Object.prototype.toString% calls into the original'); | ||
| 31 | + | ||
| 32 | + t['throws']( | ||
| 33 | + function () { callBound('does not exist'); }, | ||
| 34 | + SyntaxError, | ||
| 35 | + 'nonexistent intrinsic throws' | ||
| 36 | + ); | ||
| 37 | + t['throws']( | ||
| 38 | + function () { callBound('does not exist', true); }, | ||
| 39 | + SyntaxError, | ||
| 40 | + 'allowMissing arg still throws for unknown intrinsic' | ||
| 41 | + ); | ||
| 42 | + | ||
| 43 | + /* globals WeakRef: false */ | ||
| 44 | + t.test('real but absent intrinsic', { skip: typeof WeakRef !== 'undefined' }, function (st) { | ||
| 45 | + st['throws']( | ||
| 46 | + function () { callBound('WeakRef'); }, | ||
| 47 | + TypeError, | ||
| 48 | + 'real but absent intrinsic throws' | ||
| 49 | + ); | ||
| 50 | + st.equal(callBound('WeakRef', true), undefined, 'allowMissing arg avoids exception'); | ||
| 51 | + st.end(); | ||
| 52 | + }); | ||
| 53 | + | ||
| 54 | + t.end(); | ||
| 55 | +}); |
| 1 | +'use strict'; | ||
| 2 | + | ||
| 3 | +var callBind = require('../'); | ||
| 4 | +var bind = require('function-bind'); | ||
| 5 | + | ||
| 6 | +var test = require('tape'); | ||
| 7 | + | ||
| 8 | +/* | ||
| 9 | + * older engines have length nonconfigurable | ||
| 10 | + * in io.js v3, it is configurable except on bound functions, hence the .bind() | ||
| 11 | + */ | ||
| 12 | +var functionsHaveConfigurableLengths = !!( | ||
| 13 | + Object.getOwnPropertyDescriptor | ||
| 14 | + && Object.getOwnPropertyDescriptor(bind.call(function () {}), 'length').configurable | ||
| 15 | +); | ||
| 16 | + | ||
| 17 | +test('callBind', function (t) { | ||
| 18 | + var sentinel = { sentinel: true }; | ||
| 19 | + var func = function (a, b) { | ||
| 20 | + // eslint-disable-next-line no-invalid-this | ||
| 21 | + return [this, a, b]; | ||
| 22 | + }; | ||
| 23 | + t.equal(func.length, 2, 'original function length is 2'); | ||
| 24 | + t.deepEqual(func(), [undefined, undefined, undefined], 'unbound func with too few args'); | ||
| 25 | + t.deepEqual(func(1, 2), [undefined, 1, 2], 'unbound func with right args'); | ||
| 26 | + t.deepEqual(func(1, 2, 3), [undefined, 1, 2], 'unbound func with too many args'); | ||
| 27 | + | ||
| 28 | + var bound = callBind(func); | ||
| 29 | + t.equal(bound.length, func.length + 1, 'function length is preserved', { skip: !functionsHaveConfigurableLengths }); | ||
| 30 | + t.deepEqual(bound(), [undefined, undefined, undefined], 'bound func with too few args'); | ||
| 31 | + t.deepEqual(bound(1, 2), [1, 2, undefined], 'bound func with right args'); | ||
| 32 | + t.deepEqual(bound(1, 2, 3), [1, 2, 3], 'bound func with too many args'); | ||
| 33 | + | ||
| 34 | + var boundR = callBind(func, sentinel); | ||
| 35 | + t.equal(boundR.length, func.length, 'function length is preserved', { skip: !functionsHaveConfigurableLengths }); | ||
| 36 | + t.deepEqual(boundR(), [sentinel, undefined, undefined], 'bound func with receiver, with too few args'); | ||
| 37 | + t.deepEqual(boundR(1, 2), [sentinel, 1, 2], 'bound func with receiver, with right args'); | ||
| 38 | + t.deepEqual(boundR(1, 2, 3), [sentinel, 1, 2], 'bound func with receiver, with too many args'); | ||
| 39 | + | ||
| 40 | + var boundArg = callBind(func, sentinel, 1); | ||
| 41 | + t.equal(boundArg.length, func.length - 1, 'function length is preserved', { skip: !functionsHaveConfigurableLengths }); | ||
| 42 | + t.deepEqual(boundArg(), [sentinel, 1, undefined], 'bound func with receiver and arg, with too few args'); | ||
| 43 | + t.deepEqual(boundArg(2), [sentinel, 1, 2], 'bound func with receiver and arg, with right arg'); | ||
| 44 | + t.deepEqual(boundArg(2, 3), [sentinel, 1, 2], 'bound func with receiver and arg, with too many args'); | ||
| 45 | + | ||
| 46 | + t.test('callBind.apply', function (st) { | ||
| 47 | + var aBound = callBind.apply(func); | ||
| 48 | + st.deepEqual(aBound(sentinel), [sentinel, undefined, undefined], 'apply-bound func with no args'); | ||
| 49 | + st.deepEqual(aBound(sentinel, [1], 4), [sentinel, 1, undefined], 'apply-bound func with too few args'); | ||
| 50 | + st.deepEqual(aBound(sentinel, [1, 2], 4), [sentinel, 1, 2], 'apply-bound func with right args'); | ||
| 51 | + | ||
| 52 | + var aBoundArg = callBind.apply(func); | ||
| 53 | + st.deepEqual(aBoundArg(sentinel, [1, 2, 3], 4), [sentinel, 1, 2], 'apply-bound func with too many args'); | ||
| 54 | + st.deepEqual(aBoundArg(sentinel, [1, 2], 4), [sentinel, 1, 2], 'apply-bound func with right args'); | ||
| 55 | + st.deepEqual(aBoundArg(sentinel, [1], 4), [sentinel, 1, undefined], 'apply-bound func with too few args'); | ||
| 56 | + | ||
| 57 | + var aBoundR = callBind.apply(func, sentinel); | ||
| 58 | + st.deepEqual(aBoundR([1, 2, 3], 4), [sentinel, 1, 2], 'apply-bound func with receiver and too many args'); | ||
| 59 | + st.deepEqual(aBoundR([1, 2], 4), [sentinel, 1, 2], 'apply-bound func with receiver and right args'); | ||
| 60 | + st.deepEqual(aBoundR([1], 4), [sentinel, 1, undefined], 'apply-bound func with receiver and too few args'); | ||
| 61 | + | ||
| 62 | + st.end(); | ||
| 63 | + }); | ||
| 64 | + | ||
| 65 | + t.end(); | ||
| 66 | +}); |
| 1 | +Copyright (c) 2011 Debuggable Limited <felix@debuggable.com> | ||
| 2 | + | ||
| 3 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 4 | +of this software and associated documentation files (the "Software"), to deal | ||
| 5 | +in the Software without restriction, including without limitation the rights | ||
| 6 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 7 | +copies of the Software, and to permit persons to whom the Software is | ||
| 8 | +furnished to do so, subject to the following conditions: | ||
| 9 | + | ||
| 10 | +The above copyright notice and this permission notice shall be included in | ||
| 11 | +all copies or substantial portions of the Software. | ||
| 12 | + | ||
| 13 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 14 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 15 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 16 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 17 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 18 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 19 | +THE SOFTWARE. |
| 1 | +# combined-stream | ||
| 2 | + | ||
| 3 | +A stream that emits multiple other streams one after another. | ||
| 4 | + | ||
| 5 | +**NB** Currently `combined-stream` works with streams version 1 only. There is ongoing effort to switch this library to streams version 2. Any help is welcome. :) Meanwhile you can explore other libraries that provide streams2 support with more or less compatibility with `combined-stream`. | ||
| 6 | + | ||
| 7 | +- [combined-stream2](https://www.npmjs.com/package/combined-stream2): A drop-in streams2-compatible replacement for the combined-stream module. | ||
| 8 | + | ||
| 9 | +- [multistream](https://www.npmjs.com/package/multistream): A stream that emits multiple other streams one after another. | ||
| 10 | + | ||
| 11 | +## Installation | ||
| 12 | + | ||
| 13 | +``` bash | ||
| 14 | +npm install combined-stream | ||
| 15 | +``` | ||
| 16 | + | ||
| 17 | +## Usage | ||
| 18 | + | ||
| 19 | +Here is a simple example that shows how you can use combined-stream to combine | ||
| 20 | +two files into one: | ||
| 21 | + | ||
| 22 | +``` javascript | ||
| 23 | +var CombinedStream = require('combined-stream'); | ||
| 24 | +var fs = require('fs'); | ||
| 25 | + | ||
| 26 | +var combinedStream = CombinedStream.create(); | ||
| 27 | +combinedStream.append(fs.createReadStream('file1.txt')); | ||
| 28 | +combinedStream.append(fs.createReadStream('file2.txt')); | ||
| 29 | + | ||
| 30 | +combinedStream.pipe(fs.createWriteStream('combined.txt')); | ||
| 31 | +``` | ||
| 32 | + | ||
| 33 | +While the example above works great, it will pause all source streams until | ||
| 34 | +they are needed. If you don't want that to happen, you can set `pauseStreams` | ||
| 35 | +to `false`: | ||
| 36 | + | ||
| 37 | +``` javascript | ||
| 38 | +var CombinedStream = require('combined-stream'); | ||
| 39 | +var fs = require('fs'); | ||
| 40 | + | ||
| 41 | +var combinedStream = CombinedStream.create({pauseStreams: false}); | ||
| 42 | +combinedStream.append(fs.createReadStream('file1.txt')); | ||
| 43 | +combinedStream.append(fs.createReadStream('file2.txt')); | ||
| 44 | + | ||
| 45 | +combinedStream.pipe(fs.createWriteStream('combined.txt')); | ||
| 46 | +``` | ||
| 47 | + | ||
| 48 | +However, what if you don't have all the source streams yet, or you don't want | ||
| 49 | +to allocate the resources (file descriptors, memory, etc.) for them right away? | ||
| 50 | +Well, in that case you can simply provide a callback that supplies the stream | ||
| 51 | +by calling a `next()` function: | ||
| 52 | + | ||
| 53 | +``` javascript | ||
| 54 | +var CombinedStream = require('combined-stream'); | ||
| 55 | +var fs = require('fs'); | ||
| 56 | + | ||
| 57 | +var combinedStream = CombinedStream.create(); | ||
| 58 | +combinedStream.append(function(next) { | ||
| 59 | + next(fs.createReadStream('file1.txt')); | ||
| 60 | +}); | ||
| 61 | +combinedStream.append(function(next) { | ||
| 62 | + next(fs.createReadStream('file2.txt')); | ||
| 63 | +}); | ||
| 64 | + | ||
| 65 | +combinedStream.pipe(fs.createWriteStream('combined.txt')); | ||
| 66 | +``` | ||
| 67 | + | ||
| 68 | +## API | ||
| 69 | + | ||
| 70 | +### CombinedStream.create([options]) | ||
| 71 | + | ||
| 72 | +Returns a new combined stream object. Available options are: | ||
| 73 | + | ||
| 74 | +* `maxDataSize` | ||
| 75 | +* `pauseStreams` | ||
| 76 | + | ||
| 77 | +The effect of those options is described below. | ||
| 78 | + | ||
| 79 | +### combinedStream.pauseStreams = `true` | ||
| 80 | + | ||
| 81 | +Whether to apply back pressure to the underlaying streams. If set to `false`, | ||
| 82 | +the underlaying streams will never be paused. If set to `true`, the | ||
| 83 | +underlaying streams will be paused right after being appended, as well as when | ||
| 84 | +`delayedStream.pipe()` wants to throttle. | ||
| 85 | + | ||
| 86 | +### combinedStream.maxDataSize = `2 * 1024 * 1024` | ||
| 87 | + | ||
| 88 | +The maximum amount of bytes (or characters) to buffer for all source streams. | ||
| 89 | +If this value is exceeded, `combinedStream` emits an `'error'` event. | ||
| 90 | + | ||
| 91 | +### combinedStream.dataSize = `0` | ||
| 92 | + | ||
| 93 | +The amount of bytes (or characters) currently buffered by `combinedStream`. | ||
| 94 | + | ||
| 95 | +### combinedStream.append(stream) | ||
| 96 | + | ||
| 97 | +Appends the given `stream` to the combinedStream object. If `pauseStreams` is | ||
| 98 | +set to `true, this stream will also be paused right away. | ||
| 99 | + | ||
| 100 | +`streams` can also be a function that takes one parameter called `next`. `next` | ||
| 101 | +is a function that must be invoked in order to provide the `next` stream, see | ||
| 102 | +example above. | ||
| 103 | + | ||
| 104 | +Regardless of how the `stream` is appended, combined-stream always attaches an | ||
| 105 | +`'error'` listener to it, so you don't have to do that manually. | ||
| 106 | + | ||
| 107 | +Special case: `stream` can also be a String or Buffer. | ||
| 108 | + | ||
| 109 | +### combinedStream.write(data) | ||
| 110 | + | ||
| 111 | +You should not call this, `combinedStream` takes care of piping the appended | ||
| 112 | +streams into itself for you. | ||
| 113 | + | ||
| 114 | +### combinedStream.resume() | ||
| 115 | + | ||
| 116 | +Causes `combinedStream` to start drain the streams it manages. The function is | ||
| 117 | +idempotent, and also emits a `'resume'` event each time which usually goes to | ||
| 118 | +the stream that is currently being drained. | ||
| 119 | + | ||
| 120 | +### combinedStream.pause(); | ||
| 121 | + | ||
| 122 | +If `combinedStream.pauseStreams` is set to `false`, this does nothing. | ||
| 123 | +Otherwise a `'pause'` event is emitted, this goes to the stream that is | ||
| 124 | +currently being drained, so you can use it to apply back pressure. | ||
| 125 | + | ||
| 126 | +### combinedStream.end(); | ||
| 127 | + | ||
| 128 | +Sets `combinedStream.writable` to false, emits an `'end'` event, and removes | ||
| 129 | +all streams from the queue. | ||
| 130 | + | ||
| 131 | +### combinedStream.destroy(); | ||
| 132 | + | ||
| 133 | +Same as `combinedStream.end()`, except it emits a `'close'` event instead of | ||
| 134 | +`'end'`. | ||
| 135 | + | ||
| 136 | +## License | ||
| 137 | + | ||
| 138 | +combined-stream is licensed under the MIT license. |
| 1 | +var util = require('util'); | ||
| 2 | +var Stream = require('stream').Stream; | ||
| 3 | +var DelayedStream = require('delayed-stream'); | ||
| 4 | + | ||
| 5 | +module.exports = CombinedStream; | ||
| 6 | +function CombinedStream() { | ||
| 7 | + this.writable = false; | ||
| 8 | + this.readable = true; | ||
| 9 | + this.dataSize = 0; | ||
| 10 | + this.maxDataSize = 2 * 1024 * 1024; | ||
| 11 | + this.pauseStreams = true; | ||
| 12 | + | ||
| 13 | + this._released = false; | ||
| 14 | + this._streams = []; | ||
| 15 | + this._currentStream = null; | ||
| 16 | + this._insideLoop = false; | ||
| 17 | + this._pendingNext = false; | ||
| 18 | +} | ||
| 19 | +util.inherits(CombinedStream, Stream); | ||
| 20 | + | ||
| 21 | +CombinedStream.create = function(options) { | ||
| 22 | + var combinedStream = new this(); | ||
| 23 | + | ||
| 24 | + options = options || {}; | ||
| 25 | + for (var option in options) { | ||
| 26 | + combinedStream[option] = options[option]; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + return combinedStream; | ||
| 30 | +}; | ||
| 31 | + | ||
| 32 | +CombinedStream.isStreamLike = function(stream) { | ||
| 33 | + return (typeof stream !== 'function') | ||
| 34 | + && (typeof stream !== 'string') | ||
| 35 | + && (typeof stream !== 'boolean') | ||
| 36 | + && (typeof stream !== 'number') | ||
| 37 | + && (!Buffer.isBuffer(stream)); | ||
| 38 | +}; | ||
| 39 | + | ||
| 40 | +CombinedStream.prototype.append = function(stream) { | ||
| 41 | + var isStreamLike = CombinedStream.isStreamLike(stream); | ||
| 42 | + | ||
| 43 | + if (isStreamLike) { | ||
| 44 | + if (!(stream instanceof DelayedStream)) { | ||
| 45 | + var newStream = DelayedStream.create(stream, { | ||
| 46 | + maxDataSize: Infinity, | ||
| 47 | + pauseStream: this.pauseStreams, | ||
| 48 | + }); | ||
| 49 | + stream.on('data', this._checkDataSize.bind(this)); | ||
| 50 | + stream = newStream; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + this._handleErrors(stream); | ||
| 54 | + | ||
| 55 | + if (this.pauseStreams) { | ||
| 56 | + stream.pause(); | ||
| 57 | + } | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + this._streams.push(stream); | ||
| 61 | + return this; | ||
| 62 | +}; | ||
| 63 | + | ||
| 64 | +CombinedStream.prototype.pipe = function(dest, options) { | ||
| 65 | + Stream.prototype.pipe.call(this, dest, options); | ||
| 66 | + this.resume(); | ||
| 67 | + return dest; | ||
| 68 | +}; | ||
| 69 | + | ||
| 70 | +CombinedStream.prototype._getNext = function() { | ||
| 71 | + this._currentStream = null; | ||
| 72 | + | ||
| 73 | + if (this._insideLoop) { | ||
| 74 | + this._pendingNext = true; | ||
| 75 | + return; // defer call | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + this._insideLoop = true; | ||
| 79 | + try { | ||
| 80 | + do { | ||
| 81 | + this._pendingNext = false; | ||
| 82 | + this._realGetNext(); | ||
| 83 | + } while (this._pendingNext); | ||
| 84 | + } finally { | ||
| 85 | + this._insideLoop = false; | ||
| 86 | + } | ||
| 87 | +}; | ||
| 88 | + | ||
| 89 | +CombinedStream.prototype._realGetNext = function() { | ||
| 90 | + var stream = this._streams.shift(); | ||
| 91 | + | ||
| 92 | + | ||
| 93 | + if (typeof stream == 'undefined') { | ||
| 94 | + this.end(); | ||
| 95 | + return; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + if (typeof stream !== 'function') { | ||
| 99 | + this._pipeNext(stream); | ||
| 100 | + return; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + var getStream = stream; | ||
| 104 | + getStream(function(stream) { | ||
| 105 | + var isStreamLike = CombinedStream.isStreamLike(stream); | ||
| 106 | + if (isStreamLike) { | ||
| 107 | + stream.on('data', this._checkDataSize.bind(this)); | ||
| 108 | + this._handleErrors(stream); | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + this._pipeNext(stream); | ||
| 112 | + }.bind(this)); | ||
| 113 | +}; | ||
| 114 | + | ||
| 115 | +CombinedStream.prototype._pipeNext = function(stream) { | ||
| 116 | + this._currentStream = stream; | ||
| 117 | + | ||
| 118 | + var isStreamLike = CombinedStream.isStreamLike(stream); | ||
| 119 | + if (isStreamLike) { | ||
| 120 | + stream.on('end', this._getNext.bind(this)); | ||
| 121 | + stream.pipe(this, {end: false}); | ||
| 122 | + return; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + var value = stream; | ||
| 126 | + this.write(value); | ||
| 127 | + this._getNext(); | ||
| 128 | +}; | ||
| 129 | + | ||
| 130 | +CombinedStream.prototype._handleErrors = function(stream) { | ||
| 131 | + var self = this; | ||
| 132 | + stream.on('error', function(err) { | ||
| 133 | + self._emitError(err); | ||
| 134 | + }); | ||
| 135 | +}; | ||
| 136 | + | ||
| 137 | +CombinedStream.prototype.write = function(data) { | ||
| 138 | + this.emit('data', data); | ||
| 139 | +}; | ||
| 140 | + | ||
| 141 | +CombinedStream.prototype.pause = function() { | ||
| 142 | + if (!this.pauseStreams) { | ||
| 143 | + return; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.pause) == 'function') this._currentStream.pause(); | ||
| 147 | + this.emit('pause'); | ||
| 148 | +}; | ||
| 149 | + | ||
| 150 | +CombinedStream.prototype.resume = function() { | ||
| 151 | + if (!this._released) { | ||
| 152 | + this._released = true; | ||
| 153 | + this.writable = true; | ||
| 154 | + this._getNext(); | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.resume) == 'function') this._currentStream.resume(); | ||
| 158 | + this.emit('resume'); | ||
| 159 | +}; | ||
| 160 | + | ||
| 161 | +CombinedStream.prototype.end = function() { | ||
| 162 | + this._reset(); | ||
| 163 | + this.emit('end'); | ||
| 164 | +}; | ||
| 165 | + | ||
| 166 | +CombinedStream.prototype.destroy = function() { | ||
| 167 | + this._reset(); | ||
| 168 | + this.emit('close'); | ||
| 169 | +}; | ||
| 170 | + | ||
| 171 | +CombinedStream.prototype._reset = function() { | ||
| 172 | + this.writable = false; | ||
| 173 | + this._streams = []; | ||
| 174 | + this._currentStream = null; | ||
| 175 | +}; | ||
| 176 | + | ||
| 177 | +CombinedStream.prototype._checkDataSize = function() { | ||
| 178 | + this._updateDataSize(); | ||
| 179 | + if (this.dataSize <= this.maxDataSize) { | ||
| 180 | + return; | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + var message = | ||
| 184 | + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'; | ||
| 185 | + this._emitError(new Error(message)); | ||
| 186 | +}; | ||
| 187 | + | ||
| 188 | +CombinedStream.prototype._updateDataSize = function() { | ||
| 189 | + this.dataSize = 0; | ||
| 190 | + | ||
| 191 | + var self = this; | ||
| 192 | + this._streams.forEach(function(stream) { | ||
| 193 | + if (!stream.dataSize) { | ||
| 194 | + return; | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + self.dataSize += stream.dataSize; | ||
| 198 | + }); | ||
| 199 | + | ||
| 200 | + if (this._currentStream && this._currentStream.dataSize) { | ||
| 201 | + this.dataSize += this._currentStream.dataSize; | ||
| 202 | + } | ||
| 203 | +}; | ||
| 204 | + | ||
| 205 | +CombinedStream.prototype._emitError = function(err) { | ||
| 206 | + this._reset(); | ||
| 207 | + this.emit('error', err); | ||
| 208 | +}; |
| 1 | +{ | ||
| 2 | + "_from": "combined-stream@^1.0.8", | ||
| 3 | + "_id": "combined-stream@1.0.8", | ||
| 4 | + "_inBundle": false, | ||
| 5 | + "_integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", | ||
| 6 | + "_location": "/combined-stream", | ||
| 7 | + "_phantomChildren": {}, | ||
| 8 | + "_requested": { | ||
| 9 | + "type": "range", | ||
| 10 | + "registry": true, | ||
| 11 | + "raw": "combined-stream@^1.0.8", | ||
| 12 | + "name": "combined-stream", | ||
| 13 | + "escapedName": "combined-stream", | ||
| 14 | + "rawSpec": "^1.0.8", | ||
| 15 | + "saveSpec": null, | ||
| 16 | + "fetchSpec": "^1.0.8" | ||
| 17 | + }, | ||
| 18 | + "_requiredBy": [ | ||
| 19 | + "/form-data" | ||
| 20 | + ], | ||
| 21 | + "_resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", | ||
| 22 | + "_shasum": "c3d45a8b34fd730631a110a8a2520682b31d5a7f", | ||
| 23 | + "_spec": "combined-stream@^1.0.8", | ||
| 24 | + "_where": "C:\\Users\\SIMBA\\Desktop\\SpotifyPlaylistExport-master\\node_modules\\form-data", | ||
| 25 | + "author": { | ||
| 26 | + "name": "Felix Geisendörfer", | ||
| 27 | + "email": "felix@debuggable.com", | ||
| 28 | + "url": "http://debuggable.com/" | ||
| 29 | + }, | ||
| 30 | + "bugs": { | ||
| 31 | + "url": "https://github.com/felixge/node-combined-stream/issues" | ||
| 32 | + }, | ||
| 33 | + "bundleDependencies": false, | ||
| 34 | + "dependencies": { | ||
| 35 | + "delayed-stream": "~1.0.0" | ||
| 36 | + }, | ||
| 37 | + "deprecated": false, | ||
| 38 | + "description": "A stream that emits multiple other streams one after another.", | ||
| 39 | + "devDependencies": { | ||
| 40 | + "far": "~0.0.7" | ||
| 41 | + }, | ||
| 42 | + "engines": { | ||
| 43 | + "node": ">= 0.8" | ||
| 44 | + }, | ||
| 45 | + "homepage": "https://github.com/felixge/node-combined-stream", | ||
| 46 | + "license": "MIT", | ||
| 47 | + "main": "./lib/combined_stream", | ||
| 48 | + "name": "combined-stream", | ||
| 49 | + "repository": { | ||
| 50 | + "type": "git", | ||
| 51 | + "url": "git://github.com/felixge/node-combined-stream.git" | ||
| 52 | + }, | ||
| 53 | + "scripts": { | ||
| 54 | + "test": "node test/run.js" | ||
| 55 | + }, | ||
| 56 | + "version": "1.0.8" | ||
| 57 | +} |
| 1 | +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | ||
| 2 | +# yarn lockfile v1 | ||
| 3 | + | ||
| 4 | + | ||
| 5 | +delayed-stream@~1.0.0: | ||
| 6 | + version "1.0.0" | ||
| 7 | + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" | ||
| 8 | + | ||
| 9 | +far@~0.0.7: | ||
| 10 | + version "0.0.7" | ||
| 11 | + resolved "https://registry.yarnpkg.com/far/-/far-0.0.7.tgz#01c1fd362bcd26ce9cf161af3938aa34619f79a7" | ||
| 12 | + dependencies: | ||
| 13 | + oop "0.0.3" | ||
| 14 | + | ||
| 15 | +oop@0.0.3: | ||
| 16 | + version "0.0.3" | ||
| 17 | + resolved "https://registry.yarnpkg.com/oop/-/oop-0.0.3.tgz#70fa405a5650891a194fdc82ca68dad6dabf4401" |
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
SpotifyPlaylistExport/node_modules/readable-stream/lib/internal/streams/async_iterator.js
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
SpotifyPlaylistExport/node_modules/readable-stream/lib/internal/streams/stream-browser.js
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
SpotifyPlaylistExport/node_modules/spotify-web-api-node/examples/add-tracks-to-a-playlist.js
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
SpotifyPlaylistExport/node_modules/spotify-web-api-node/examples/get-info-about-current-user.js
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
SpotifyPlaylistExport/node_modules/spotify-web-api-node/examples/get-top-tracks-for-artist.js
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
SpotifyPlaylistExport/node_modules/spotify-web-api-node/examples/tutorial/00-get-access-token.js
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
8.65 KB
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
SpotifyPlaylistExport/package-lock.json
0 → 100644
This diff is collapsed. Click to expand it.
SpotifyPlaylistExport/package.json
0 → 100644
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment