├── .gitignore
├── lib
├── README
├── soda-js.js
└── soda-js.bundle.js
├── .travis.yml
├── sample
├── basic_query.js
├── browser.html
└── basic_producer.js
├── test
├── connection_tests.coffee
├── consumer_tests.coffee
├── producer_tests.coffee
├── query_tests.coffee
└── operation_tests.coffee
├── package.json
├── README.textile
├── Cakefile
└── src
└── soda-js.coffee
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.swp
3 | *.swo
4 | node_modules/
5 |
--------------------------------------------------------------------------------
/lib/README:
--------------------------------------------------------------------------------
1 | this directory contains autogenerated files. do not edit them! edit the files in src/ instead.
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 0.8
4 | before_install:
5 | - npm install -g npm@'>=1.4.3'
6 |
--------------------------------------------------------------------------------
/sample/basic_query.js:
--------------------------------------------------------------------------------
1 | var soda = require('../lib/soda-js');
2 |
3 | var consumer = new soda.Consumer('open.whitehouse.gov');
4 |
5 | consumer.query()
6 | .withDataset('p86s-ychb')
7 | .limit(5)
8 | .where({ namelast: 'SMITH' })
9 | .order('namelast')
10 | .getRows()
11 | .on('success', function(rows) { console.log(rows); })
12 | .on('error', function(error) { console.error(error); });
13 |
14 |
--------------------------------------------------------------------------------
/test/connection_tests.coffee:
--------------------------------------------------------------------------------
1 |
2 | soda = require('../lib/soda-js')
3 |
4 | module.exports =
5 |
6 | 'basic construction': (beforeExit, assert) ->
7 | connection = new soda._internal.Connection('opendata.socrata.com')
8 | assert.eql(connection.dataSite, 'opendata.socrata.com')
9 |
10 | 'failed construction': (beforeExit, assert) ->
11 | caught = false
12 | try
13 | connection = new soda._internal.Connection('http://data.cityofchicago.org')
14 | catch ex
15 | caught = true
16 | assert.ok(caught)
--------------------------------------------------------------------------------
/test/consumer_tests.coffee:
--------------------------------------------------------------------------------
1 |
2 | soda = require('../lib/soda-js')
3 |
4 | module.exports =
5 | 'create consumer connection': (beforeExit, assert) ->
6 | consumer = new soda.Producer('data.seattle.gov')
7 | assert.ok(consumer.connection instanceof soda._internal.Connection)
8 | assert.eql(consumer.connection.dataSite, 'data.seattle.gov')
9 |
10 | 'create query': (beforeExit, assert) ->
11 | consumer = new soda.Consumer('data.seattle.gov')
12 | query = consumer.query()
13 | assert.ok(query instanceof soda._internal.Query)
14 | assert.eql(query.consumer, consumer)
15 |
16 |
--------------------------------------------------------------------------------
/sample/browser.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | soda-js sample
6 |
7 |
8 |
9 |
21 |
22 |
--------------------------------------------------------------------------------
/test/producer_tests.coffee:
--------------------------------------------------------------------------------
1 |
2 | soda = require('../lib/soda-js')
3 |
4 | module.exports =
5 | 'create producer connection': (beforeExit, assert) ->
6 | producer = new soda.Producer('data.seattle.gov')
7 | assert.ok(producer.connection instanceof soda._internal.Connection)
8 | assert.eql(producer.connection.dataSite, 'data.seattle.gov')
9 |
10 | 'create producer operation': (beforeExit, assert) ->
11 | producer = new soda.Producer('data.seattle.gov')
12 | operation = producer.operation()
13 | assert.ok(operation instanceof soda._internal.Operation)
14 | assert.eql(operation.producer, producer)
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "soda-js",
3 | "description": "js library for accessing a soda2 api",
4 | "homepage": "https://github.com/socrata/soda-js",
5 | "keywords": [
6 | "socrata",
7 | "soda",
8 | "api",
9 | "opendata",
10 | "open data"
11 | ],
12 | "contributors": [
13 | {
14 | "name": "Clint Tseng",
15 | "email": "clint.tseng@socrata.com"
16 | }
17 | ],
18 | "dependencies": {
19 | "eventemitter2": "~0.4.14",
20 | "superagent": "^3.7.0"
21 | },
22 | "devDependencies": {
23 | "coffee-script": "~1.6.3",
24 | "expresso": "~0.9.2",
25 | "browserify": "^12.0.1"
26 | },
27 | "licenses": [
28 | {
29 | "type": "MIT"
30 | }
31 | ],
32 | "scripts": {
33 | "test": "node_modules/expresso/bin/expresso test/*",
34 | "coffee": "node_modules/coffee-script/bin/cake build",
35 | "bundle": "browserify lib/soda-js.js --standalone soda > lib/soda-js.bundle.js",
36 | "build": "npm run coffee && npm run bundle"
37 | },
38 | "main": "./lib/soda-js.js",
39 | "version": "0.2.4"
40 | }
41 |
--------------------------------------------------------------------------------
/sample/basic_producer.js:
--------------------------------------------------------------------------------
1 | var soda = require('../lib/soda-js');
2 |
3 | var sodaOpts = {
4 | "username": "testuser@gmail.com",
5 | "password" : "OpenData",
6 | "apiToken" : "D8Atrg62F2j017ZTdkMpuZ9vY"
7 | }
8 | var producer = new soda.Producer('sandbox.demo.socrata.com', sodaOpts);
9 |
10 |
11 | var addSample = function() {
12 | var data = {
13 | mynum : 42,
14 | mytext: "hello world",
15 | mymoney: 999.99
16 | }
17 |
18 | console.log("Adding Sample")
19 | producer.operation()
20 | .withDataset('rphc-ayt9')
21 | .add(data)
22 | .on('success', function(row) { console.log(row); updateSample(row[':id']); })
23 | .on('error', function(error) { console.error(error); })
24 | }
25 |
26 | var updateSample = function(id) {
27 | var data = { mytext: "goodbye world" }
28 |
29 | console.log("\nUpdating Sample")
30 | producer.operation()
31 | .withDataset('rphc-ayt9')
32 | .update(id, data)
33 | .on('success', function(row) { console.log(row); deleteSample(row[':id']); })
34 | .on('error', function(error) { console.error(error); })
35 | }
36 |
37 |
38 | var deleteSample = function(id) {
39 | console.log("\nDeleting Sample")
40 | producer.operation()
41 | .withDataset('rphc-ayt9')
42 | .delete(id)
43 | .on('success', function(row) { console.log(row); })
44 | .on('error', function(error) { console.error(error); })
45 | }
46 |
47 |
48 |
49 | addSample();
--------------------------------------------------------------------------------
/README.textile:
--------------------------------------------------------------------------------
1 | h1. soda-js "!https://secure.travis-ci.org/socrata/soda-js.png!":http://travis-ci.org/socrata/soda-js
2 |
3 | A client implementation of the Socrata Open Data API in Coffeescript and Javascript.
4 |
5 | h2. Important Note
6 |
7 | In order to access the SODA API via HTTPS, clients must now "support the Server Name Indication (SNI)":https://dev.socrata.com/changelog/2016/08/24/sni-now-required-for-https-connections.html extension to the TLS protocol. What does this mean? It means that if you're using @soda-js@, you must use a JavaScript VM that supports SNI:
8 |
9 | * "Internet Explorer 7+":https://en.wikipedia.org/wiki/Server_Name_Indication#Support
10 | * "Mozilla Firefox 2+":https://en.wikipedia.org/wiki/Server_Name_Indication#Support
11 | * "Apple Safari (all versions)":https://en.wikipedia.org/wiki/Server_Name_Indication#Support
12 | * "Google Chrome 6.0+":https://en.wikipedia.org/wiki/Server_Name_Indication#Support
13 | * "node.js 0.5.3+":https://github.com/nodejs/node/blob/e1643ccc5a5ecf7cb779472d244459469c9971a1/doc/changelogs/CHANGELOG_ARCHIVE.md#20110801-version-053-unstable
14 |
15 | h2. Supported Operations
16 |
17 | Supports both consumer and producer API, but does not currently support creating datasets or the import workflow.
18 |
19 | h2. Usage
20 |
21 | See the @sample/@ directory for sample code, but here's the general idea:
22 |
23 | bc.. var soda = require('soda-js');
24 |
25 | h3. Consumer API
26 |
27 | You can query a dataset by SODA2 clauses, or supply a custom SoQL query to be run.
28 |
29 | bc.. var consumer = new soda.Consumer('explore.data.gov');
30 |
31 | consumer.query()
32 | .withDataset('644b-gaut')
33 | .limit(5)
34 | .where({ namelast: 'SMITH' })
35 | .order('namelast')
36 | .getRows()
37 | .on('success', function(rows) { console.log(rows); })
38 | .on('error', function(error) { console.error(error); });
39 |
40 | p. Using 'like' in a where clause:
41 |
42 | bc.. .where("namelast like '%MITH'")
43 |
44 | h3. Producer API
45 |
46 | You can add, update, replace, delete, and upsert rows, as well as truncate a dataset.
47 |
48 | bc.. var producer = new soda.Producer('sandbox.demo.socrata.com', sodaConnectionOptions);
49 |
50 | var data = { mynum : 42, mytext: "hello world" }
51 |
52 | producer.operation()
53 | .withDataset('rphc-ayt9')
54 | .add(data)
55 | .on('success', function(row) { console.log(row); })
56 | .on('error', function(error) { console.error(error); })
57 |
58 | h2. License
59 |
60 | Provided under the MIT license.
61 |
62 |
--------------------------------------------------------------------------------
/test/query_tests.coffee:
--------------------------------------------------------------------------------
1 |
2 | soda = require('../lib/soda-js')
3 |
4 | # fixture generator to allow injecting verifiers as networkers
5 | consumer = (verifier) ->
6 | connection:
7 | networker: ((opts) -> verifier(opts); -> null),
8 | emitterOpts:
9 | wildcard: true,
10 | delimiter: '.',
11 | maxListeners: 15
12 |
13 | # convenience func for using the above fixture with a query
14 | queryWith = (networker) -> new soda._internal.Query(consumer(networker))
15 |
16 | module.exports =
17 |
18 | 'basic query': (beforeExit, assert) ->
19 | verifier = (opts) ->
20 | assert.eql(opts.path, '/resource/hospitals.json')
21 |
22 | queryWith(verifier)
23 | .withDataset('hospitals')
24 | .getRows()
25 |
26 | 'col select': (beforeExit, assert) ->
27 | verifier = (opts) ->
28 | assert.eql(opts.query, { $select: 'street, city, state, zip' })
29 |
30 | queryWith(verifier)
31 | .withDataset('hospitals')
32 | .select('street', 'city', 'state', 'zip')
33 | .getRows()
34 |
35 | 'string expr': (beforeExit, assert) ->
36 | expr = soda.expr.eq('name', 'bob')
37 | assert.eql(expr, "name = 'bob'")
38 |
39 | 'number expr': (beforeExit, assert) ->
40 | expr = soda.expr.eq('age', 15)
41 | assert.eql(expr, "age = 15")
42 |
43 | 'compound expr': (beforeExit, assert) ->
44 | expr = soda.expr.and(soda.expr.eq('columnone', 1), soda.expr.eq('columntwo', 2))
45 | assert.eql(expr, '(columnone = 1) and (columntwo = 2)')
46 |
47 | 'string where': (beforeExit, assert) ->
48 | verifier = (opts) ->
49 | assert.eql(opts.query, { $where: '(salary > 35000) and (yearsWorked >= 5)' })
50 |
51 | queryWith(verifier)
52 | .withDataset('salaries')
53 | .where('salary > 35000', 'yearsWorked >= 5')
54 | .getRows()
55 |
56 | 'obj where': (beforeExit, assert) ->
57 | verifier = (opts) ->
58 | assert.eql(opts.query, { $where: "(firstname = 'abed') and (lastname = 'nadir')" })
59 |
60 | queryWith(verifier)
61 | .withDataset('people')
62 | .where({ firstname: 'abed', lastname: 'nadir' })
63 | .getRows()
64 |
65 | 'groupby': (beforeExit, assert) ->
66 | verifier = (opts) ->
67 | assert.eql(opts.query, { $group: 'department, type' })
68 |
69 | queryWith(verifier)
70 | .withDataset('payments')
71 | .group('department', 'type')
72 | .getRows()
73 |
74 | 'having': (beforeExit, assert) ->
75 | # having is the same implementation as where, so just test a maxiquery
76 | verifier = (opts) ->
77 | assert.eql(opts.query,
78 | $group: 'firstname, lastname, total_salary',
79 | $having: "((firstname = 'jeff') or (lastname = 'winger')) and (total_salary > 100000)")
80 |
81 | queryWith(verifier)
82 | .withDataset('salaries')
83 | .group('firstname', 'lastname', 'total_salary') # of course in reality total_salary would be an aggr func..
84 | .having(soda.expr.or(soda.expr.eq('firstname', 'jeff'), soda.expr.eq('lastname', 'winger')), 'total_salary > 100000')
85 | .getRows()
86 |
87 | 'orderby': (beforeExit, assert) ->
88 | verifier = (opts) ->
89 | assert.eql(opts.query, { $order: 'lastname asc, firstname desc' })
90 |
91 | queryWith(verifier)
92 | .withDataset('salaries')
93 | .order('lastname', 'firstname desc')
94 | .getRows()
95 |
96 | 'offset and limit': (beforeExit, assert) ->
97 | verifier = (opts) ->
98 | assert.eql(opts.query, { $offset: 5, $limit: 10 })
99 |
100 | queryWith(verifier)
101 | .withDataset('hospitals')
102 | .offset(5)
103 | .limit(10)
104 | .getRows()
105 |
106 |
--------------------------------------------------------------------------------
/test/operation_tests.coffee:
--------------------------------------------------------------------------------
1 |
2 | soda = require('../lib/soda-js')
3 |
4 | # fixture generator to allow injecting verifiers as networkers
5 | producer = (verifier) ->
6 | connection:
7 | networker: ((opts, data) -> verifier(opts, data); -> null),
8 | emitterOpts:
9 | wildcard: true,
10 | delimiter: '.',
11 | maxListeners: 15
12 |
13 |
14 | # convenience func for using the above fixture with an operation
15 | operateWith = (networker) -> new soda._internal.Operation(producer(networker))
16 |
17 | module.exports =
18 | 'basic add': (beforeExit, assert) ->
19 | verifier = (opts, data) ->
20 | assert.eql(opts.method, "post")
21 | assert.eql(opts.path, "/resource/abcd-1234")
22 | assert.eql(data, { hello: "world" })
23 |
24 | operateWith(verifier)
25 | .withDataset('abcd-1234')
26 | .add( {hello: "world" })
27 |
28 | 'multiple add': (beforeExit, assert) ->
29 | verifier = (opts, data) ->
30 | assert.eql(opts.method, "post")
31 | assert.eql(opts.path, "/resource/abcd-1234")
32 | assert.eql(data.length, 3)
33 |
34 | operateWith(verifier)
35 | .withDataset('abcd-1234')
36 | .add( [{col:"a"}, {col:"b"}, {col:"c"}] )
37 |
38 | 'add prevents upsert of object': (beforeExit, assert) ->
39 | verifier = (opts, data) ->
40 | assert.eql(opts.method, "post")
41 | assert.eql(opts.path, "/resource/abcd-1234")
42 | assert.eql(data, { col: "c" })
43 |
44 | operateWith(verifier)
45 | .withDataset('abcd-1234')
46 | .add( { ":id": 3, ":delete": true, col:"c"} )
47 |
48 | 'add prevents upsert of array': (beforeExit, assert) ->
49 | verifier = (opts, data) ->
50 | assert.eql(opts.method, "post")
51 | assert.eql(opts.path, "/resource/abcd-1234")
52 | assert.eql(data, [
53 | {col:"a"},
54 | {col:"b"},
55 | {col:"c"},
56 | {col:"d"}
57 | ])
58 |
59 | operateWith(verifier)
60 | .withDataset('abcd-1234')
61 | .add([
62 | { ":id": 1, col: "a"},
63 | { col: "b", ":delete": true },
64 | { ":id": 3, ":delete": true, col:"c"},
65 | { col: "d" }
66 | ])
67 |
68 |
69 | 'upsert array': (beforeExit, assert) ->
70 | verifier = (opts, data) ->
71 | assert.eql(opts.method, "post")
72 | assert.eql(opts.path, "/resource/abcd-1234")
73 | assert.eql(data, [
74 | { col: "a", ":id": 1},
75 | { col: "b", ":delete": true },
76 | { col: "c", ":id": 3, ":delete": true },
77 | { col: "d" }
78 | ])
79 |
80 | operateWith(verifier)
81 | .withDataset('abcd-1234')
82 | .upsert([
83 | { ":id": 1, col: "a"},
84 | { col: "b", ":delete": true },
85 | { ":id": 3, ":delete": true, col:"c"},
86 | { col: "d" }
87 | ])
88 |
89 | 'basic truncate': (beforeExit, assert) ->
90 | verifier = (opts, data) ->
91 | assert.eql(opts.method, "delete")
92 | assert.eql(opts.path, "/resource/lmno-9876")
93 | assert.isUndefined(data)
94 |
95 | operateWith(verifier)
96 | .withDataset('lmno-9876')
97 | .truncate()
98 |
99 | 'basic delete': (beforeExit, assert) ->
100 | verifier = (opts, data) ->
101 | assert.eql(opts.method, "delete")
102 | assert.eql(opts.path, "/resource/lmno-9876/123")
103 | assert.isUndefined(data)
104 |
105 | operateWith(verifier)
106 | .withDataset('lmno-9876')
107 | .delete(123)
108 |
109 | 'basic update': (beforeExit, assert) ->
110 | verifier = (opts, data) ->
111 | assert.eql(opts.method, "post") # seriously, why isn't this patch?
112 | assert.eql(opts.path, "/resource/lmno-9876/123")
113 | assert.eql(data, { num : 987 })
114 |
115 | operateWith(verifier)
116 | .withDataset("lmno-9876")
117 | .update(123, { num : 987 })
118 |
119 | 'basic replace': (beforeExit, assert) ->
120 | verifier = (opts, data) ->
121 | assert.eql(opts.method, "put")
122 | assert.eql(opts.path, "/resource/lmno-1234/987")
123 | assert.eql(data, { num : 456 })
124 |
125 | operateWith(verifier)
126 | .withDataset("lmno-1234")
127 | .replace(987, { num : 456 })
128 |
129 |
--------------------------------------------------------------------------------
/Cakefile:
--------------------------------------------------------------------------------
1 | # Taken almost entirely from https://github.com/twilson63/cakefile-template
2 | #
3 | # Il y a 5 tasks:
4 | #
5 | # * build - compiles your src directory to your lib directory
6 | # * watch - watches any changes in your src directory and automatically compiles to the lib directory
7 | # * test - runs mocha test framework, you can edit this task to use your favorite test framework
8 | # * docs - generates annotated documentation using docco
9 | # * clean - clean generated .js files
10 | files = [
11 | 'lib'
12 | 'src'
13 | ]
14 |
15 | fs = require 'fs'
16 | {print} = require 'util'
17 | {spawn, exec} = require 'child_process'
18 |
19 | try
20 | which = require('which').sync
21 | catch err
22 | which = null
23 |
24 | # ANSI Terminal Colors
25 | bold = '\x1b[0;1m'
26 | green = '\x1b[0;32m'
27 | reset = '\x1b[0m'
28 | red = '\x1b[0;31m'
29 |
30 | # Cakefile Tasks
31 | #
32 | # ## *docs*
33 | #
34 | # Generate Annotated Documentation
35 | #
36 | # Usage
37 | #
38 | # ```
39 | # cake docs
40 | # ```
41 | task 'docs', 'generate documentation', -> docco()
42 |
43 | # ## *build*
44 | #
45 | # Builds Source
46 | #
47 | # Usage
48 | #
49 | # ```
50 | # cake build
51 | # ```
52 | task 'build', 'compile source', -> build -> log ":)", green
53 |
54 | # ## *watch*
55 | #
56 | # Builds your source whenever it changes
57 | #
58 | # Usage
59 | #
60 | # ```
61 | # cake watch
62 | # ```
63 | task 'watch', 'compile and watch', -> build true, -> log ":-)", green
64 |
65 | # ## *test*
66 | #
67 | # Runs your test suite.
68 | #
69 | # Usage
70 | #
71 | # ```
72 | # cake test
73 | # ```
74 | task 'test', 'run tests', -> build -> expresso [ 'test/*' ], -> log ":)", green
75 |
76 | # ## *clean*
77 | #
78 | # Cleans up generated js files
79 | #
80 | # Ussage
81 | #
82 | # ```
83 | # cake clean
84 | # ```
85 | task 'clean', 'clean generated files', -> clean -> log ";)", green
86 |
87 |
88 | # Internal Functions
89 | #
90 | # ## *walk*
91 | #
92 | # **given** string as dir which represents a directory in relation to local directory
93 | # **and** callback as done in the form of (err, results)
94 | # **then** recurse through directory returning an array of files
95 | walk = (dir, done) ->
96 | results = []
97 | fs.readdir dir, (err, list) ->
98 | return done(err, []) if err
99 | pending = list.length
100 | return done(null, results) unless pending
101 | for name in list
102 | file = "#{dir}/#{name}"
103 | try
104 | stat = fs.statSync file
105 | catch err
106 | stat = null
107 | if stat?.isDirectory()
108 | walk file, (err, res) ->
109 | results.push name for name in res
110 | done(null, results) unless --pending
111 | else
112 | results.push file
113 | done(null, results) unless --pending
114 |
115 | # ## *log*
116 | #
117 | # **given** string as a message
118 | # **and** string as a color
119 | # **and** optional string as an explaination
120 | # **then** builds a statement and logs to console.
121 | log = (message, color, explanation) -> console.log color + message + reset + ' ' + (explanation or '')
122 |
123 | # ## *launch*
124 | #
125 | # **given** string as a cmd
126 | # **and** optional array and option flags
127 | # **and** optional callback
128 | # **then** spawn cmd with options
129 | # **and** pipe to process stdout and stderr respectively
130 | # **and** on child process exit emit callback if set and status is 0
131 | launch = (cmd, options=[], callback) ->
132 | cmd = which(cmd) if which
133 | app = spawn cmd, options
134 | app.stdout.pipe(process.stdout)
135 | app.stderr.pipe(process.stderr)
136 | app.on 'exit', (status) -> callback?() if status is 0
137 |
138 | # ## *build*
139 | #
140 | # **given** optional boolean as watch
141 | # **and** optional function as callback
142 | # **then** invoke launch passing coffee command
143 | # **and** defaulted options to compile src to lib
144 | build = (watch, callback) ->
145 | if typeof watch is 'function'
146 | callback = watch
147 | watch = false
148 |
149 | options = ['-c', '-b', '-o' ]
150 | options = options.concat files
151 | options.unshift '-w' if watch
152 | launch 'coffee', options, callback
153 |
154 | # ## *unlinkIfCoffeeFile*
155 | #
156 | # **given** string as file
157 | # **and** file ends in '.coffee'
158 | # **then** convert '.coffee' to '.js'
159 | # **and** remove the result
160 | unlinkIfCoffeeFile = (file) ->
161 | if file.match /\.coffee$/
162 | fs.unlink file.replace(/\.coffee$/, '.js')
163 | true
164 | else false
165 |
166 | # ## *clean*
167 | #
168 | # **given** optional function as callback
169 | # **then** loop through files variable
170 | # **and** call unlinkIfCoffeeFile on each
171 | clean = (callback) ->
172 | try
173 | for file in files
174 | unless unlinkIfCoffeeFile file
175 | walk file, (err, results) ->
176 | for f in results
177 | unlinkIfCoffeeFile f
178 |
179 | callback?()
180 | catch err
181 |
182 | # ## *moduleExists*
183 | #
184 | # **given** name for module
185 | # **when** trying to require module
186 | # **and** not found
187 | # **then* print not found message with install helper in red
188 | # **and* return false if not found
189 | moduleExists = (name) ->
190 | try
191 | require name
192 | catch err
193 | log "#{name} required: npm install #{name}", red
194 | false
195 |
196 |
197 | # ## *expresso*
198 | #
199 | # **given** optional array of option flags
200 | # **and** optional function as callback
201 | # **then** invoke launch passing expresso command
202 | expresso = (options, callback) ->
203 | if typeof options is 'function'
204 | callback = options
205 | options = []
206 |
207 | launch './node_modules/expresso/bin/expresso', options, callback
208 |
209 | # ## *docco*
210 | #
211 | # **given** optional function as callback
212 | # **then** invoke launch passing docco command
213 | docco = (callback) ->
214 | #if moduleExists('docco')
215 | walk 'src', (err, files) -> launch 'docco', files, callback
216 |
217 |
--------------------------------------------------------------------------------
/src/soda-js.coffee:
--------------------------------------------------------------------------------
1 | # soda.coffee -- chained, evented, buzzworded library for accessing SODA via JS.
2 |
3 | # sodaOpts options:
4 | # username: https basic auth username
5 | # password: https basic auth password
6 | # apiToken: socrata api token
7 | #
8 | # emitterOpts: options to override EventEmitter2 declaration options
9 |
10 | # TODO:
11 | # * we're inconsistent about validating query correctness. do we continue with catch-what-we-can,
12 | # or do we just back off and leave all failures to the api to return?
13 |
14 | eelib = require('eventemitter2')
15 | EventEmitter = eelib.EventEmitter2 || eelib
16 | httpClient = require('superagent')
17 |
18 | # internal util funcs
19 | isString = (obj) -> typeof obj == 'string'
20 | isArray = (obj) -> Array.isArray(obj)
21 | isNumber = (obj) -> !isNaN(parseFloat(obj))
22 | extend = (target, sources...) -> (target[k] = v for k, v of source) for source in sources; null
23 |
24 | # it's really, really, really stupid that i have to solve this problem here
25 | toBase64 =
26 | if Buffer?
27 | (str) -> new Buffer(str).toString('base64')
28 | else
29 | # adapted/modified from https://github.com/rwz/base64.coffee
30 | base64Lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split('')
31 | rawToBase64 = btoa ? (str) ->
32 | result = []
33 | i = 0
34 | while i < str.length
35 | chr1 = str.charCodeAt(i++)
36 | chr2 = str.charCodeAt(i++)
37 | chr3 = str.charCodeAt(i++)
38 | throw new Error('Invalid character!') if Math.max(chr1, chr2, chr3) > 0xFF
39 |
40 | enc1 = chr1 >> 2
41 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4)
42 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6)
43 | enc4 = chr3 & 63
44 |
45 | if isNaN(chr2)
46 | enc3 = enc4 = 64
47 | else if isNaN(chr3)
48 | enc4 = 64
49 |
50 | result.push(base64Lookup[enc1])
51 | result.push(base64Lookup[enc2])
52 | result.push(base64Lookup[enc3])
53 | result.push(base64Lookup[enc4])
54 | result.join('')
55 | (str) -> rawToBase64(unescape(encodeURIComponent(str)))
56 |
57 | handleLiteral = (literal) ->
58 | if isString(literal)
59 | "'#{literal}'"
60 | else if isNumber(literal)
61 | # TODO: possibly ensure number cleanliness for sending to the api? sci not?
62 | literal
63 | else
64 | literal
65 |
66 | handleOrder = (order) ->
67 | if /( asc$| desc$)/i.test(order)
68 | order
69 | else
70 | order + ' asc'
71 |
72 | addExpr = (target, args) ->
73 | for arg in args
74 | if isString(arg)
75 | target.push(arg)
76 | else
77 | target.push("#{k} = #{handleLiteral(v)}") for k, v of arg
78 |
79 | # extern util funcs
80 |
81 | # convenience functions for building where clauses, if so desired
82 | expr =
83 | and: (clauses...) -> ("(#{clause})" for clause in clauses).join(' and ')
84 | or: (clauses...) -> ("(#{clause})" for clause in clauses).join(' or ')
85 |
86 | gt: (column, literal) -> "#{column} > #{handleLiteral(literal)}"
87 | gte: (column, literal) -> "#{column} >= #{handleLiteral(literal)}"
88 | lt: (column, literal) -> "#{column} < #{handleLiteral(literal)}"
89 | lte: (column, literal) -> "#{column} <= #{handleLiteral(literal)}"
90 | eq: (column, literal) -> "#{column} = #{handleLiteral(literal)}"
91 |
92 | # serialize object to querystring
93 | toQuerystring = (obj) ->
94 | str = []
95 | for own key, val of obj
96 | str.push encodeURIComponent(key) + '=' + encodeURIComponent(val)
97 | str.join '&'
98 |
99 | class Connection
100 | constructor: (@dataSite, @sodaOpts = {}) ->
101 | throw new Error('dataSite does not appear to be valid! Please supply a domain name, eg data.seattle.gov') unless /^[a-z0-9-_.]+(:[0-9]+)?$/i.test(@dataSite)
102 |
103 | # options passed directly into EventEmitter2 construction
104 | @emitterOpts = @sodaOpts.emitterOpts ?
105 | wildcard: true,
106 | delimiter: '.',
107 | maxListeners: 15
108 |
109 | @networker = (opts, data) ->
110 | url = "https://#{@dataSite}#{opts.path}"
111 |
112 | client = httpClient(opts.method, url)
113 |
114 | client.set('Accept', "application/json") if data?
115 | client.set('Content-type', "application/json") if data?
116 | client.set('X-App-Token', @sodaOpts.apiToken) if @sodaOpts.apiToken?
117 | client.set('Authorization', "Basic " + toBase64("#{@sodaOpts.username}:#{@sodaOpts.password}")) if @sodaOpts.username? and @sodaOpts.password?
118 | client.set('Authorization', "OAuth " + accessToken) if @sodaOpts.accessToken?
119 |
120 | client.query(opts.query) if opts.query?
121 | client.send(data) if data?
122 |
123 | (responseHandler) => client.end(responseHandler || @getDefaultHandler())
124 |
125 | getDefaultHandler: ->
126 | # instance variable for easy chaining
127 | @emitter = emitter = new EventEmitter(@emitterOpts)
128 |
129 | # return the handler
130 | handler = (error, response) ->
131 | # TODO: possibly more granular handling?
132 | if response.ok
133 | if response.accepted
134 | # handle 202 by remaking request. inform of possible progress.
135 | emitter.emit('progress', response.body)
136 | setTimeout((-> @consumer.networker(opts)(handler)), 5000)
137 | else
138 | emitter.emit('success', response.body)
139 | else
140 | emitter.emit('error', response.body ? response.text)
141 |
142 | # just emit the raw superagent obj if they just want complete event
143 | emitter.emit('complete', response)
144 |
145 |
146 |
147 |
148 | # main class
149 | class Consumer
150 | constructor: (@dataSite, @sodaOpts = {}) ->
151 | @connection = new Connection(@dataSite, @sodaOpts)
152 |
153 | query: ->
154 | new Query(this)
155 |
156 | getDataset: (id) ->
157 | emitter = new EventEmitter(@emitterOpts)
158 | # TODO: implement me
159 |
160 | # Producer class
161 | class Producer
162 | constructor: (@dataSite, @sodaOpts = {}) ->
163 | @connection = new Connection(@dataSite, @sodaOpts)
164 |
165 | operation: ->
166 | new Operation(this)
167 |
168 | class Operation
169 | constructor: (@producer) ->
170 |
171 | withDataset: (datasetId) -> @_datasetId = datasetId; this
172 |
173 | # truncate the entire dataset
174 | truncate: ->
175 | opts = method: 'delete'
176 | opts.path = "/resource/#{@_datasetId}"
177 | this._exec(opts)
178 |
179 | # add a new row - explicitly avoids upserting (updating/deleting existing rows)
180 | add: (data) ->
181 | opts = method: 'post'
182 | opts.path = "/resource/#{@_datasetId}"
183 |
184 | _data = JSON.parse(JSON.stringify(data))
185 | delete _data[':id']
186 | delete _data[':delete']
187 | for obj in _data
188 | delete obj[':id']
189 | delete obj[':delete']
190 |
191 | this._exec(opts, _data)
192 |
193 | # modify existing rows
194 | delete: (id) ->
195 | opts = method: 'delete'
196 | opts.path = "/resource/#{@_datasetId}/#{id}"
197 | this._exec(opts)
198 | update: (id, data) ->
199 | opts = method: 'post'
200 | opts.path = "/resource/#{@_datasetId}/#{id}"
201 | this._exec(opts, data)
202 | replace: (id, data) ->
203 | opts = method: 'put'
204 | opts.path = "/resource/#{@_datasetId}/#{id}"
205 | this._exec(opts, data)
206 |
207 | # add objects, update if existing, delete if :delete=true
208 | upsert: (data) ->
209 | opts = method: 'post'
210 | opts.path = "/resource/#{@_datasetId}"
211 | this._exec(opts, data)
212 |
213 | _exec: (opts, data) ->
214 | throw new Error('no dataset given to work against!') unless @_datasetId?
215 | @producer.connection.networker(opts, data)()
216 | @producer.connection.emitter
217 |
218 |
219 | # querybuilder class
220 | class Query
221 | constructor: (@consumer) ->
222 | @_select = []
223 | @_where = []
224 | @_group = []
225 | @_having = []
226 | @_order = []
227 | @_offset = @_limit = @_q = null
228 |
229 | withDataset: (datasetId) -> @_datasetId = datasetId; this
230 |
231 | # for passing in a fully formed soql query. all other params will be ignored
232 | soql: (query) -> @_soql = query; this
233 |
234 | select: (selects...) -> @_select.push(select) for select in selects; this
235 |
236 | # args: ('clause', [...])
237 | # ({ column: value1, columnb: value2 }, [...]])
238 | # multiple calls are assumed to be and-chained
239 | where: (args...) -> addExpr(@_where, args); this
240 | having: (args...) -> addExpr(@_having, args); this
241 |
242 | group: (groups...) -> @_group.push(group) for group in groups; this
243 |
244 | # args: ("column direction", ["column direction", [...]])
245 | order: (orders...) -> @_order.push(handleOrder(order)) for order in orders; this
246 |
247 | offset: (offset) -> @_offset = offset; this
248 |
249 | limit: (limit) -> @_limit = limit; this
250 |
251 | q: (q) -> @_q = q; this
252 |
253 | getOpts: ->
254 | opts = method: 'get'
255 |
256 | throw new Error('no dataset given to work against!') unless @_datasetId?
257 | opts.path = "/resource/#{@_datasetId}.json"
258 |
259 | queryComponents = this._buildQueryComponents()
260 | opts.query = {}
261 | opts.query['$' + k] = v for k, v of queryComponents
262 |
263 | opts
264 |
265 | getURL: ->
266 | opts = this.getOpts()
267 | query = toQuerystring(opts.query)
268 |
269 | "https://#{@consumer.dataSite}#{opts.path}" + (if query then "?#{query}" else "")
270 |
271 | getRows: ->
272 | opts = this.getOpts()
273 |
274 | @consumer.connection.networker(opts)()
275 | @consumer.connection.emitter
276 |
277 | _buildQueryComponents: ->
278 | query = {}
279 |
280 | if @_soql?
281 | query.query = @_soql
282 | else
283 | query.select = @_select.join(', ') if @_select.length > 0
284 |
285 | query.where = expr.and.apply(this, @_where) if @_where.length > 0
286 |
287 | query.group = @_group.join(', ') if @_group.length > 0
288 |
289 | if @_having.length > 0
290 | throw new Error('Having provided without group by!') unless @_group.length > 0
291 | query.having = expr.and.apply(this, @_having)
292 |
293 | query.order = @_order.join(', ') if @_order.length > 0
294 |
295 | query.offset = @_offset if isNumber(@_offset)
296 | query.limit = @_limit if isNumber(@_limit)
297 |
298 | query.q = @_q if @_q
299 |
300 | query
301 |
302 | class Dataset
303 | constructor: (@data, @client) ->
304 | # TODO: implement me
305 |
306 | extend(exports ? this.soda,
307 | Consumer: Consumer,
308 | Producer: Producer,
309 | expr: expr,
310 |
311 | # exported for testing reasons
312 | _internal:
313 | Connection: Connection,
314 | Query: Query,
315 | Operation: Operation,
316 | util:
317 | toBase64: toBase64,
318 | handleLiteral: handleLiteral,
319 | handleOrder: handleOrder
320 | )
321 |
322 |
--------------------------------------------------------------------------------
/lib/soda-js.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.6.3
2 | var Connection, Consumer, Dataset, EventEmitter, Operation, Producer, Query, addExpr, base64Lookup, eelib, expr, extend, handleLiteral, handleOrder, httpClient, isArray, isNumber, isString, rawToBase64, toBase64, toQuerystring,
3 | __slice = [].slice,
4 | __hasProp = {}.hasOwnProperty;
5 |
6 | eelib = require('eventemitter2');
7 |
8 | EventEmitter = eelib.EventEmitter2 || eelib;
9 |
10 | httpClient = require('superagent');
11 |
12 | isString = function(obj) {
13 | return typeof obj === 'string';
14 | };
15 |
16 | isArray = function(obj) {
17 | return Array.isArray(obj);
18 | };
19 |
20 | isNumber = function(obj) {
21 | return !isNaN(parseFloat(obj));
22 | };
23 |
24 | extend = function() {
25 | var k, source, sources, target, v, _i, _len;
26 | target = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
27 | for (_i = 0, _len = sources.length; _i < _len; _i++) {
28 | source = sources[_i];
29 | for (k in source) {
30 | v = source[k];
31 | target[k] = v;
32 | }
33 | }
34 | return null;
35 | };
36 |
37 | toBase64 = typeof Buffer !== "undefined" && Buffer !== null ? function(str) {
38 | return new Buffer(str).toString('base64');
39 | } : (base64Lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''), rawToBase64 = typeof btoa !== "undefined" && btoa !== null ? btoa : function(str) {
40 | var chr1, chr2, chr3, enc1, enc2, enc3, enc4, i, result;
41 | result = [];
42 | i = 0;
43 | while (i < str.length) {
44 | chr1 = str.charCodeAt(i++);
45 | chr2 = str.charCodeAt(i++);
46 | chr3 = str.charCodeAt(i++);
47 | if (Math.max(chr1, chr2, chr3) > 0xFF) {
48 | throw new Error('Invalid character!');
49 | }
50 | enc1 = chr1 >> 2;
51 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
52 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
53 | enc4 = chr3 & 63;
54 | if (isNaN(chr2)) {
55 | enc3 = enc4 = 64;
56 | } else if (isNaN(chr3)) {
57 | enc4 = 64;
58 | }
59 | result.push(base64Lookup[enc1]);
60 | result.push(base64Lookup[enc2]);
61 | result.push(base64Lookup[enc3]);
62 | result.push(base64Lookup[enc4]);
63 | }
64 | return result.join('');
65 | }, function(str) {
66 | return rawToBase64(unescape(encodeURIComponent(str)));
67 | });
68 |
69 | handleLiteral = function(literal) {
70 | if (isString(literal)) {
71 | return "'" + literal + "'";
72 | } else if (isNumber(literal)) {
73 | return literal;
74 | } else {
75 | return literal;
76 | }
77 | };
78 |
79 | handleOrder = function(order) {
80 | if (/( asc$| desc$)/i.test(order)) {
81 | return order;
82 | } else {
83 | return order + ' asc';
84 | }
85 | };
86 |
87 | addExpr = function(target, args) {
88 | var arg, k, v, _i, _len, _results;
89 | _results = [];
90 | for (_i = 0, _len = args.length; _i < _len; _i++) {
91 | arg = args[_i];
92 | if (isString(arg)) {
93 | _results.push(target.push(arg));
94 | } else {
95 | _results.push((function() {
96 | var _results1;
97 | _results1 = [];
98 | for (k in arg) {
99 | v = arg[k];
100 | _results1.push(target.push("" + k + " = " + (handleLiteral(v))));
101 | }
102 | return _results1;
103 | })());
104 | }
105 | }
106 | return _results;
107 | };
108 |
109 | expr = {
110 | and: function() {
111 | var clause, clauses;
112 | clauses = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
113 | return ((function() {
114 | var _i, _len, _results;
115 | _results = [];
116 | for (_i = 0, _len = clauses.length; _i < _len; _i++) {
117 | clause = clauses[_i];
118 | _results.push("(" + clause + ")");
119 | }
120 | return _results;
121 | })()).join(' and ');
122 | },
123 | or: function() {
124 | var clause, clauses;
125 | clauses = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
126 | return ((function() {
127 | var _i, _len, _results;
128 | _results = [];
129 | for (_i = 0, _len = clauses.length; _i < _len; _i++) {
130 | clause = clauses[_i];
131 | _results.push("(" + clause + ")");
132 | }
133 | return _results;
134 | })()).join(' or ');
135 | },
136 | gt: function(column, literal) {
137 | return "" + column + " > " + (handleLiteral(literal));
138 | },
139 | gte: function(column, literal) {
140 | return "" + column + " >= " + (handleLiteral(literal));
141 | },
142 | lt: function(column, literal) {
143 | return "" + column + " < " + (handleLiteral(literal));
144 | },
145 | lte: function(column, literal) {
146 | return "" + column + " <= " + (handleLiteral(literal));
147 | },
148 | eq: function(column, literal) {
149 | return "" + column + " = " + (handleLiteral(literal));
150 | }
151 | };
152 |
153 | toQuerystring = function(obj) {
154 | var key, str, val;
155 | str = [];
156 | for (key in obj) {
157 | if (!__hasProp.call(obj, key)) continue;
158 | val = obj[key];
159 | str.push(encodeURIComponent(key) + '=' + encodeURIComponent(val));
160 | }
161 | return str.join('&');
162 | };
163 |
164 | Connection = (function() {
165 | function Connection(dataSite, sodaOpts) {
166 | var _ref;
167 | this.dataSite = dataSite;
168 | this.sodaOpts = sodaOpts != null ? sodaOpts : {};
169 | if (!/^[a-z0-9-_.]+(:[0-9]+)?$/i.test(this.dataSite)) {
170 | throw new Error('dataSite does not appear to be valid! Please supply a domain name, eg data.seattle.gov');
171 | }
172 | this.emitterOpts = (_ref = this.sodaOpts.emitterOpts) != null ? _ref : {
173 | wildcard: true,
174 | delimiter: '.',
175 | maxListeners: 15
176 | };
177 | this.networker = function(opts, data) {
178 | var client, url,
179 | _this = this;
180 | url = "https://" + this.dataSite + opts.path;
181 | client = httpClient(opts.method, url);
182 | if (data != null) {
183 | client.set('Accept', "application/json");
184 | }
185 | if (data != null) {
186 | client.set('Content-type', "application/json");
187 | }
188 | if (this.sodaOpts.apiToken != null) {
189 | client.set('X-App-Token', this.sodaOpts.apiToken);
190 | }
191 | if ((this.sodaOpts.username != null) && (this.sodaOpts.password != null)) {
192 | client.set('Authorization', "Basic " + toBase64("" + this.sodaOpts.username + ":" + this.sodaOpts.password));
193 | }
194 | if (this.sodaOpts.accessToken != null) {
195 | client.set('Authorization', "OAuth " + accessToken);
196 | }
197 | if (opts.query != null) {
198 | client.query(opts.query);
199 | }
200 | if (data != null) {
201 | client.send(data);
202 | }
203 | return function(responseHandler) {
204 | return client.end(responseHandler || _this.getDefaultHandler());
205 | };
206 | };
207 | }
208 |
209 | Connection.prototype.getDefaultHandler = function() {
210 | var emitter, handler;
211 | this.emitter = emitter = new EventEmitter(this.emitterOpts);
212 | return handler = function(error, response) {
213 | var _ref;
214 | if (response.ok) {
215 | if (response.accepted) {
216 | emitter.emit('progress', response.body);
217 | setTimeout((function() {
218 | return this.consumer.networker(opts)(handler);
219 | }), 5000);
220 | } else {
221 | emitter.emit('success', response.body);
222 | }
223 | } else {
224 | emitter.emit('error', (_ref = response.body) != null ? _ref : response.text);
225 | }
226 | return emitter.emit('complete', response);
227 | };
228 | };
229 |
230 | return Connection;
231 |
232 | })();
233 |
234 | Consumer = (function() {
235 | function Consumer(dataSite, sodaOpts) {
236 | this.dataSite = dataSite;
237 | this.sodaOpts = sodaOpts != null ? sodaOpts : {};
238 | this.connection = new Connection(this.dataSite, this.sodaOpts);
239 | }
240 |
241 | Consumer.prototype.query = function() {
242 | return new Query(this);
243 | };
244 |
245 | Consumer.prototype.getDataset = function(id) {
246 | var emitter;
247 | return emitter = new EventEmitter(this.emitterOpts);
248 | };
249 |
250 | return Consumer;
251 |
252 | })();
253 |
254 | Producer = (function() {
255 | function Producer(dataSite, sodaOpts) {
256 | this.dataSite = dataSite;
257 | this.sodaOpts = sodaOpts != null ? sodaOpts : {};
258 | this.connection = new Connection(this.dataSite, this.sodaOpts);
259 | }
260 |
261 | Producer.prototype.operation = function() {
262 | return new Operation(this);
263 | };
264 |
265 | return Producer;
266 |
267 | })();
268 |
269 | Operation = (function() {
270 | function Operation(producer) {
271 | this.producer = producer;
272 | }
273 |
274 | Operation.prototype.withDataset = function(datasetId) {
275 | this._datasetId = datasetId;
276 | return this;
277 | };
278 |
279 | Operation.prototype.truncate = function() {
280 | var opts;
281 | opts = {
282 | method: 'delete'
283 | };
284 | opts.path = "/resource/" + this._datasetId;
285 | return this._exec(opts);
286 | };
287 |
288 | Operation.prototype.add = function(data) {
289 | var obj, opts, _data, _i, _len;
290 | opts = {
291 | method: 'post'
292 | };
293 | opts.path = "/resource/" + this._datasetId;
294 | _data = JSON.parse(JSON.stringify(data));
295 | delete _data[':id'];
296 | delete _data[':delete'];
297 | for (_i = 0, _len = _data.length; _i < _len; _i++) {
298 | obj = _data[_i];
299 | delete obj[':id'];
300 | delete obj[':delete'];
301 | }
302 | return this._exec(opts, _data);
303 | };
304 |
305 | Operation.prototype["delete"] = function(id) {
306 | var opts;
307 | opts = {
308 | method: 'delete'
309 | };
310 | opts.path = "/resource/" + this._datasetId + "/" + id;
311 | return this._exec(opts);
312 | };
313 |
314 | Operation.prototype.update = function(id, data) {
315 | var opts;
316 | opts = {
317 | method: 'post'
318 | };
319 | opts.path = "/resource/" + this._datasetId + "/" + id;
320 | return this._exec(opts, data);
321 | };
322 |
323 | Operation.prototype.replace = function(id, data) {
324 | var opts;
325 | opts = {
326 | method: 'put'
327 | };
328 | opts.path = "/resource/" + this._datasetId + "/" + id;
329 | return this._exec(opts, data);
330 | };
331 |
332 | Operation.prototype.upsert = function(data) {
333 | var opts;
334 | opts = {
335 | method: 'post'
336 | };
337 | opts.path = "/resource/" + this._datasetId;
338 | return this._exec(opts, data);
339 | };
340 |
341 | Operation.prototype._exec = function(opts, data) {
342 | if (this._datasetId == null) {
343 | throw new Error('no dataset given to work against!');
344 | }
345 | this.producer.connection.networker(opts, data)();
346 | return this.producer.connection.emitter;
347 | };
348 |
349 | return Operation;
350 |
351 | })();
352 |
353 | Query = (function() {
354 | function Query(consumer) {
355 | this.consumer = consumer;
356 | this._select = [];
357 | this._where = [];
358 | this._group = [];
359 | this._having = [];
360 | this._order = [];
361 | this._offset = this._limit = this._q = null;
362 | }
363 |
364 | Query.prototype.withDataset = function(datasetId) {
365 | this._datasetId = datasetId;
366 | return this;
367 | };
368 |
369 | Query.prototype.soql = function(query) {
370 | this._soql = query;
371 | return this;
372 | };
373 |
374 | Query.prototype.select = function() {
375 | var select, selects, _i, _len;
376 | selects = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
377 | for (_i = 0, _len = selects.length; _i < _len; _i++) {
378 | select = selects[_i];
379 | this._select.push(select);
380 | }
381 | return this;
382 | };
383 |
384 | Query.prototype.where = function() {
385 | var args;
386 | args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
387 | addExpr(this._where, args);
388 | return this;
389 | };
390 |
391 | Query.prototype.having = function() {
392 | var args;
393 | args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
394 | addExpr(this._having, args);
395 | return this;
396 | };
397 |
398 | Query.prototype.group = function() {
399 | var group, groups, _i, _len;
400 | groups = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
401 | for (_i = 0, _len = groups.length; _i < _len; _i++) {
402 | group = groups[_i];
403 | this._group.push(group);
404 | }
405 | return this;
406 | };
407 |
408 | Query.prototype.order = function() {
409 | var order, orders, _i, _len;
410 | orders = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
411 | for (_i = 0, _len = orders.length; _i < _len; _i++) {
412 | order = orders[_i];
413 | this._order.push(handleOrder(order));
414 | }
415 | return this;
416 | };
417 |
418 | Query.prototype.offset = function(offset) {
419 | this._offset = offset;
420 | return this;
421 | };
422 |
423 | Query.prototype.limit = function(limit) {
424 | this._limit = limit;
425 | return this;
426 | };
427 |
428 | Query.prototype.q = function(q) {
429 | this._q = q;
430 | return this;
431 | };
432 |
433 | Query.prototype.getOpts = function() {
434 | var k, opts, queryComponents, v;
435 | opts = {
436 | method: 'get'
437 | };
438 | if (this._datasetId == null) {
439 | throw new Error('no dataset given to work against!');
440 | }
441 | opts.path = "/resource/" + this._datasetId + ".json";
442 | queryComponents = this._buildQueryComponents();
443 | opts.query = {};
444 | for (k in queryComponents) {
445 | v = queryComponents[k];
446 | opts.query['$' + k] = v;
447 | }
448 | return opts;
449 | };
450 |
451 | Query.prototype.getURL = function() {
452 | var opts, query;
453 | opts = this.getOpts();
454 | query = toQuerystring(opts.query);
455 | return ("https://" + this.consumer.dataSite + opts.path) + (query ? "?" + query : "");
456 | };
457 |
458 | Query.prototype.getRows = function() {
459 | var opts;
460 | opts = this.getOpts();
461 | this.consumer.connection.networker(opts)();
462 | return this.consumer.connection.emitter;
463 | };
464 |
465 | Query.prototype._buildQueryComponents = function() {
466 | var query;
467 | query = {};
468 | if (this._soql != null) {
469 | query.query = this._soql;
470 | } else {
471 | if (this._select.length > 0) {
472 | query.select = this._select.join(', ');
473 | }
474 | if (this._where.length > 0) {
475 | query.where = expr.and.apply(this, this._where);
476 | }
477 | if (this._group.length > 0) {
478 | query.group = this._group.join(', ');
479 | }
480 | if (this._having.length > 0) {
481 | if (!(this._group.length > 0)) {
482 | throw new Error('Having provided without group by!');
483 | }
484 | query.having = expr.and.apply(this, this._having);
485 | }
486 | if (this._order.length > 0) {
487 | query.order = this._order.join(', ');
488 | }
489 | if (isNumber(this._offset)) {
490 | query.offset = this._offset;
491 | }
492 | if (isNumber(this._limit)) {
493 | query.limit = this._limit;
494 | }
495 | if (this._q) {
496 | query.q = this._q;
497 | }
498 | }
499 | return query;
500 | };
501 |
502 | return Query;
503 |
504 | })();
505 |
506 | Dataset = (function() {
507 | function Dataset(data, client) {
508 | this.data = data;
509 | this.client = client;
510 | }
511 |
512 | return Dataset;
513 |
514 | })();
515 |
516 | extend(typeof exports !== "undefined" && exports !== null ? exports : this.soda, {
517 | Consumer: Consumer,
518 | Producer: Producer,
519 | expr: expr,
520 | _internal: {
521 | Connection: Connection,
522 | Query: Query,
523 | Operation: Operation,
524 | util: {
525 | toBase64: toBase64,
526 | handleLiteral: handleLiteral,
527 | handleOrder: handleOrder
528 | }
529 | }
530 | });
531 |
--------------------------------------------------------------------------------
/lib/soda-js.bundle.js:
--------------------------------------------------------------------------------
1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.soda = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0xFF) {
50 | throw new Error('Invalid character!');
51 | }
52 | enc1 = chr1 >> 2;
53 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
54 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
55 | enc4 = chr3 & 63;
56 | if (isNaN(chr2)) {
57 | enc3 = enc4 = 64;
58 | } else if (isNaN(chr3)) {
59 | enc4 = 64;
60 | }
61 | result.push(base64Lookup[enc1]);
62 | result.push(base64Lookup[enc2]);
63 | result.push(base64Lookup[enc3]);
64 | result.push(base64Lookup[enc4]);
65 | }
66 | return result.join('');
67 | }, function(str) {
68 | return rawToBase64(unescape(encodeURIComponent(str)));
69 | });
70 |
71 | handleLiteral = function(literal) {
72 | if (isString(literal)) {
73 | return "'" + literal + "'";
74 | } else if (isNumber(literal)) {
75 | return literal;
76 | } else {
77 | return literal;
78 | }
79 | };
80 |
81 | handleOrder = function(order) {
82 | if (/( asc$| desc$)/i.test(order)) {
83 | return order;
84 | } else {
85 | return order + ' asc';
86 | }
87 | };
88 |
89 | addExpr = function(target, args) {
90 | var arg, k, v, _i, _len, _results;
91 | _results = [];
92 | for (_i = 0, _len = args.length; _i < _len; _i++) {
93 | arg = args[_i];
94 | if (isString(arg)) {
95 | _results.push(target.push(arg));
96 | } else {
97 | _results.push((function() {
98 | var _results1;
99 | _results1 = [];
100 | for (k in arg) {
101 | v = arg[k];
102 | _results1.push(target.push("" + k + " = " + (handleLiteral(v))));
103 | }
104 | return _results1;
105 | })());
106 | }
107 | }
108 | return _results;
109 | };
110 |
111 | expr = {
112 | and: function() {
113 | var clause, clauses;
114 | clauses = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
115 | return ((function() {
116 | var _i, _len, _results;
117 | _results = [];
118 | for (_i = 0, _len = clauses.length; _i < _len; _i++) {
119 | clause = clauses[_i];
120 | _results.push("(" + clause + ")");
121 | }
122 | return _results;
123 | })()).join(' and ');
124 | },
125 | or: function() {
126 | var clause, clauses;
127 | clauses = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
128 | return ((function() {
129 | var _i, _len, _results;
130 | _results = [];
131 | for (_i = 0, _len = clauses.length; _i < _len; _i++) {
132 | clause = clauses[_i];
133 | _results.push("(" + clause + ")");
134 | }
135 | return _results;
136 | })()).join(' or ');
137 | },
138 | gt: function(column, literal) {
139 | return "" + column + " > " + (handleLiteral(literal));
140 | },
141 | gte: function(column, literal) {
142 | return "" + column + " >= " + (handleLiteral(literal));
143 | },
144 | lt: function(column, literal) {
145 | return "" + column + " < " + (handleLiteral(literal));
146 | },
147 | lte: function(column, literal) {
148 | return "" + column + " <= " + (handleLiteral(literal));
149 | },
150 | eq: function(column, literal) {
151 | return "" + column + " = " + (handleLiteral(literal));
152 | }
153 | };
154 |
155 | toQuerystring = function(obj) {
156 | var key, str, val;
157 | str = [];
158 | for (key in obj) {
159 | if (!__hasProp.call(obj, key)) continue;
160 | val = obj[key];
161 | str.push(encodeURIComponent(key) + '=' + encodeURIComponent(val));
162 | }
163 | return str.join('&');
164 | };
165 |
166 | Connection = (function() {
167 | function Connection(dataSite, sodaOpts) {
168 | var _ref;
169 | this.dataSite = dataSite;
170 | this.sodaOpts = sodaOpts != null ? sodaOpts : {};
171 | if (!/^[a-z0-9-_.]+(:[0-9]+)?$/i.test(this.dataSite)) {
172 | throw new Error('dataSite does not appear to be valid! Please supply a domain name, eg data.seattle.gov');
173 | }
174 | this.emitterOpts = (_ref = this.sodaOpts.emitterOpts) != null ? _ref : {
175 | wildcard: true,
176 | delimiter: '.',
177 | maxListeners: 15
178 | };
179 | this.networker = function(opts, data) {
180 | var client, url,
181 | _this = this;
182 | url = "https://" + this.dataSite + opts.path;
183 | client = httpClient(opts.method, url);
184 | if (data != null) {
185 | client.set('Accept', "application/json");
186 | }
187 | if (data != null) {
188 | client.set('Content-type', "application/json");
189 | }
190 | if (this.sodaOpts.apiToken != null) {
191 | client.set('X-App-Token', this.sodaOpts.apiToken);
192 | }
193 | if ((this.sodaOpts.username != null) && (this.sodaOpts.password != null)) {
194 | client.set('Authorization', "Basic " + toBase64("" + this.sodaOpts.username + ":" + this.sodaOpts.password));
195 | }
196 | if (this.sodaOpts.accessToken != null) {
197 | client.set('Authorization', "OAuth " + accessToken);
198 | }
199 | if (opts.query != null) {
200 | client.query(opts.query);
201 | }
202 | if (data != null) {
203 | client.send(data);
204 | }
205 | return function(responseHandler) {
206 | return client.end(responseHandler || _this.getDefaultHandler());
207 | };
208 | };
209 | }
210 |
211 | Connection.prototype.getDefaultHandler = function() {
212 | var emitter, handler;
213 | this.emitter = emitter = new EventEmitter(this.emitterOpts);
214 | return handler = function(error, response) {
215 | var _ref;
216 | if (response.ok) {
217 | if (response.accepted) {
218 | emitter.emit('progress', response.body);
219 | setTimeout((function() {
220 | return this.consumer.networker(opts)(handler);
221 | }), 5000);
222 | } else {
223 | emitter.emit('success', response.body);
224 | }
225 | } else {
226 | emitter.emit('error', (_ref = response.body) != null ? _ref : response.text);
227 | }
228 | return emitter.emit('complete', response);
229 | };
230 | };
231 |
232 | return Connection;
233 |
234 | })();
235 |
236 | Consumer = (function() {
237 | function Consumer(dataSite, sodaOpts) {
238 | this.dataSite = dataSite;
239 | this.sodaOpts = sodaOpts != null ? sodaOpts : {};
240 | this.connection = new Connection(this.dataSite, this.sodaOpts);
241 | }
242 |
243 | Consumer.prototype.query = function() {
244 | return new Query(this);
245 | };
246 |
247 | Consumer.prototype.getDataset = function(id) {
248 | var emitter;
249 | return emitter = new EventEmitter(this.emitterOpts);
250 | };
251 |
252 | return Consumer;
253 |
254 | })();
255 |
256 | Producer = (function() {
257 | function Producer(dataSite, sodaOpts) {
258 | this.dataSite = dataSite;
259 | this.sodaOpts = sodaOpts != null ? sodaOpts : {};
260 | this.connection = new Connection(this.dataSite, this.sodaOpts);
261 | }
262 |
263 | Producer.prototype.operation = function() {
264 | return new Operation(this);
265 | };
266 |
267 | return Producer;
268 |
269 | })();
270 |
271 | Operation = (function() {
272 | function Operation(producer) {
273 | this.producer = producer;
274 | }
275 |
276 | Operation.prototype.withDataset = function(datasetId) {
277 | this._datasetId = datasetId;
278 | return this;
279 | };
280 |
281 | Operation.prototype.truncate = function() {
282 | var opts;
283 | opts = {
284 | method: 'delete'
285 | };
286 | opts.path = "/resource/" + this._datasetId;
287 | return this._exec(opts);
288 | };
289 |
290 | Operation.prototype.add = function(data) {
291 | var obj, opts, _data, _i, _len;
292 | opts = {
293 | method: 'post'
294 | };
295 | opts.path = "/resource/" + this._datasetId;
296 | _data = JSON.parse(JSON.stringify(data));
297 | delete _data[':id'];
298 | delete _data[':delete'];
299 | for (_i = 0, _len = _data.length; _i < _len; _i++) {
300 | obj = _data[_i];
301 | delete obj[':id'];
302 | delete obj[':delete'];
303 | }
304 | return this._exec(opts, _data);
305 | };
306 |
307 | Operation.prototype["delete"] = function(id) {
308 | var opts;
309 | opts = {
310 | method: 'delete'
311 | };
312 | opts.path = "/resource/" + this._datasetId + "/" + id;
313 | return this._exec(opts);
314 | };
315 |
316 | Operation.prototype.update = function(id, data) {
317 | var opts;
318 | opts = {
319 | method: 'post'
320 | };
321 | opts.path = "/resource/" + this._datasetId + "/" + id;
322 | return this._exec(opts, data);
323 | };
324 |
325 | Operation.prototype.replace = function(id, data) {
326 | var opts;
327 | opts = {
328 | method: 'put'
329 | };
330 | opts.path = "/resource/" + this._datasetId + "/" + id;
331 | return this._exec(opts, data);
332 | };
333 |
334 | Operation.prototype.upsert = function(data) {
335 | var opts;
336 | opts = {
337 | method: 'post'
338 | };
339 | opts.path = "/resource/" + this._datasetId;
340 | return this._exec(opts, data);
341 | };
342 |
343 | Operation.prototype._exec = function(opts, data) {
344 | if (this._datasetId == null) {
345 | throw new Error('no dataset given to work against!');
346 | }
347 | this.producer.connection.networker(opts, data)();
348 | return this.producer.connection.emitter;
349 | };
350 |
351 | return Operation;
352 |
353 | })();
354 |
355 | Query = (function() {
356 | function Query(consumer) {
357 | this.consumer = consumer;
358 | this._select = [];
359 | this._where = [];
360 | this._group = [];
361 | this._having = [];
362 | this._order = [];
363 | this._offset = this._limit = this._q = null;
364 | }
365 |
366 | Query.prototype.withDataset = function(datasetId) {
367 | this._datasetId = datasetId;
368 | return this;
369 | };
370 |
371 | Query.prototype.soql = function(query) {
372 | this._soql = query;
373 | return this;
374 | };
375 |
376 | Query.prototype.select = function() {
377 | var select, selects, _i, _len;
378 | selects = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
379 | for (_i = 0, _len = selects.length; _i < _len; _i++) {
380 | select = selects[_i];
381 | this._select.push(select);
382 | }
383 | return this;
384 | };
385 |
386 | Query.prototype.where = function() {
387 | var args;
388 | args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
389 | addExpr(this._where, args);
390 | return this;
391 | };
392 |
393 | Query.prototype.having = function() {
394 | var args;
395 | args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
396 | addExpr(this._having, args);
397 | return this;
398 | };
399 |
400 | Query.prototype.group = function() {
401 | var group, groups, _i, _len;
402 | groups = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
403 | for (_i = 0, _len = groups.length; _i < _len; _i++) {
404 | group = groups[_i];
405 | this._group.push(group);
406 | }
407 | return this;
408 | };
409 |
410 | Query.prototype.order = function() {
411 | var order, orders, _i, _len;
412 | orders = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
413 | for (_i = 0, _len = orders.length; _i < _len; _i++) {
414 | order = orders[_i];
415 | this._order.push(handleOrder(order));
416 | }
417 | return this;
418 | };
419 |
420 | Query.prototype.offset = function(offset) {
421 | this._offset = offset;
422 | return this;
423 | };
424 |
425 | Query.prototype.limit = function(limit) {
426 | this._limit = limit;
427 | return this;
428 | };
429 |
430 | Query.prototype.q = function(q) {
431 | this._q = q;
432 | return this;
433 | };
434 |
435 | Query.prototype.getOpts = function() {
436 | var k, opts, queryComponents, v;
437 | opts = {
438 | method: 'get'
439 | };
440 | if (this._datasetId == null) {
441 | throw new Error('no dataset given to work against!');
442 | }
443 | opts.path = "/resource/" + this._datasetId + ".json";
444 | queryComponents = this._buildQueryComponents();
445 | opts.query = {};
446 | for (k in queryComponents) {
447 | v = queryComponents[k];
448 | opts.query['$' + k] = v;
449 | }
450 | return opts;
451 | };
452 |
453 | Query.prototype.getURL = function() {
454 | var opts, query;
455 | opts = this.getOpts();
456 | query = toQuerystring(opts.query);
457 | return ("https://" + this.consumer.dataSite + opts.path) + (query ? "?" + query : "");
458 | };
459 |
460 | Query.prototype.getRows = function() {
461 | var opts;
462 | opts = this.getOpts();
463 | this.consumer.connection.networker(opts)();
464 | return this.consumer.connection.emitter;
465 | };
466 |
467 | Query.prototype._buildQueryComponents = function() {
468 | var query;
469 | query = {};
470 | if (this._soql != null) {
471 | query.query = this._soql;
472 | } else {
473 | if (this._select.length > 0) {
474 | query.select = this._select.join(', ');
475 | }
476 | if (this._where.length > 0) {
477 | query.where = expr.and.apply(this, this._where);
478 | }
479 | if (this._group.length > 0) {
480 | query.group = this._group.join(', ');
481 | }
482 | if (this._having.length > 0) {
483 | if (!(this._group.length > 0)) {
484 | throw new Error('Having provided without group by!');
485 | }
486 | query.having = expr.and.apply(this, this._having);
487 | }
488 | if (this._order.length > 0) {
489 | query.order = this._order.join(', ');
490 | }
491 | if (isNumber(this._offset)) {
492 | query.offset = this._offset;
493 | }
494 | if (isNumber(this._limit)) {
495 | query.limit = this._limit;
496 | }
497 | if (this._q) {
498 | query.q = this._q;
499 | }
500 | }
501 | return query;
502 | };
503 |
504 | return Query;
505 |
506 | })();
507 |
508 | Dataset = (function() {
509 | function Dataset(data, client) {
510 | this.data = data;
511 | this.client = client;
512 | }
513 |
514 | return Dataset;
515 |
516 | })();
517 |
518 | extend(typeof exports !== "undefined" && exports !== null ? exports : this.soda, {
519 | Consumer: Consumer,
520 | Producer: Producer,
521 | expr: expr,
522 | _internal: {
523 | Connection: Connection,
524 | Query: Query,
525 | Operation: Operation,
526 | util: {
527 | toBase64: toBase64,
528 | handleLiteral: handleLiteral,
529 | handleOrder: handleOrder
530 | }
531 | }
532 | });
533 |
534 | }).call(this,require("buffer").Buffer)
535 | },{"buffer":3,"eventemitter2":6,"superagent":9}],2:[function(require,module,exports){
536 | var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
537 |
538 | ;(function (exports) {
539 | 'use strict';
540 |
541 | var Arr = (typeof Uint8Array !== 'undefined')
542 | ? Uint8Array
543 | : Array
544 |
545 | var PLUS = '+'.charCodeAt(0)
546 | var SLASH = '/'.charCodeAt(0)
547 | var NUMBER = '0'.charCodeAt(0)
548 | var LOWER = 'a'.charCodeAt(0)
549 | var UPPER = 'A'.charCodeAt(0)
550 | var PLUS_URL_SAFE = '-'.charCodeAt(0)
551 | var SLASH_URL_SAFE = '_'.charCodeAt(0)
552 |
553 | function decode (elt) {
554 | var code = elt.charCodeAt(0)
555 | if (code === PLUS ||
556 | code === PLUS_URL_SAFE)
557 | return 62 // '+'
558 | if (code === SLASH ||
559 | code === SLASH_URL_SAFE)
560 | return 63 // '/'
561 | if (code < NUMBER)
562 | return -1 //no match
563 | if (code < NUMBER + 10)
564 | return code - NUMBER + 26 + 26
565 | if (code < UPPER + 26)
566 | return code - UPPER
567 | if (code < LOWER + 26)
568 | return code - LOWER + 26
569 | }
570 |
571 | function b64ToByteArray (b64) {
572 | var i, j, l, tmp, placeHolders, arr
573 |
574 | if (b64.length % 4 > 0) {
575 | throw new Error('Invalid string. Length must be a multiple of 4')
576 | }
577 |
578 | // the number of equal signs (place holders)
579 | // if there are two placeholders, than the two characters before it
580 | // represent one byte
581 | // if there is only one, then the three characters before it represent 2 bytes
582 | // this is just a cheap hack to not do indexOf twice
583 | var len = b64.length
584 | placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
585 |
586 | // base64 is 4/3 + up to two characters of the original data
587 | arr = new Arr(b64.length * 3 / 4 - placeHolders)
588 |
589 | // if there are placeholders, only get up to the last complete 4 chars
590 | l = placeHolders > 0 ? b64.length - 4 : b64.length
591 |
592 | var L = 0
593 |
594 | function push (v) {
595 | arr[L++] = v
596 | }
597 |
598 | for (i = 0, j = 0; i < l; i += 4, j += 3) {
599 | tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
600 | push((tmp & 0xFF0000) >> 16)
601 | push((tmp & 0xFF00) >> 8)
602 | push(tmp & 0xFF)
603 | }
604 |
605 | if (placeHolders === 2) {
606 | tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
607 | push(tmp & 0xFF)
608 | } else if (placeHolders === 1) {
609 | tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
610 | push((tmp >> 8) & 0xFF)
611 | push(tmp & 0xFF)
612 | }
613 |
614 | return arr
615 | }
616 |
617 | function uint8ToBase64 (uint8) {
618 | var i,
619 | extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
620 | output = "",
621 | temp, length
622 |
623 | function encode (num) {
624 | return lookup.charAt(num)
625 | }
626 |
627 | function tripletToBase64 (num) {
628 | return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
629 | }
630 |
631 | // go through the array every three bytes, we'll deal with trailing stuff later
632 | for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
633 | temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
634 | output += tripletToBase64(temp)
635 | }
636 |
637 | // pad the end with zeros, but make sure to not forget the extra bytes
638 | switch (extraBytes) {
639 | case 1:
640 | temp = uint8[uint8.length - 1]
641 | output += encode(temp >> 2)
642 | output += encode((temp << 4) & 0x3F)
643 | output += '=='
644 | break
645 | case 2:
646 | temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
647 | output += encode(temp >> 10)
648 | output += encode((temp >> 4) & 0x3F)
649 | output += encode((temp << 2) & 0x3F)
650 | output += '='
651 | break
652 | }
653 |
654 | return output
655 | }
656 |
657 | exports.toByteArray = b64ToByteArray
658 | exports.fromByteArray = uint8ToBase64
659 | }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
660 |
661 | },{}],3:[function(require,module,exports){
662 | (function (global){
663 | /*!
664 | * The buffer module from node.js, for the browser.
665 | *
666 | * @author Feross Aboukhadijeh
667 | * @license MIT
668 | */
669 | /* eslint-disable no-proto */
670 |
671 | 'use strict'
672 |
673 | var base64 = require('base64-js')
674 | var ieee754 = require('ieee754')
675 | var isArray = require('isarray')
676 |
677 | exports.Buffer = Buffer
678 | exports.SlowBuffer = SlowBuffer
679 | exports.INSPECT_MAX_BYTES = 50
680 | Buffer.poolSize = 8192 // not used by this implementation
681 |
682 | var rootParent = {}
683 |
684 | /**
685 | * If `Buffer.TYPED_ARRAY_SUPPORT`:
686 | * === true Use Uint8Array implementation (fastest)
687 | * === false Use Object implementation (most compatible, even IE6)
688 | *
689 | * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
690 | * Opera 11.6+, iOS 4.2+.
691 | *
692 | * Due to various browser bugs, sometimes the Object implementation will be used even
693 | * when the browser supports typed arrays.
694 | *
695 | * Note:
696 | *
697 | * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
698 | * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
699 | *
700 | * - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
701 | * on objects.
702 | *
703 | * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
704 | *
705 | * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
706 | * incorrect length in some situations.
707 |
708 | * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
709 | * get the Object implementation, which is slower but behaves correctly.
710 | */
711 | Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
712 | ? global.TYPED_ARRAY_SUPPORT
713 | : typedArraySupport()
714 |
715 | function typedArraySupport () {
716 | function Bar () {}
717 | try {
718 | var arr = new Uint8Array(1)
719 | arr.foo = function () { return 42 }
720 | arr.constructor = Bar
721 | return arr.foo() === 42 && // typed array instances can be augmented
722 | arr.constructor === Bar && // constructor can be set
723 | typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
724 | arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
725 | } catch (e) {
726 | return false
727 | }
728 | }
729 |
730 | function kMaxLength () {
731 | return Buffer.TYPED_ARRAY_SUPPORT
732 | ? 0x7fffffff
733 | : 0x3fffffff
734 | }
735 |
736 | /**
737 | * Class: Buffer
738 | * =============
739 | *
740 | * The Buffer constructor returns instances of `Uint8Array` that are augmented
741 | * with function properties for all the node `Buffer` API functions. We use
742 | * `Uint8Array` so that square bracket notation works as expected -- it returns
743 | * a single octet.
744 | *
745 | * By augmenting the instances, we can avoid modifying the `Uint8Array`
746 | * prototype.
747 | */
748 | function Buffer (arg) {
749 | if (!(this instanceof Buffer)) {
750 | // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
751 | if (arguments.length > 1) return new Buffer(arg, arguments[1])
752 | return new Buffer(arg)
753 | }
754 |
755 | if (!Buffer.TYPED_ARRAY_SUPPORT) {
756 | this.length = 0
757 | this.parent = undefined
758 | }
759 |
760 | // Common case.
761 | if (typeof arg === 'number') {
762 | return fromNumber(this, arg)
763 | }
764 |
765 | // Slightly less common case.
766 | if (typeof arg === 'string') {
767 | return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
768 | }
769 |
770 | // Unusual.
771 | return fromObject(this, arg)
772 | }
773 |
774 | function fromNumber (that, length) {
775 | that = allocate(that, length < 0 ? 0 : checked(length) | 0)
776 | if (!Buffer.TYPED_ARRAY_SUPPORT) {
777 | for (var i = 0; i < length; i++) {
778 | that[i] = 0
779 | }
780 | }
781 | return that
782 | }
783 |
784 | function fromString (that, string, encoding) {
785 | if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
786 |
787 | // Assumption: byteLength() return value is always < kMaxLength.
788 | var length = byteLength(string, encoding) | 0
789 | that = allocate(that, length)
790 |
791 | that.write(string, encoding)
792 | return that
793 | }
794 |
795 | function fromObject (that, object) {
796 | if (Buffer.isBuffer(object)) return fromBuffer(that, object)
797 |
798 | if (isArray(object)) return fromArray(that, object)
799 |
800 | if (object == null) {
801 | throw new TypeError('must start with number, buffer, array or string')
802 | }
803 |
804 | if (typeof ArrayBuffer !== 'undefined') {
805 | if (object.buffer instanceof ArrayBuffer) {
806 | return fromTypedArray(that, object)
807 | }
808 | if (object instanceof ArrayBuffer) {
809 | return fromArrayBuffer(that, object)
810 | }
811 | }
812 |
813 | if (object.length) return fromArrayLike(that, object)
814 |
815 | return fromJsonObject(that, object)
816 | }
817 |
818 | function fromBuffer (that, buffer) {
819 | var length = checked(buffer.length) | 0
820 | that = allocate(that, length)
821 | buffer.copy(that, 0, 0, length)
822 | return that
823 | }
824 |
825 | function fromArray (that, array) {
826 | var length = checked(array.length) | 0
827 | that = allocate(that, length)
828 | for (var i = 0; i < length; i += 1) {
829 | that[i] = array[i] & 255
830 | }
831 | return that
832 | }
833 |
834 | // Duplicate of fromArray() to keep fromArray() monomorphic.
835 | function fromTypedArray (that, array) {
836 | var length = checked(array.length) | 0
837 | that = allocate(that, length)
838 | // Truncating the elements is probably not what people expect from typed
839 | // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
840 | // of the old Buffer constructor.
841 | for (var i = 0; i < length; i += 1) {
842 | that[i] = array[i] & 255
843 | }
844 | return that
845 | }
846 |
847 | function fromArrayBuffer (that, array) {
848 | if (Buffer.TYPED_ARRAY_SUPPORT) {
849 | // Return an augmented `Uint8Array` instance, for best performance
850 | array.byteLength
851 | that = Buffer._augment(new Uint8Array(array))
852 | } else {
853 | // Fallback: Return an object instance of the Buffer class
854 | that = fromTypedArray(that, new Uint8Array(array))
855 | }
856 | return that
857 | }
858 |
859 | function fromArrayLike (that, array) {
860 | var length = checked(array.length) | 0
861 | that = allocate(that, length)
862 | for (var i = 0; i < length; i += 1) {
863 | that[i] = array[i] & 255
864 | }
865 | return that
866 | }
867 |
868 | // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
869 | // Returns a zero-length buffer for inputs that don't conform to the spec.
870 | function fromJsonObject (that, object) {
871 | var array
872 | var length = 0
873 |
874 | if (object.type === 'Buffer' && isArray(object.data)) {
875 | array = object.data
876 | length = checked(array.length) | 0
877 | }
878 | that = allocate(that, length)
879 |
880 | for (var i = 0; i < length; i += 1) {
881 | that[i] = array[i] & 255
882 | }
883 | return that
884 | }
885 |
886 | if (Buffer.TYPED_ARRAY_SUPPORT) {
887 | Buffer.prototype.__proto__ = Uint8Array.prototype
888 | Buffer.__proto__ = Uint8Array
889 | } else {
890 | // pre-set for values that may exist in the future
891 | Buffer.prototype.length = undefined
892 | Buffer.prototype.parent = undefined
893 | }
894 |
895 | function allocate (that, length) {
896 | if (Buffer.TYPED_ARRAY_SUPPORT) {
897 | // Return an augmented `Uint8Array` instance, for best performance
898 | that = Buffer._augment(new Uint8Array(length))
899 | that.__proto__ = Buffer.prototype
900 | } else {
901 | // Fallback: Return an object instance of the Buffer class
902 | that.length = length
903 | that._isBuffer = true
904 | }
905 |
906 | var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
907 | if (fromPool) that.parent = rootParent
908 |
909 | return that
910 | }
911 |
912 | function checked (length) {
913 | // Note: cannot use `length < kMaxLength` here because that fails when
914 | // length is NaN (which is otherwise coerced to zero.)
915 | if (length >= kMaxLength()) {
916 | throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
917 | 'size: 0x' + kMaxLength().toString(16) + ' bytes')
918 | }
919 | return length | 0
920 | }
921 |
922 | function SlowBuffer (subject, encoding) {
923 | if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
924 |
925 | var buf = new Buffer(subject, encoding)
926 | delete buf.parent
927 | return buf
928 | }
929 |
930 | Buffer.isBuffer = function isBuffer (b) {
931 | return !!(b != null && b._isBuffer)
932 | }
933 |
934 | Buffer.compare = function compare (a, b) {
935 | if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
936 | throw new TypeError('Arguments must be Buffers')
937 | }
938 |
939 | if (a === b) return 0
940 |
941 | var x = a.length
942 | var y = b.length
943 |
944 | var i = 0
945 | var len = Math.min(x, y)
946 | while (i < len) {
947 | if (a[i] !== b[i]) break
948 |
949 | ++i
950 | }
951 |
952 | if (i !== len) {
953 | x = a[i]
954 | y = b[i]
955 | }
956 |
957 | if (x < y) return -1
958 | if (y < x) return 1
959 | return 0
960 | }
961 |
962 | Buffer.isEncoding = function isEncoding (encoding) {
963 | switch (String(encoding).toLowerCase()) {
964 | case 'hex':
965 | case 'utf8':
966 | case 'utf-8':
967 | case 'ascii':
968 | case 'binary':
969 | case 'base64':
970 | case 'raw':
971 | case 'ucs2':
972 | case 'ucs-2':
973 | case 'utf16le':
974 | case 'utf-16le':
975 | return true
976 | default:
977 | return false
978 | }
979 | }
980 |
981 | Buffer.concat = function concat (list, length) {
982 | if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
983 |
984 | if (list.length === 0) {
985 | return new Buffer(0)
986 | }
987 |
988 | var i
989 | if (length === undefined) {
990 | length = 0
991 | for (i = 0; i < list.length; i++) {
992 | length += list[i].length
993 | }
994 | }
995 |
996 | var buf = new Buffer(length)
997 | var pos = 0
998 | for (i = 0; i < list.length; i++) {
999 | var item = list[i]
1000 | item.copy(buf, pos)
1001 | pos += item.length
1002 | }
1003 | return buf
1004 | }
1005 |
1006 | function byteLength (string, encoding) {
1007 | if (typeof string !== 'string') string = '' + string
1008 |
1009 | var len = string.length
1010 | if (len === 0) return 0
1011 |
1012 | // Use a for loop to avoid recursion
1013 | var loweredCase = false
1014 | for (;;) {
1015 | switch (encoding) {
1016 | case 'ascii':
1017 | case 'binary':
1018 | // Deprecated
1019 | case 'raw':
1020 | case 'raws':
1021 | return len
1022 | case 'utf8':
1023 | case 'utf-8':
1024 | return utf8ToBytes(string).length
1025 | case 'ucs2':
1026 | case 'ucs-2':
1027 | case 'utf16le':
1028 | case 'utf-16le':
1029 | return len * 2
1030 | case 'hex':
1031 | return len >>> 1
1032 | case 'base64':
1033 | return base64ToBytes(string).length
1034 | default:
1035 | if (loweredCase) return utf8ToBytes(string).length // assume utf8
1036 | encoding = ('' + encoding).toLowerCase()
1037 | loweredCase = true
1038 | }
1039 | }
1040 | }
1041 | Buffer.byteLength = byteLength
1042 |
1043 | function slowToString (encoding, start, end) {
1044 | var loweredCase = false
1045 |
1046 | start = start | 0
1047 | end = end === undefined || end === Infinity ? this.length : end | 0
1048 |
1049 | if (!encoding) encoding = 'utf8'
1050 | if (start < 0) start = 0
1051 | if (end > this.length) end = this.length
1052 | if (end <= start) return ''
1053 |
1054 | while (true) {
1055 | switch (encoding) {
1056 | case 'hex':
1057 | return hexSlice(this, start, end)
1058 |
1059 | case 'utf8':
1060 | case 'utf-8':
1061 | return utf8Slice(this, start, end)
1062 |
1063 | case 'ascii':
1064 | return asciiSlice(this, start, end)
1065 |
1066 | case 'binary':
1067 | return binarySlice(this, start, end)
1068 |
1069 | case 'base64':
1070 | return base64Slice(this, start, end)
1071 |
1072 | case 'ucs2':
1073 | case 'ucs-2':
1074 | case 'utf16le':
1075 | case 'utf-16le':
1076 | return utf16leSlice(this, start, end)
1077 |
1078 | default:
1079 | if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
1080 | encoding = (encoding + '').toLowerCase()
1081 | loweredCase = true
1082 | }
1083 | }
1084 | }
1085 |
1086 | Buffer.prototype.toString = function toString () {
1087 | var length = this.length | 0
1088 | if (length === 0) return ''
1089 | if (arguments.length === 0) return utf8Slice(this, 0, length)
1090 | return slowToString.apply(this, arguments)
1091 | }
1092 |
1093 | Buffer.prototype.equals = function equals (b) {
1094 | if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
1095 | if (this === b) return true
1096 | return Buffer.compare(this, b) === 0
1097 | }
1098 |
1099 | Buffer.prototype.inspect = function inspect () {
1100 | var str = ''
1101 | var max = exports.INSPECT_MAX_BYTES
1102 | if (this.length > 0) {
1103 | str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
1104 | if (this.length > max) str += ' ... '
1105 | }
1106 | return ''
1107 | }
1108 |
1109 | Buffer.prototype.compare = function compare (b) {
1110 | if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
1111 | if (this === b) return 0
1112 | return Buffer.compare(this, b)
1113 | }
1114 |
1115 | Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
1116 | if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
1117 | else if (byteOffset < -0x80000000) byteOffset = -0x80000000
1118 | byteOffset >>= 0
1119 |
1120 | if (this.length === 0) return -1
1121 | if (byteOffset >= this.length) return -1
1122 |
1123 | // Negative offsets start from the end of the buffer
1124 | if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
1125 |
1126 | if (typeof val === 'string') {
1127 | if (val.length === 0) return -1 // special case: looking for empty string always fails
1128 | return String.prototype.indexOf.call(this, val, byteOffset)
1129 | }
1130 | if (Buffer.isBuffer(val)) {
1131 | return arrayIndexOf(this, val, byteOffset)
1132 | }
1133 | if (typeof val === 'number') {
1134 | if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
1135 | return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
1136 | }
1137 | return arrayIndexOf(this, [ val ], byteOffset)
1138 | }
1139 |
1140 | function arrayIndexOf (arr, val, byteOffset) {
1141 | var foundIndex = -1
1142 | for (var i = 0; byteOffset + i < arr.length; i++) {
1143 | if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
1144 | if (foundIndex === -1) foundIndex = i
1145 | if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
1146 | } else {
1147 | foundIndex = -1
1148 | }
1149 | }
1150 | return -1
1151 | }
1152 |
1153 | throw new TypeError('val must be string, number or Buffer')
1154 | }
1155 |
1156 | // `get` is deprecated
1157 | Buffer.prototype.get = function get (offset) {
1158 | console.log('.get() is deprecated. Access using array indexes instead.')
1159 | return this.readUInt8(offset)
1160 | }
1161 |
1162 | // `set` is deprecated
1163 | Buffer.prototype.set = function set (v, offset) {
1164 | console.log('.set() is deprecated. Access using array indexes instead.')
1165 | return this.writeUInt8(v, offset)
1166 | }
1167 |
1168 | function hexWrite (buf, string, offset, length) {
1169 | offset = Number(offset) || 0
1170 | var remaining = buf.length - offset
1171 | if (!length) {
1172 | length = remaining
1173 | } else {
1174 | length = Number(length)
1175 | if (length > remaining) {
1176 | length = remaining
1177 | }
1178 | }
1179 |
1180 | // must be an even number of digits
1181 | var strLen = string.length
1182 | if (strLen % 2 !== 0) throw new Error('Invalid hex string')
1183 |
1184 | if (length > strLen / 2) {
1185 | length = strLen / 2
1186 | }
1187 | for (var i = 0; i < length; i++) {
1188 | var parsed = parseInt(string.substr(i * 2, 2), 16)
1189 | if (isNaN(parsed)) throw new Error('Invalid hex string')
1190 | buf[offset + i] = parsed
1191 | }
1192 | return i
1193 | }
1194 |
1195 | function utf8Write (buf, string, offset, length) {
1196 | return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
1197 | }
1198 |
1199 | function asciiWrite (buf, string, offset, length) {
1200 | return blitBuffer(asciiToBytes(string), buf, offset, length)
1201 | }
1202 |
1203 | function binaryWrite (buf, string, offset, length) {
1204 | return asciiWrite(buf, string, offset, length)
1205 | }
1206 |
1207 | function base64Write (buf, string, offset, length) {
1208 | return blitBuffer(base64ToBytes(string), buf, offset, length)
1209 | }
1210 |
1211 | function ucs2Write (buf, string, offset, length) {
1212 | return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
1213 | }
1214 |
1215 | Buffer.prototype.write = function write (string, offset, length, encoding) {
1216 | // Buffer#write(string)
1217 | if (offset === undefined) {
1218 | encoding = 'utf8'
1219 | length = this.length
1220 | offset = 0
1221 | // Buffer#write(string, encoding)
1222 | } else if (length === undefined && typeof offset === 'string') {
1223 | encoding = offset
1224 | length = this.length
1225 | offset = 0
1226 | // Buffer#write(string, offset[, length][, encoding])
1227 | } else if (isFinite(offset)) {
1228 | offset = offset | 0
1229 | if (isFinite(length)) {
1230 | length = length | 0
1231 | if (encoding === undefined) encoding = 'utf8'
1232 | } else {
1233 | encoding = length
1234 | length = undefined
1235 | }
1236 | // legacy write(string, encoding, offset, length) - remove in v0.13
1237 | } else {
1238 | var swap = encoding
1239 | encoding = offset
1240 | offset = length | 0
1241 | length = swap
1242 | }
1243 |
1244 | var remaining = this.length - offset
1245 | if (length === undefined || length > remaining) length = remaining
1246 |
1247 | if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
1248 | throw new RangeError('attempt to write outside buffer bounds')
1249 | }
1250 |
1251 | if (!encoding) encoding = 'utf8'
1252 |
1253 | var loweredCase = false
1254 | for (;;) {
1255 | switch (encoding) {
1256 | case 'hex':
1257 | return hexWrite(this, string, offset, length)
1258 |
1259 | case 'utf8':
1260 | case 'utf-8':
1261 | return utf8Write(this, string, offset, length)
1262 |
1263 | case 'ascii':
1264 | return asciiWrite(this, string, offset, length)
1265 |
1266 | case 'binary':
1267 | return binaryWrite(this, string, offset, length)
1268 |
1269 | case 'base64':
1270 | // Warning: maxLength not taken into account in base64Write
1271 | return base64Write(this, string, offset, length)
1272 |
1273 | case 'ucs2':
1274 | case 'ucs-2':
1275 | case 'utf16le':
1276 | case 'utf-16le':
1277 | return ucs2Write(this, string, offset, length)
1278 |
1279 | default:
1280 | if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
1281 | encoding = ('' + encoding).toLowerCase()
1282 | loweredCase = true
1283 | }
1284 | }
1285 | }
1286 |
1287 | Buffer.prototype.toJSON = function toJSON () {
1288 | return {
1289 | type: 'Buffer',
1290 | data: Array.prototype.slice.call(this._arr || this, 0)
1291 | }
1292 | }
1293 |
1294 | function base64Slice (buf, start, end) {
1295 | if (start === 0 && end === buf.length) {
1296 | return base64.fromByteArray(buf)
1297 | } else {
1298 | return base64.fromByteArray(buf.slice(start, end))
1299 | }
1300 | }
1301 |
1302 | function utf8Slice (buf, start, end) {
1303 | end = Math.min(buf.length, end)
1304 | var res = []
1305 |
1306 | var i = start
1307 | while (i < end) {
1308 | var firstByte = buf[i]
1309 | var codePoint = null
1310 | var bytesPerSequence = (firstByte > 0xEF) ? 4
1311 | : (firstByte > 0xDF) ? 3
1312 | : (firstByte > 0xBF) ? 2
1313 | : 1
1314 |
1315 | if (i + bytesPerSequence <= end) {
1316 | var secondByte, thirdByte, fourthByte, tempCodePoint
1317 |
1318 | switch (bytesPerSequence) {
1319 | case 1:
1320 | if (firstByte < 0x80) {
1321 | codePoint = firstByte
1322 | }
1323 | break
1324 | case 2:
1325 | secondByte = buf[i + 1]
1326 | if ((secondByte & 0xC0) === 0x80) {
1327 | tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
1328 | if (tempCodePoint > 0x7F) {
1329 | codePoint = tempCodePoint
1330 | }
1331 | }
1332 | break
1333 | case 3:
1334 | secondByte = buf[i + 1]
1335 | thirdByte = buf[i + 2]
1336 | if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
1337 | tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
1338 | if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
1339 | codePoint = tempCodePoint
1340 | }
1341 | }
1342 | break
1343 | case 4:
1344 | secondByte = buf[i + 1]
1345 | thirdByte = buf[i + 2]
1346 | fourthByte = buf[i + 3]
1347 | if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
1348 | tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
1349 | if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
1350 | codePoint = tempCodePoint
1351 | }
1352 | }
1353 | }
1354 | }
1355 |
1356 | if (codePoint === null) {
1357 | // we did not generate a valid codePoint so insert a
1358 | // replacement char (U+FFFD) and advance only 1 byte
1359 | codePoint = 0xFFFD
1360 | bytesPerSequence = 1
1361 | } else if (codePoint > 0xFFFF) {
1362 | // encode to utf16 (surrogate pair dance)
1363 | codePoint -= 0x10000
1364 | res.push(codePoint >>> 10 & 0x3FF | 0xD800)
1365 | codePoint = 0xDC00 | codePoint & 0x3FF
1366 | }
1367 |
1368 | res.push(codePoint)
1369 | i += bytesPerSequence
1370 | }
1371 |
1372 | return decodeCodePointsArray(res)
1373 | }
1374 |
1375 | // Based on http://stackoverflow.com/a/22747272/680742, the browser with
1376 | // the lowest limit is Chrome, with 0x10000 args.
1377 | // We go 1 magnitude less, for safety
1378 | var MAX_ARGUMENTS_LENGTH = 0x1000
1379 |
1380 | function decodeCodePointsArray (codePoints) {
1381 | var len = codePoints.length
1382 | if (len <= MAX_ARGUMENTS_LENGTH) {
1383 | return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
1384 | }
1385 |
1386 | // Decode in chunks to avoid "call stack size exceeded".
1387 | var res = ''
1388 | var i = 0
1389 | while (i < len) {
1390 | res += String.fromCharCode.apply(
1391 | String,
1392 | codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
1393 | )
1394 | }
1395 | return res
1396 | }
1397 |
1398 | function asciiSlice (buf, start, end) {
1399 | var ret = ''
1400 | end = Math.min(buf.length, end)
1401 |
1402 | for (var i = start; i < end; i++) {
1403 | ret += String.fromCharCode(buf[i] & 0x7F)
1404 | }
1405 | return ret
1406 | }
1407 |
1408 | function binarySlice (buf, start, end) {
1409 | var ret = ''
1410 | end = Math.min(buf.length, end)
1411 |
1412 | for (var i = start; i < end; i++) {
1413 | ret += String.fromCharCode(buf[i])
1414 | }
1415 | return ret
1416 | }
1417 |
1418 | function hexSlice (buf, start, end) {
1419 | var len = buf.length
1420 |
1421 | if (!start || start < 0) start = 0
1422 | if (!end || end < 0 || end > len) end = len
1423 |
1424 | var out = ''
1425 | for (var i = start; i < end; i++) {
1426 | out += toHex(buf[i])
1427 | }
1428 | return out
1429 | }
1430 |
1431 | function utf16leSlice (buf, start, end) {
1432 | var bytes = buf.slice(start, end)
1433 | var res = ''
1434 | for (var i = 0; i < bytes.length; i += 2) {
1435 | res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
1436 | }
1437 | return res
1438 | }
1439 |
1440 | Buffer.prototype.slice = function slice (start, end) {
1441 | var len = this.length
1442 | start = ~~start
1443 | end = end === undefined ? len : ~~end
1444 |
1445 | if (start < 0) {
1446 | start += len
1447 | if (start < 0) start = 0
1448 | } else if (start > len) {
1449 | start = len
1450 | }
1451 |
1452 | if (end < 0) {
1453 | end += len
1454 | if (end < 0) end = 0
1455 | } else if (end > len) {
1456 | end = len
1457 | }
1458 |
1459 | if (end < start) end = start
1460 |
1461 | var newBuf
1462 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1463 | newBuf = Buffer._augment(this.subarray(start, end))
1464 | } else {
1465 | var sliceLen = end - start
1466 | newBuf = new Buffer(sliceLen, undefined)
1467 | for (var i = 0; i < sliceLen; i++) {
1468 | newBuf[i] = this[i + start]
1469 | }
1470 | }
1471 |
1472 | if (newBuf.length) newBuf.parent = this.parent || this
1473 |
1474 | return newBuf
1475 | }
1476 |
1477 | /*
1478 | * Need to make sure that buffer isn't trying to write out of bounds.
1479 | */
1480 | function checkOffset (offset, ext, length) {
1481 | if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
1482 | if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
1483 | }
1484 |
1485 | Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
1486 | offset = offset | 0
1487 | byteLength = byteLength | 0
1488 | if (!noAssert) checkOffset(offset, byteLength, this.length)
1489 |
1490 | var val = this[offset]
1491 | var mul = 1
1492 | var i = 0
1493 | while (++i < byteLength && (mul *= 0x100)) {
1494 | val += this[offset + i] * mul
1495 | }
1496 |
1497 | return val
1498 | }
1499 |
1500 | Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
1501 | offset = offset | 0
1502 | byteLength = byteLength | 0
1503 | if (!noAssert) {
1504 | checkOffset(offset, byteLength, this.length)
1505 | }
1506 |
1507 | var val = this[offset + --byteLength]
1508 | var mul = 1
1509 | while (byteLength > 0 && (mul *= 0x100)) {
1510 | val += this[offset + --byteLength] * mul
1511 | }
1512 |
1513 | return val
1514 | }
1515 |
1516 | Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
1517 | if (!noAssert) checkOffset(offset, 1, this.length)
1518 | return this[offset]
1519 | }
1520 |
1521 | Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
1522 | if (!noAssert) checkOffset(offset, 2, this.length)
1523 | return this[offset] | (this[offset + 1] << 8)
1524 | }
1525 |
1526 | Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
1527 | if (!noAssert) checkOffset(offset, 2, this.length)
1528 | return (this[offset] << 8) | this[offset + 1]
1529 | }
1530 |
1531 | Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
1532 | if (!noAssert) checkOffset(offset, 4, this.length)
1533 |
1534 | return ((this[offset]) |
1535 | (this[offset + 1] << 8) |
1536 | (this[offset + 2] << 16)) +
1537 | (this[offset + 3] * 0x1000000)
1538 | }
1539 |
1540 | Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
1541 | if (!noAssert) checkOffset(offset, 4, this.length)
1542 |
1543 | return (this[offset] * 0x1000000) +
1544 | ((this[offset + 1] << 16) |
1545 | (this[offset + 2] << 8) |
1546 | this[offset + 3])
1547 | }
1548 |
1549 | Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
1550 | offset = offset | 0
1551 | byteLength = byteLength | 0
1552 | if (!noAssert) checkOffset(offset, byteLength, this.length)
1553 |
1554 | var val = this[offset]
1555 | var mul = 1
1556 | var i = 0
1557 | while (++i < byteLength && (mul *= 0x100)) {
1558 | val += this[offset + i] * mul
1559 | }
1560 | mul *= 0x80
1561 |
1562 | if (val >= mul) val -= Math.pow(2, 8 * byteLength)
1563 |
1564 | return val
1565 | }
1566 |
1567 | Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
1568 | offset = offset | 0
1569 | byteLength = byteLength | 0
1570 | if (!noAssert) checkOffset(offset, byteLength, this.length)
1571 |
1572 | var i = byteLength
1573 | var mul = 1
1574 | var val = this[offset + --i]
1575 | while (i > 0 && (mul *= 0x100)) {
1576 | val += this[offset + --i] * mul
1577 | }
1578 | mul *= 0x80
1579 |
1580 | if (val >= mul) val -= Math.pow(2, 8 * byteLength)
1581 |
1582 | return val
1583 | }
1584 |
1585 | Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
1586 | if (!noAssert) checkOffset(offset, 1, this.length)
1587 | if (!(this[offset] & 0x80)) return (this[offset])
1588 | return ((0xff - this[offset] + 1) * -1)
1589 | }
1590 |
1591 | Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
1592 | if (!noAssert) checkOffset(offset, 2, this.length)
1593 | var val = this[offset] | (this[offset + 1] << 8)
1594 | return (val & 0x8000) ? val | 0xFFFF0000 : val
1595 | }
1596 |
1597 | Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
1598 | if (!noAssert) checkOffset(offset, 2, this.length)
1599 | var val = this[offset + 1] | (this[offset] << 8)
1600 | return (val & 0x8000) ? val | 0xFFFF0000 : val
1601 | }
1602 |
1603 | Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
1604 | if (!noAssert) checkOffset(offset, 4, this.length)
1605 |
1606 | return (this[offset]) |
1607 | (this[offset + 1] << 8) |
1608 | (this[offset + 2] << 16) |
1609 | (this[offset + 3] << 24)
1610 | }
1611 |
1612 | Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
1613 | if (!noAssert) checkOffset(offset, 4, this.length)
1614 |
1615 | return (this[offset] << 24) |
1616 | (this[offset + 1] << 16) |
1617 | (this[offset + 2] << 8) |
1618 | (this[offset + 3])
1619 | }
1620 |
1621 | Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
1622 | if (!noAssert) checkOffset(offset, 4, this.length)
1623 | return ieee754.read(this, offset, true, 23, 4)
1624 | }
1625 |
1626 | Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
1627 | if (!noAssert) checkOffset(offset, 4, this.length)
1628 | return ieee754.read(this, offset, false, 23, 4)
1629 | }
1630 |
1631 | Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
1632 | if (!noAssert) checkOffset(offset, 8, this.length)
1633 | return ieee754.read(this, offset, true, 52, 8)
1634 | }
1635 |
1636 | Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
1637 | if (!noAssert) checkOffset(offset, 8, this.length)
1638 | return ieee754.read(this, offset, false, 52, 8)
1639 | }
1640 |
1641 | function checkInt (buf, value, offset, ext, max, min) {
1642 | if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
1643 | if (value > max || value < min) throw new RangeError('value is out of bounds')
1644 | if (offset + ext > buf.length) throw new RangeError('index out of range')
1645 | }
1646 |
1647 | Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
1648 | value = +value
1649 | offset = offset | 0
1650 | byteLength = byteLength | 0
1651 | if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
1652 |
1653 | var mul = 1
1654 | var i = 0
1655 | this[offset] = value & 0xFF
1656 | while (++i < byteLength && (mul *= 0x100)) {
1657 | this[offset + i] = (value / mul) & 0xFF
1658 | }
1659 |
1660 | return offset + byteLength
1661 | }
1662 |
1663 | Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
1664 | value = +value
1665 | offset = offset | 0
1666 | byteLength = byteLength | 0
1667 | if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
1668 |
1669 | var i = byteLength - 1
1670 | var mul = 1
1671 | this[offset + i] = value & 0xFF
1672 | while (--i >= 0 && (mul *= 0x100)) {
1673 | this[offset + i] = (value / mul) & 0xFF
1674 | }
1675 |
1676 | return offset + byteLength
1677 | }
1678 |
1679 | Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
1680 | value = +value
1681 | offset = offset | 0
1682 | if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
1683 | if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
1684 | this[offset] = (value & 0xff)
1685 | return offset + 1
1686 | }
1687 |
1688 | function objectWriteUInt16 (buf, value, offset, littleEndian) {
1689 | if (value < 0) value = 0xffff + value + 1
1690 | for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
1691 | buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
1692 | (littleEndian ? i : 1 - i) * 8
1693 | }
1694 | }
1695 |
1696 | Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
1697 | value = +value
1698 | offset = offset | 0
1699 | if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
1700 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1701 | this[offset] = (value & 0xff)
1702 | this[offset + 1] = (value >>> 8)
1703 | } else {
1704 | objectWriteUInt16(this, value, offset, true)
1705 | }
1706 | return offset + 2
1707 | }
1708 |
1709 | Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
1710 | value = +value
1711 | offset = offset | 0
1712 | if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
1713 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1714 | this[offset] = (value >>> 8)
1715 | this[offset + 1] = (value & 0xff)
1716 | } else {
1717 | objectWriteUInt16(this, value, offset, false)
1718 | }
1719 | return offset + 2
1720 | }
1721 |
1722 | function objectWriteUInt32 (buf, value, offset, littleEndian) {
1723 | if (value < 0) value = 0xffffffff + value + 1
1724 | for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
1725 | buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
1726 | }
1727 | }
1728 |
1729 | Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
1730 | value = +value
1731 | offset = offset | 0
1732 | if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
1733 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1734 | this[offset + 3] = (value >>> 24)
1735 | this[offset + 2] = (value >>> 16)
1736 | this[offset + 1] = (value >>> 8)
1737 | this[offset] = (value & 0xff)
1738 | } else {
1739 | objectWriteUInt32(this, value, offset, true)
1740 | }
1741 | return offset + 4
1742 | }
1743 |
1744 | Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
1745 | value = +value
1746 | offset = offset | 0
1747 | if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
1748 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1749 | this[offset] = (value >>> 24)
1750 | this[offset + 1] = (value >>> 16)
1751 | this[offset + 2] = (value >>> 8)
1752 | this[offset + 3] = (value & 0xff)
1753 | } else {
1754 | objectWriteUInt32(this, value, offset, false)
1755 | }
1756 | return offset + 4
1757 | }
1758 |
1759 | Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
1760 | value = +value
1761 | offset = offset | 0
1762 | if (!noAssert) {
1763 | var limit = Math.pow(2, 8 * byteLength - 1)
1764 |
1765 | checkInt(this, value, offset, byteLength, limit - 1, -limit)
1766 | }
1767 |
1768 | var i = 0
1769 | var mul = 1
1770 | var sub = value < 0 ? 1 : 0
1771 | this[offset] = value & 0xFF
1772 | while (++i < byteLength && (mul *= 0x100)) {
1773 | this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
1774 | }
1775 |
1776 | return offset + byteLength
1777 | }
1778 |
1779 | Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
1780 | value = +value
1781 | offset = offset | 0
1782 | if (!noAssert) {
1783 | var limit = Math.pow(2, 8 * byteLength - 1)
1784 |
1785 | checkInt(this, value, offset, byteLength, limit - 1, -limit)
1786 | }
1787 |
1788 | var i = byteLength - 1
1789 | var mul = 1
1790 | var sub = value < 0 ? 1 : 0
1791 | this[offset + i] = value & 0xFF
1792 | while (--i >= 0 && (mul *= 0x100)) {
1793 | this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
1794 | }
1795 |
1796 | return offset + byteLength
1797 | }
1798 |
1799 | Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
1800 | value = +value
1801 | offset = offset | 0
1802 | if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
1803 | if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
1804 | if (value < 0) value = 0xff + value + 1
1805 | this[offset] = (value & 0xff)
1806 | return offset + 1
1807 | }
1808 |
1809 | Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
1810 | value = +value
1811 | offset = offset | 0
1812 | if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
1813 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1814 | this[offset] = (value & 0xff)
1815 | this[offset + 1] = (value >>> 8)
1816 | } else {
1817 | objectWriteUInt16(this, value, offset, true)
1818 | }
1819 | return offset + 2
1820 | }
1821 |
1822 | Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
1823 | value = +value
1824 | offset = offset | 0
1825 | if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
1826 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1827 | this[offset] = (value >>> 8)
1828 | this[offset + 1] = (value & 0xff)
1829 | } else {
1830 | objectWriteUInt16(this, value, offset, false)
1831 | }
1832 | return offset + 2
1833 | }
1834 |
1835 | Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
1836 | value = +value
1837 | offset = offset | 0
1838 | if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
1839 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1840 | this[offset] = (value & 0xff)
1841 | this[offset + 1] = (value >>> 8)
1842 | this[offset + 2] = (value >>> 16)
1843 | this[offset + 3] = (value >>> 24)
1844 | } else {
1845 | objectWriteUInt32(this, value, offset, true)
1846 | }
1847 | return offset + 4
1848 | }
1849 |
1850 | Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
1851 | value = +value
1852 | offset = offset | 0
1853 | if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
1854 | if (value < 0) value = 0xffffffff + value + 1
1855 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1856 | this[offset] = (value >>> 24)
1857 | this[offset + 1] = (value >>> 16)
1858 | this[offset + 2] = (value >>> 8)
1859 | this[offset + 3] = (value & 0xff)
1860 | } else {
1861 | objectWriteUInt32(this, value, offset, false)
1862 | }
1863 | return offset + 4
1864 | }
1865 |
1866 | function checkIEEE754 (buf, value, offset, ext, max, min) {
1867 | if (value > max || value < min) throw new RangeError('value is out of bounds')
1868 | if (offset + ext > buf.length) throw new RangeError('index out of range')
1869 | if (offset < 0) throw new RangeError('index out of range')
1870 | }
1871 |
1872 | function writeFloat (buf, value, offset, littleEndian, noAssert) {
1873 | if (!noAssert) {
1874 | checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
1875 | }
1876 | ieee754.write(buf, value, offset, littleEndian, 23, 4)
1877 | return offset + 4
1878 | }
1879 |
1880 | Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
1881 | return writeFloat(this, value, offset, true, noAssert)
1882 | }
1883 |
1884 | Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
1885 | return writeFloat(this, value, offset, false, noAssert)
1886 | }
1887 |
1888 | function writeDouble (buf, value, offset, littleEndian, noAssert) {
1889 | if (!noAssert) {
1890 | checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
1891 | }
1892 | ieee754.write(buf, value, offset, littleEndian, 52, 8)
1893 | return offset + 8
1894 | }
1895 |
1896 | Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
1897 | return writeDouble(this, value, offset, true, noAssert)
1898 | }
1899 |
1900 | Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
1901 | return writeDouble(this, value, offset, false, noAssert)
1902 | }
1903 |
1904 | // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
1905 | Buffer.prototype.copy = function copy (target, targetStart, start, end) {
1906 | if (!start) start = 0
1907 | if (!end && end !== 0) end = this.length
1908 | if (targetStart >= target.length) targetStart = target.length
1909 | if (!targetStart) targetStart = 0
1910 | if (end > 0 && end < start) end = start
1911 |
1912 | // Copy 0 bytes; we're done
1913 | if (end === start) return 0
1914 | if (target.length === 0 || this.length === 0) return 0
1915 |
1916 | // Fatal error conditions
1917 | if (targetStart < 0) {
1918 | throw new RangeError('targetStart out of bounds')
1919 | }
1920 | if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
1921 | if (end < 0) throw new RangeError('sourceEnd out of bounds')
1922 |
1923 | // Are we oob?
1924 | if (end > this.length) end = this.length
1925 | if (target.length - targetStart < end - start) {
1926 | end = target.length - targetStart + start
1927 | }
1928 |
1929 | var len = end - start
1930 | var i
1931 |
1932 | if (this === target && start < targetStart && targetStart < end) {
1933 | // descending copy from end
1934 | for (i = len - 1; i >= 0; i--) {
1935 | target[i + targetStart] = this[i + start]
1936 | }
1937 | } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
1938 | // ascending copy from start
1939 | for (i = 0; i < len; i++) {
1940 | target[i + targetStart] = this[i + start]
1941 | }
1942 | } else {
1943 | target._set(this.subarray(start, start + len), targetStart)
1944 | }
1945 |
1946 | return len
1947 | }
1948 |
1949 | // fill(value, start=0, end=buffer.length)
1950 | Buffer.prototype.fill = function fill (value, start, end) {
1951 | if (!value) value = 0
1952 | if (!start) start = 0
1953 | if (!end) end = this.length
1954 |
1955 | if (end < start) throw new RangeError('end < start')
1956 |
1957 | // Fill 0 bytes; we're done
1958 | if (end === start) return
1959 | if (this.length === 0) return
1960 |
1961 | if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
1962 | if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
1963 |
1964 | var i
1965 | if (typeof value === 'number') {
1966 | for (i = start; i < end; i++) {
1967 | this[i] = value
1968 | }
1969 | } else {
1970 | var bytes = utf8ToBytes(value.toString())
1971 | var len = bytes.length
1972 | for (i = start; i < end; i++) {
1973 | this[i] = bytes[i % len]
1974 | }
1975 | }
1976 |
1977 | return this
1978 | }
1979 |
1980 | /**
1981 | * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
1982 | * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
1983 | */
1984 | Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
1985 | if (typeof Uint8Array !== 'undefined') {
1986 | if (Buffer.TYPED_ARRAY_SUPPORT) {
1987 | return (new Buffer(this)).buffer
1988 | } else {
1989 | var buf = new Uint8Array(this.length)
1990 | for (var i = 0, len = buf.length; i < len; i += 1) {
1991 | buf[i] = this[i]
1992 | }
1993 | return buf.buffer
1994 | }
1995 | } else {
1996 | throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
1997 | }
1998 | }
1999 |
2000 | // HELPER FUNCTIONS
2001 | // ================
2002 |
2003 | var BP = Buffer.prototype
2004 |
2005 | /**
2006 | * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
2007 | */
2008 | Buffer._augment = function _augment (arr) {
2009 | arr.constructor = Buffer
2010 | arr._isBuffer = true
2011 |
2012 | // save reference to original Uint8Array set method before overwriting
2013 | arr._set = arr.set
2014 |
2015 | // deprecated
2016 | arr.get = BP.get
2017 | arr.set = BP.set
2018 |
2019 | arr.write = BP.write
2020 | arr.toString = BP.toString
2021 | arr.toLocaleString = BP.toString
2022 | arr.toJSON = BP.toJSON
2023 | arr.equals = BP.equals
2024 | arr.compare = BP.compare
2025 | arr.indexOf = BP.indexOf
2026 | arr.copy = BP.copy
2027 | arr.slice = BP.slice
2028 | arr.readUIntLE = BP.readUIntLE
2029 | arr.readUIntBE = BP.readUIntBE
2030 | arr.readUInt8 = BP.readUInt8
2031 | arr.readUInt16LE = BP.readUInt16LE
2032 | arr.readUInt16BE = BP.readUInt16BE
2033 | arr.readUInt32LE = BP.readUInt32LE
2034 | arr.readUInt32BE = BP.readUInt32BE
2035 | arr.readIntLE = BP.readIntLE
2036 | arr.readIntBE = BP.readIntBE
2037 | arr.readInt8 = BP.readInt8
2038 | arr.readInt16LE = BP.readInt16LE
2039 | arr.readInt16BE = BP.readInt16BE
2040 | arr.readInt32LE = BP.readInt32LE
2041 | arr.readInt32BE = BP.readInt32BE
2042 | arr.readFloatLE = BP.readFloatLE
2043 | arr.readFloatBE = BP.readFloatBE
2044 | arr.readDoubleLE = BP.readDoubleLE
2045 | arr.readDoubleBE = BP.readDoubleBE
2046 | arr.writeUInt8 = BP.writeUInt8
2047 | arr.writeUIntLE = BP.writeUIntLE
2048 | arr.writeUIntBE = BP.writeUIntBE
2049 | arr.writeUInt16LE = BP.writeUInt16LE
2050 | arr.writeUInt16BE = BP.writeUInt16BE
2051 | arr.writeUInt32LE = BP.writeUInt32LE
2052 | arr.writeUInt32BE = BP.writeUInt32BE
2053 | arr.writeIntLE = BP.writeIntLE
2054 | arr.writeIntBE = BP.writeIntBE
2055 | arr.writeInt8 = BP.writeInt8
2056 | arr.writeInt16LE = BP.writeInt16LE
2057 | arr.writeInt16BE = BP.writeInt16BE
2058 | arr.writeInt32LE = BP.writeInt32LE
2059 | arr.writeInt32BE = BP.writeInt32BE
2060 | arr.writeFloatLE = BP.writeFloatLE
2061 | arr.writeFloatBE = BP.writeFloatBE
2062 | arr.writeDoubleLE = BP.writeDoubleLE
2063 | arr.writeDoubleBE = BP.writeDoubleBE
2064 | arr.fill = BP.fill
2065 | arr.inspect = BP.inspect
2066 | arr.toArrayBuffer = BP.toArrayBuffer
2067 |
2068 | return arr
2069 | }
2070 |
2071 | var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
2072 |
2073 | function base64clean (str) {
2074 | // Node strips out invalid characters like \n and \t from the string, base64-js does not
2075 | str = stringtrim(str).replace(INVALID_BASE64_RE, '')
2076 | // Node converts strings with length < 2 to ''
2077 | if (str.length < 2) return ''
2078 | // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
2079 | while (str.length % 4 !== 0) {
2080 | str = str + '='
2081 | }
2082 | return str
2083 | }
2084 |
2085 | function stringtrim (str) {
2086 | if (str.trim) return str.trim()
2087 | return str.replace(/^\s+|\s+$/g, '')
2088 | }
2089 |
2090 | function toHex (n) {
2091 | if (n < 16) return '0' + n.toString(16)
2092 | return n.toString(16)
2093 | }
2094 |
2095 | function utf8ToBytes (string, units) {
2096 | units = units || Infinity
2097 | var codePoint
2098 | var length = string.length
2099 | var leadSurrogate = null
2100 | var bytes = []
2101 |
2102 | for (var i = 0; i < length; i++) {
2103 | codePoint = string.charCodeAt(i)
2104 |
2105 | // is surrogate component
2106 | if (codePoint > 0xD7FF && codePoint < 0xE000) {
2107 | // last char was a lead
2108 | if (!leadSurrogate) {
2109 | // no lead yet
2110 | if (codePoint > 0xDBFF) {
2111 | // unexpected trail
2112 | if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
2113 | continue
2114 | } else if (i + 1 === length) {
2115 | // unpaired lead
2116 | if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
2117 | continue
2118 | }
2119 |
2120 | // valid lead
2121 | leadSurrogate = codePoint
2122 |
2123 | continue
2124 | }
2125 |
2126 | // 2 leads in a row
2127 | if (codePoint < 0xDC00) {
2128 | if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
2129 | leadSurrogate = codePoint
2130 | continue
2131 | }
2132 |
2133 | // valid surrogate pair
2134 | codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
2135 | } else if (leadSurrogate) {
2136 | // valid bmp char, but last char was a lead
2137 | if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
2138 | }
2139 |
2140 | leadSurrogate = null
2141 |
2142 | // encode utf8
2143 | if (codePoint < 0x80) {
2144 | if ((units -= 1) < 0) break
2145 | bytes.push(codePoint)
2146 | } else if (codePoint < 0x800) {
2147 | if ((units -= 2) < 0) break
2148 | bytes.push(
2149 | codePoint >> 0x6 | 0xC0,
2150 | codePoint & 0x3F | 0x80
2151 | )
2152 | } else if (codePoint < 0x10000) {
2153 | if ((units -= 3) < 0) break
2154 | bytes.push(
2155 | codePoint >> 0xC | 0xE0,
2156 | codePoint >> 0x6 & 0x3F | 0x80,
2157 | codePoint & 0x3F | 0x80
2158 | )
2159 | } else if (codePoint < 0x110000) {
2160 | if ((units -= 4) < 0) break
2161 | bytes.push(
2162 | codePoint >> 0x12 | 0xF0,
2163 | codePoint >> 0xC & 0x3F | 0x80,
2164 | codePoint >> 0x6 & 0x3F | 0x80,
2165 | codePoint & 0x3F | 0x80
2166 | )
2167 | } else {
2168 | throw new Error('Invalid code point')
2169 | }
2170 | }
2171 |
2172 | return bytes
2173 | }
2174 |
2175 | function asciiToBytes (str) {
2176 | var byteArray = []
2177 | for (var i = 0; i < str.length; i++) {
2178 | // Node's code seems to be doing this and not & 0x7F..
2179 | byteArray.push(str.charCodeAt(i) & 0xFF)
2180 | }
2181 | return byteArray
2182 | }
2183 |
2184 | function utf16leToBytes (str, units) {
2185 | var c, hi, lo
2186 | var byteArray = []
2187 | for (var i = 0; i < str.length; i++) {
2188 | if ((units -= 2) < 0) break
2189 |
2190 | c = str.charCodeAt(i)
2191 | hi = c >> 8
2192 | lo = c % 256
2193 | byteArray.push(lo)
2194 | byteArray.push(hi)
2195 | }
2196 |
2197 | return byteArray
2198 | }
2199 |
2200 | function base64ToBytes (str) {
2201 | return base64.toByteArray(base64clean(str))
2202 | }
2203 |
2204 | function blitBuffer (src, dst, offset, length) {
2205 | for (var i = 0; i < length; i++) {
2206 | if ((i + offset >= dst.length) || (i >= src.length)) break
2207 | dst[i + offset] = src[i]
2208 | }
2209 | return i
2210 | }
2211 |
2212 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
2213 | },{"base64-js":2,"ieee754":7,"isarray":4}],4:[function(require,module,exports){
2214 | var toString = {}.toString;
2215 |
2216 | module.exports = Array.isArray || function (arr) {
2217 | return toString.call(arr) == '[object Array]';
2218 | };
2219 |
2220 | },{}],5:[function(require,module,exports){
2221 |
2222 | /**
2223 | * Expose `Emitter`.
2224 | */
2225 |
2226 | module.exports = Emitter;
2227 |
2228 | /**
2229 | * Initialize a new `Emitter`.
2230 | *
2231 | * @api public
2232 | */
2233 |
2234 | function Emitter(obj) {
2235 | if (obj) return mixin(obj);
2236 | };
2237 |
2238 | /**
2239 | * Mixin the emitter properties.
2240 | *
2241 | * @param {Object} obj
2242 | * @return {Object}
2243 | * @api private
2244 | */
2245 |
2246 | function mixin(obj) {
2247 | for (var key in Emitter.prototype) {
2248 | obj[key] = Emitter.prototype[key];
2249 | }
2250 | return obj;
2251 | }
2252 |
2253 | /**
2254 | * Listen on the given `event` with `fn`.
2255 | *
2256 | * @param {String} event
2257 | * @param {Function} fn
2258 | * @return {Emitter}
2259 | * @api public
2260 | */
2261 |
2262 | Emitter.prototype.on =
2263 | Emitter.prototype.addEventListener = function(event, fn){
2264 | this._callbacks = this._callbacks || {};
2265 | (this._callbacks[event] = this._callbacks[event] || [])
2266 | .push(fn);
2267 | return this;
2268 | };
2269 |
2270 | /**
2271 | * Adds an `event` listener that will be invoked a single
2272 | * time then automatically removed.
2273 | *
2274 | * @param {String} event
2275 | * @param {Function} fn
2276 | * @return {Emitter}
2277 | * @api public
2278 | */
2279 |
2280 | Emitter.prototype.once = function(event, fn){
2281 | var self = this;
2282 | this._callbacks = this._callbacks || {};
2283 |
2284 | function on() {
2285 | self.off(event, on);
2286 | fn.apply(this, arguments);
2287 | }
2288 |
2289 | on.fn = fn;
2290 | this.on(event, on);
2291 | return this;
2292 | };
2293 |
2294 | /**
2295 | * Remove the given callback for `event` or all
2296 | * registered callbacks.
2297 | *
2298 | * @param {String} event
2299 | * @param {Function} fn
2300 | * @return {Emitter}
2301 | * @api public
2302 | */
2303 |
2304 | Emitter.prototype.off =
2305 | Emitter.prototype.removeListener =
2306 | Emitter.prototype.removeAllListeners =
2307 | Emitter.prototype.removeEventListener = function(event, fn){
2308 | this._callbacks = this._callbacks || {};
2309 |
2310 | // all
2311 | if (0 == arguments.length) {
2312 | this._callbacks = {};
2313 | return this;
2314 | }
2315 |
2316 | // specific event
2317 | var callbacks = this._callbacks[event];
2318 | if (!callbacks) return this;
2319 |
2320 | // remove all handlers
2321 | if (1 == arguments.length) {
2322 | delete this._callbacks[event];
2323 | return this;
2324 | }
2325 |
2326 | // remove specific handler
2327 | var cb;
2328 | for (var i = 0; i < callbacks.length; i++) {
2329 | cb = callbacks[i];
2330 | if (cb === fn || cb.fn === fn) {
2331 | callbacks.splice(i, 1);
2332 | break;
2333 | }
2334 | }
2335 | return this;
2336 | };
2337 |
2338 | /**
2339 | * Emit `event` with the given args.
2340 | *
2341 | * @param {String} event
2342 | * @param {Mixed} ...
2343 | * @return {Emitter}
2344 | */
2345 |
2346 | Emitter.prototype.emit = function(event){
2347 | this._callbacks = this._callbacks || {};
2348 | var args = [].slice.call(arguments, 1)
2349 | , callbacks = this._callbacks[event];
2350 |
2351 | if (callbacks) {
2352 | callbacks = callbacks.slice(0);
2353 | for (var i = 0, len = callbacks.length; i < len; ++i) {
2354 | callbacks[i].apply(this, args);
2355 | }
2356 | }
2357 |
2358 | return this;
2359 | };
2360 |
2361 | /**
2362 | * Return array of callbacks for `event`.
2363 | *
2364 | * @param {String} event
2365 | * @return {Array}
2366 | * @api public
2367 | */
2368 |
2369 | Emitter.prototype.listeners = function(event){
2370 | this._callbacks = this._callbacks || {};
2371 | return this._callbacks[event] || [];
2372 | };
2373 |
2374 | /**
2375 | * Check if this emitter has `event` handlers.
2376 | *
2377 | * @param {String} event
2378 | * @return {Boolean}
2379 | * @api public
2380 | */
2381 |
2382 | Emitter.prototype.hasListeners = function(event){
2383 | return !! this.listeners(event).length;
2384 | };
2385 |
2386 | },{}],6:[function(require,module,exports){
2387 | /*!
2388 | * EventEmitter2
2389 | * https://github.com/hij1nx/EventEmitter2
2390 | *
2391 | * Copyright (c) 2013 hij1nx
2392 | * Licensed under the MIT license.
2393 | */
2394 | ;!function(undefined) {
2395 |
2396 | var isArray = Array.isArray ? Array.isArray : function _isArray(obj) {
2397 | return Object.prototype.toString.call(obj) === "[object Array]";
2398 | };
2399 | var defaultMaxListeners = 10;
2400 |
2401 | function init() {
2402 | this._events = {};
2403 | if (this._conf) {
2404 | configure.call(this, this._conf);
2405 | }
2406 | }
2407 |
2408 | function configure(conf) {
2409 | if (conf) {
2410 |
2411 | this._conf = conf;
2412 |
2413 | conf.delimiter && (this.delimiter = conf.delimiter);
2414 | conf.maxListeners && (this._events.maxListeners = conf.maxListeners);
2415 | conf.wildcard && (this.wildcard = conf.wildcard);
2416 | conf.newListener && (this.newListener = conf.newListener);
2417 |
2418 | if (this.wildcard) {
2419 | this.listenerTree = {};
2420 | }
2421 | }
2422 | }
2423 |
2424 | function EventEmitter(conf) {
2425 | this._events = {};
2426 | this.newListener = false;
2427 | configure.call(this, conf);
2428 | }
2429 |
2430 | //
2431 | // Attention, function return type now is array, always !
2432 | // It has zero elements if no any matches found and one or more
2433 | // elements (leafs) if there are matches
2434 | //
2435 | function searchListenerTree(handlers, type, tree, i) {
2436 | if (!tree) {
2437 | return [];
2438 | }
2439 | var listeners=[], leaf, len, branch, xTree, xxTree, isolatedBranch, endReached,
2440 | typeLength = type.length, currentType = type[i], nextType = type[i+1];
2441 | if (i === typeLength && tree._listeners) {
2442 | //
2443 | // If at the end of the event(s) list and the tree has listeners
2444 | // invoke those listeners.
2445 | //
2446 | if (typeof tree._listeners === 'function') {
2447 | handlers && handlers.push(tree._listeners);
2448 | return [tree];
2449 | } else {
2450 | for (leaf = 0, len = tree._listeners.length; leaf < len; leaf++) {
2451 | handlers && handlers.push(tree._listeners[leaf]);
2452 | }
2453 | return [tree];
2454 | }
2455 | }
2456 |
2457 | if ((currentType === '*' || currentType === '**') || tree[currentType]) {
2458 | //
2459 | // If the event emitted is '*' at this part
2460 | // or there is a concrete match at this patch
2461 | //
2462 | if (currentType === '*') {
2463 | for (branch in tree) {
2464 | if (branch !== '_listeners' && tree.hasOwnProperty(branch)) {
2465 | listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+1));
2466 | }
2467 | }
2468 | return listeners;
2469 | } else if(currentType === '**') {
2470 | endReached = (i+1 === typeLength || (i+2 === typeLength && nextType === '*'));
2471 | if(endReached && tree._listeners) {
2472 | // The next element has a _listeners, add it to the handlers.
2473 | listeners = listeners.concat(searchListenerTree(handlers, type, tree, typeLength));
2474 | }
2475 |
2476 | for (branch in tree) {
2477 | if (branch !== '_listeners' && tree.hasOwnProperty(branch)) {
2478 | if(branch === '*' || branch === '**') {
2479 | if(tree[branch]._listeners && !endReached) {
2480 | listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], typeLength));
2481 | }
2482 | listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i));
2483 | } else if(branch === nextType) {
2484 | listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+2));
2485 | } else {
2486 | // No match on this one, shift into the tree but not in the type array.
2487 | listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i));
2488 | }
2489 | }
2490 | }
2491 | return listeners;
2492 | }
2493 |
2494 | listeners = listeners.concat(searchListenerTree(handlers, type, tree[currentType], i+1));
2495 | }
2496 |
2497 | xTree = tree['*'];
2498 | if (xTree) {
2499 | //
2500 | // If the listener tree will allow any match for this part,
2501 | // then recursively explore all branches of the tree
2502 | //
2503 | searchListenerTree(handlers, type, xTree, i+1);
2504 | }
2505 |
2506 | xxTree = tree['**'];
2507 | if(xxTree) {
2508 | if(i < typeLength) {
2509 | if(xxTree._listeners) {
2510 | // If we have a listener on a '**', it will catch all, so add its handler.
2511 | searchListenerTree(handlers, type, xxTree, typeLength);
2512 | }
2513 |
2514 | // Build arrays of matching next branches and others.
2515 | for(branch in xxTree) {
2516 | if(branch !== '_listeners' && xxTree.hasOwnProperty(branch)) {
2517 | if(branch === nextType) {
2518 | // We know the next element will match, so jump twice.
2519 | searchListenerTree(handlers, type, xxTree[branch], i+2);
2520 | } else if(branch === currentType) {
2521 | // Current node matches, move into the tree.
2522 | searchListenerTree(handlers, type, xxTree[branch], i+1);
2523 | } else {
2524 | isolatedBranch = {};
2525 | isolatedBranch[branch] = xxTree[branch];
2526 | searchListenerTree(handlers, type, { '**': isolatedBranch }, i+1);
2527 | }
2528 | }
2529 | }
2530 | } else if(xxTree._listeners) {
2531 | // We have reached the end and still on a '**'
2532 | searchListenerTree(handlers, type, xxTree, typeLength);
2533 | } else if(xxTree['*'] && xxTree['*']._listeners) {
2534 | searchListenerTree(handlers, type, xxTree['*'], typeLength);
2535 | }
2536 | }
2537 |
2538 | return listeners;
2539 | }
2540 |
2541 | function growListenerTree(type, listener) {
2542 |
2543 | type = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
2544 |
2545 | //
2546 | // Looks for two consecutive '**', if so, don't add the event at all.
2547 | //
2548 | for(var i = 0, len = type.length; i+1 < len; i++) {
2549 | if(type[i] === '**' && type[i+1] === '**') {
2550 | return;
2551 | }
2552 | }
2553 |
2554 | var tree = this.listenerTree;
2555 | var name = type.shift();
2556 |
2557 | while (name) {
2558 |
2559 | if (!tree[name]) {
2560 | tree[name] = {};
2561 | }
2562 |
2563 | tree = tree[name];
2564 |
2565 | if (type.length === 0) {
2566 |
2567 | if (!tree._listeners) {
2568 | tree._listeners = listener;
2569 | }
2570 | else if(typeof tree._listeners === 'function') {
2571 | tree._listeners = [tree._listeners, listener];
2572 | }
2573 | else if (isArray(tree._listeners)) {
2574 |
2575 | tree._listeners.push(listener);
2576 |
2577 | if (!tree._listeners.warned) {
2578 |
2579 | var m = defaultMaxListeners;
2580 |
2581 | if (typeof this._events.maxListeners !== 'undefined') {
2582 | m = this._events.maxListeners;
2583 | }
2584 |
2585 | if (m > 0 && tree._listeners.length > m) {
2586 |
2587 | tree._listeners.warned = true;
2588 | console.error('(node) warning: possible EventEmitter memory ' +
2589 | 'leak detected. %d listeners added. ' +
2590 | 'Use emitter.setMaxListeners() to increase limit.',
2591 | tree._listeners.length);
2592 | console.trace();
2593 | }
2594 | }
2595 | }
2596 | return true;
2597 | }
2598 | name = type.shift();
2599 | }
2600 | return true;
2601 | }
2602 |
2603 | // By default EventEmitters will print a warning if more than
2604 | // 10 listeners are added to it. This is a useful default which
2605 | // helps finding memory leaks.
2606 | //
2607 | // Obviously not all Emitters should be limited to 10. This function allows
2608 | // that to be increased. Set to zero for unlimited.
2609 |
2610 | EventEmitter.prototype.delimiter = '.';
2611 |
2612 | EventEmitter.prototype.setMaxListeners = function(n) {
2613 | this._events || init.call(this);
2614 | this._events.maxListeners = n;
2615 | if (!this._conf) this._conf = {};
2616 | this._conf.maxListeners = n;
2617 | };
2618 |
2619 | EventEmitter.prototype.event = '';
2620 |
2621 | EventEmitter.prototype.once = function(event, fn) {
2622 | this.many(event, 1, fn);
2623 | return this;
2624 | };
2625 |
2626 | EventEmitter.prototype.many = function(event, ttl, fn) {
2627 | var self = this;
2628 |
2629 | if (typeof fn !== 'function') {
2630 | throw new Error('many only accepts instances of Function');
2631 | }
2632 |
2633 | function listener() {
2634 | if (--ttl === 0) {
2635 | self.off(event, listener);
2636 | }
2637 | fn.apply(this, arguments);
2638 | }
2639 |
2640 | listener._origin = fn;
2641 |
2642 | this.on(event, listener);
2643 |
2644 | return self;
2645 | };
2646 |
2647 | EventEmitter.prototype.emit = function() {
2648 |
2649 | this._events || init.call(this);
2650 |
2651 | var type = arguments[0];
2652 |
2653 | if (type === 'newListener' && !this.newListener) {
2654 | if (!this._events.newListener) { return false; }
2655 | }
2656 |
2657 | // Loop through the *_all* functions and invoke them.
2658 | if (this._all) {
2659 | var l = arguments.length;
2660 | var args = new Array(l - 1);
2661 | for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
2662 | for (i = 0, l = this._all.length; i < l; i++) {
2663 | this.event = type;
2664 | this._all[i].apply(this, args);
2665 | }
2666 | }
2667 |
2668 | // If there is no 'error' event listener then throw.
2669 | if (type === 'error') {
2670 |
2671 | if (!this._all &&
2672 | !this._events.error &&
2673 | !(this.wildcard && this.listenerTree.error)) {
2674 |
2675 | if (arguments[1] instanceof Error) {
2676 | throw arguments[1]; // Unhandled 'error' event
2677 | } else {
2678 | throw new Error("Uncaught, unspecified 'error' event.");
2679 | }
2680 | return false;
2681 | }
2682 | }
2683 |
2684 | var handler;
2685 |
2686 | if(this.wildcard) {
2687 | handler = [];
2688 | var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
2689 | searchListenerTree.call(this, handler, ns, this.listenerTree, 0);
2690 | }
2691 | else {
2692 | handler = this._events[type];
2693 | }
2694 |
2695 | if (typeof handler === 'function') {
2696 | this.event = type;
2697 | if (arguments.length === 1) {
2698 | handler.call(this);
2699 | }
2700 | else if (arguments.length > 1)
2701 | switch (arguments.length) {
2702 | case 2:
2703 | handler.call(this, arguments[1]);
2704 | break;
2705 | case 3:
2706 | handler.call(this, arguments[1], arguments[2]);
2707 | break;
2708 | // slower
2709 | default:
2710 | var l = arguments.length;
2711 | var args = new Array(l - 1);
2712 | for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
2713 | handler.apply(this, args);
2714 | }
2715 | return true;
2716 | }
2717 | else if (handler) {
2718 | var l = arguments.length;
2719 | var args = new Array(l - 1);
2720 | for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
2721 |
2722 | var listeners = handler.slice();
2723 | for (var i = 0, l = listeners.length; i < l; i++) {
2724 | this.event = type;
2725 | listeners[i].apply(this, args);
2726 | }
2727 | return (listeners.length > 0) || !!this._all;
2728 | }
2729 | else {
2730 | return !!this._all;
2731 | }
2732 |
2733 | };
2734 |
2735 | EventEmitter.prototype.on = function(type, listener) {
2736 |
2737 | if (typeof type === 'function') {
2738 | this.onAny(type);
2739 | return this;
2740 | }
2741 |
2742 | if (typeof listener !== 'function') {
2743 | throw new Error('on only accepts instances of Function');
2744 | }
2745 | this._events || init.call(this);
2746 |
2747 | // To avoid recursion in the case that type == "newListeners"! Before
2748 | // adding it to the listeners, first emit "newListeners".
2749 | this.emit('newListener', type, listener);
2750 |
2751 | if(this.wildcard) {
2752 | growListenerTree.call(this, type, listener);
2753 | return this;
2754 | }
2755 |
2756 | if (!this._events[type]) {
2757 | // Optimize the case of one listener. Don't need the extra array object.
2758 | this._events[type] = listener;
2759 | }
2760 | else if(typeof this._events[type] === 'function') {
2761 | // Adding the second element, need to change to array.
2762 | this._events[type] = [this._events[type], listener];
2763 | }
2764 | else if (isArray(this._events[type])) {
2765 | // If we've already got an array, just append.
2766 | this._events[type].push(listener);
2767 |
2768 | // Check for listener leak
2769 | if (!this._events[type].warned) {
2770 |
2771 | var m = defaultMaxListeners;
2772 |
2773 | if (typeof this._events.maxListeners !== 'undefined') {
2774 | m = this._events.maxListeners;
2775 | }
2776 |
2777 | if (m > 0 && this._events[type].length > m) {
2778 |
2779 | this._events[type].warned = true;
2780 | console.error('(node) warning: possible EventEmitter memory ' +
2781 | 'leak detected. %d listeners added. ' +
2782 | 'Use emitter.setMaxListeners() to increase limit.',
2783 | this._events[type].length);
2784 | console.trace();
2785 | }
2786 | }
2787 | }
2788 | return this;
2789 | };
2790 |
2791 | EventEmitter.prototype.onAny = function(fn) {
2792 |
2793 | if (typeof fn !== 'function') {
2794 | throw new Error('onAny only accepts instances of Function');
2795 | }
2796 |
2797 | if(!this._all) {
2798 | this._all = [];
2799 | }
2800 |
2801 | // Add the function to the event listener collection.
2802 | this._all.push(fn);
2803 | return this;
2804 | };
2805 |
2806 | EventEmitter.prototype.addListener = EventEmitter.prototype.on;
2807 |
2808 | EventEmitter.prototype.off = function(type, listener) {
2809 | if (typeof listener !== 'function') {
2810 | throw new Error('removeListener only takes instances of Function');
2811 | }
2812 |
2813 | var handlers,leafs=[];
2814 |
2815 | if(this.wildcard) {
2816 | var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
2817 | leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);
2818 | }
2819 | else {
2820 | // does not use listeners(), so no side effect of creating _events[type]
2821 | if (!this._events[type]) return this;
2822 | handlers = this._events[type];
2823 | leafs.push({_listeners:handlers});
2824 | }
2825 |
2826 | for (var iLeaf=0; iLeaf 0) {
2881 | fns = this._all;
2882 | for(i = 0, l = fns.length; i < l; i++) {
2883 | if(fn === fns[i]) {
2884 | fns.splice(i, 1);
2885 | return this;
2886 | }
2887 | }
2888 | } else {
2889 | this._all = [];
2890 | }
2891 | return this;
2892 | };
2893 |
2894 | EventEmitter.prototype.removeListener = EventEmitter.prototype.off;
2895 |
2896 | EventEmitter.prototype.removeAllListeners = function(type) {
2897 | if (arguments.length === 0) {
2898 | !this._events || init.call(this);
2899 | return this;
2900 | }
2901 |
2902 | if(this.wildcard) {
2903 | var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
2904 | var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);
2905 |
2906 | for (var iLeaf=0; iLeaf> 1
2967 | var nBits = -7
2968 | var i = isLE ? (nBytes - 1) : 0
2969 | var d = isLE ? -1 : 1
2970 | var s = buffer[offset + i]
2971 |
2972 | i += d
2973 |
2974 | e = s & ((1 << (-nBits)) - 1)
2975 | s >>= (-nBits)
2976 | nBits += eLen
2977 | for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
2978 |
2979 | m = e & ((1 << (-nBits)) - 1)
2980 | e >>= (-nBits)
2981 | nBits += mLen
2982 | for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
2983 |
2984 | if (e === 0) {
2985 | e = 1 - eBias
2986 | } else if (e === eMax) {
2987 | return m ? NaN : ((s ? -1 : 1) * Infinity)
2988 | } else {
2989 | m = m + Math.pow(2, mLen)
2990 | e = e - eBias
2991 | }
2992 | return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
2993 | }
2994 |
2995 | exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
2996 | var e, m, c
2997 | var eLen = nBytes * 8 - mLen - 1
2998 | var eMax = (1 << eLen) - 1
2999 | var eBias = eMax >> 1
3000 | var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
3001 | var i = isLE ? 0 : (nBytes - 1)
3002 | var d = isLE ? 1 : -1
3003 | var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
3004 |
3005 | value = Math.abs(value)
3006 |
3007 | if (isNaN(value) || value === Infinity) {
3008 | m = isNaN(value) ? 1 : 0
3009 | e = eMax
3010 | } else {
3011 | e = Math.floor(Math.log(value) / Math.LN2)
3012 | if (value * (c = Math.pow(2, -e)) < 1) {
3013 | e--
3014 | c *= 2
3015 | }
3016 | if (e + eBias >= 1) {
3017 | value += rt / c
3018 | } else {
3019 | value += rt * Math.pow(2, 1 - eBias)
3020 | }
3021 | if (value * c >= 2) {
3022 | e++
3023 | c /= 2
3024 | }
3025 |
3026 | if (e + eBias >= eMax) {
3027 | m = 0
3028 | e = eMax
3029 | } else if (e + eBias >= 1) {
3030 | m = (value * c - 1) * Math.pow(2, mLen)
3031 | e = e + eBias
3032 | } else {
3033 | m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
3034 | e = 0
3035 | }
3036 | }
3037 |
3038 | for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
3039 |
3040 | e = (e << mLen) | m
3041 | eLen += mLen
3042 | for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
3043 |
3044 | buffer[offset + i - d] |= s * 128
3045 | }
3046 |
3047 | },{}],8:[function(require,module,exports){
3048 |
3049 | /**
3050 | * Reduce `arr` with `fn`.
3051 | *
3052 | * @param {Array} arr
3053 | * @param {Function} fn
3054 | * @param {Mixed} initial
3055 | *
3056 | * TODO: combatible error handling?
3057 | */
3058 |
3059 | module.exports = function(arr, fn, initial){
3060 | var idx = 0;
3061 | var len = arr.length;
3062 | var curr = arguments.length == 3
3063 | ? initial
3064 | : arr[idx++];
3065 |
3066 | while (idx < len) {
3067 | curr = fn.call(null, curr, arr[idx], ++idx, arr);
3068 | }
3069 |
3070 | return curr;
3071 | };
3072 | },{}],9:[function(require,module,exports){
3073 | /**
3074 | * Module dependencies.
3075 | */
3076 |
3077 | var Emitter = require('emitter');
3078 | var reduce = require('reduce');
3079 |
3080 | /**
3081 | * Root reference for iframes.
3082 | */
3083 |
3084 | var root = 'undefined' == typeof window
3085 | ? this
3086 | : window;
3087 |
3088 | /**
3089 | * Noop.
3090 | */
3091 |
3092 | function noop(){};
3093 |
3094 | /**
3095 | * Check if `obj` is a host object,
3096 | * we don't want to serialize these :)
3097 | *
3098 | * TODO: future proof, move to compoent land
3099 | *
3100 | * @param {Object} obj
3101 | * @return {Boolean}
3102 | * @api private
3103 | */
3104 |
3105 | function isHost(obj) {
3106 | var str = {}.toString.call(obj);
3107 |
3108 | switch (str) {
3109 | case '[object File]':
3110 | case '[object Blob]':
3111 | case '[object FormData]':
3112 | return true;
3113 | default:
3114 | return false;
3115 | }
3116 | }
3117 |
3118 | /**
3119 | * Determine XHR.
3120 | */
3121 |
3122 | function getXHR() {
3123 | if (root.XMLHttpRequest
3124 | && ('file:' != root.location.protocol || !root.ActiveXObject)) {
3125 | return new XMLHttpRequest;
3126 | } else {
3127 | try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
3128 | try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}
3129 | try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}
3130 | try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
3131 | }
3132 | return false;
3133 | }
3134 |
3135 | /**
3136 | * Removes leading and trailing whitespace, added to support IE.
3137 | *
3138 | * @param {String} s
3139 | * @return {String}
3140 | * @api private
3141 | */
3142 |
3143 | var trim = ''.trim
3144 | ? function(s) { return s.trim(); }
3145 | : function(s) { return s.replace(/(^\s*|\s*$)/g, ''); };
3146 |
3147 | /**
3148 | * Check if `obj` is an object.
3149 | *
3150 | * @param {Object} obj
3151 | * @return {Boolean}
3152 | * @api private
3153 | */
3154 |
3155 | function isObject(obj) {
3156 | return obj === Object(obj);
3157 | }
3158 |
3159 | /**
3160 | * Serialize the given `obj`.
3161 | *
3162 | * @param {Object} obj
3163 | * @return {String}
3164 | * @api private
3165 | */
3166 |
3167 | function serialize(obj) {
3168 | if (!isObject(obj)) return obj;
3169 | var pairs = [];
3170 | for (var key in obj) {
3171 | if (null != obj[key]) {
3172 | pairs.push(encodeURIComponent(key)
3173 | + '=' + encodeURIComponent(obj[key]));
3174 | }
3175 | }
3176 | return pairs.join('&');
3177 | }
3178 |
3179 | /**
3180 | * Expose serialization method.
3181 | */
3182 |
3183 | request.serializeObject = serialize;
3184 |
3185 | /**
3186 | * Parse the given x-www-form-urlencoded `str`.
3187 | *
3188 | * @param {String} str
3189 | * @return {Object}
3190 | * @api private
3191 | */
3192 |
3193 | function parseString(str) {
3194 | var obj = {};
3195 | var pairs = str.split('&');
3196 | var parts;
3197 | var pair;
3198 |
3199 | for (var i = 0, len = pairs.length; i < len; ++i) {
3200 | pair = pairs[i];
3201 | parts = pair.split('=');
3202 | obj[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
3203 | }
3204 |
3205 | return obj;
3206 | }
3207 |
3208 | /**
3209 | * Expose parser.
3210 | */
3211 |
3212 | request.parseString = parseString;
3213 |
3214 | /**
3215 | * Default MIME type map.
3216 | *
3217 | * superagent.types.xml = 'application/xml';
3218 | *
3219 | */
3220 |
3221 | request.types = {
3222 | html: 'text/html',
3223 | json: 'application/json',
3224 | xml: 'application/xml',
3225 | urlencoded: 'application/x-www-form-urlencoded',
3226 | 'form': 'application/x-www-form-urlencoded',
3227 | 'form-data': 'application/x-www-form-urlencoded'
3228 | };
3229 |
3230 | /**
3231 | * Default serialization map.
3232 | *
3233 | * superagent.serialize['application/xml'] = function(obj){
3234 | * return 'generated xml here';
3235 | * };
3236 | *
3237 | */
3238 |
3239 | request.serialize = {
3240 | 'application/x-www-form-urlencoded': serialize,
3241 | 'application/json': JSON.stringify
3242 | };
3243 |
3244 | /**
3245 | * Default parsers.
3246 | *
3247 | * superagent.parse['application/xml'] = function(str){
3248 | * return { object parsed from str };
3249 | * };
3250 | *
3251 | */
3252 |
3253 | request.parse = {
3254 | 'application/x-www-form-urlencoded': parseString,
3255 | 'application/json': JSON.parse
3256 | };
3257 |
3258 | /**
3259 | * Parse the given header `str` into
3260 | * an object containing the mapped fields.
3261 | *
3262 | * @param {String} str
3263 | * @return {Object}
3264 | * @api private
3265 | */
3266 |
3267 | function parseHeader(str) {
3268 | var lines = str.split(/\r?\n/);
3269 | var fields = {};
3270 | var index;
3271 | var line;
3272 | var field;
3273 | var val;
3274 |
3275 | lines.pop(); // trailing CRLF
3276 |
3277 | for (var i = 0, len = lines.length; i < len; ++i) {
3278 | line = lines[i];
3279 | index = line.indexOf(':');
3280 | field = line.slice(0, index).toLowerCase();
3281 | val = trim(line.slice(index + 1));
3282 | fields[field] = val;
3283 | }
3284 |
3285 | return fields;
3286 | }
3287 |
3288 | /**
3289 | * Return the mime type for the given `str`.
3290 | *
3291 | * @param {String} str
3292 | * @return {String}
3293 | * @api private
3294 | */
3295 |
3296 | function type(str){
3297 | return str.split(/ *; */).shift();
3298 | };
3299 |
3300 | /**
3301 | * Return header field parameters.
3302 | *
3303 | * @param {String} str
3304 | * @return {Object}
3305 | * @api private
3306 | */
3307 |
3308 | function params(str){
3309 | return reduce(str.split(/ *; */), function(obj, str){
3310 | var parts = str.split(/ *= */)
3311 | , key = parts.shift()
3312 | , val = parts.shift();
3313 |
3314 | if (key && val) obj[key] = val;
3315 | return obj;
3316 | }, {});
3317 | };
3318 |
3319 | /**
3320 | * Initialize a new `Response` with the given `xhr`.
3321 | *
3322 | * - set flags (.ok, .error, etc)
3323 | * - parse header
3324 | *
3325 | * Examples:
3326 | *
3327 | * Aliasing `superagent` as `request` is nice:
3328 | *
3329 | * request = superagent;
3330 | *
3331 | * We can use the promise-like API, or pass callbacks:
3332 | *
3333 | * request.get('/').end(function(res){});
3334 | * request.get('/', function(res){});
3335 | *
3336 | * Sending data can be chained:
3337 | *
3338 | * request
3339 | * .post('/user')
3340 | * .send({ name: 'tj' })
3341 | * .end(function(res){});
3342 | *
3343 | * Or passed to `.send()`:
3344 | *
3345 | * request
3346 | * .post('/user')
3347 | * .send({ name: 'tj' }, function(res){});
3348 | *
3349 | * Or passed to `.post()`:
3350 | *
3351 | * request
3352 | * .post('/user', { name: 'tj' })
3353 | * .end(function(res){});
3354 | *
3355 | * Or further reduced to a single call for simple cases:
3356 | *
3357 | * request
3358 | * .post('/user', { name: 'tj' }, function(res){});
3359 | *
3360 | * @param {XMLHTTPRequest} xhr
3361 | * @param {Object} options
3362 | * @api private
3363 | */
3364 |
3365 | function Response(req, options) {
3366 | options = options || {};
3367 | this.req = req;
3368 | this.xhr = this.req.xhr;
3369 | this.text = this.req.method !='HEAD'
3370 | ? this.xhr.responseText
3371 | : null;
3372 | this.setStatusProperties(this.xhr.status);
3373 | this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());
3374 | // getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
3375 | // getResponseHeader still works. so we get content-type even if getting
3376 | // other headers fails.
3377 | this.header['content-type'] = this.xhr.getResponseHeader('content-type');
3378 | this.setHeaderProperties(this.header);
3379 | this.body = this.req.method != 'HEAD'
3380 | ? this.parseBody(this.text)
3381 | : null;
3382 | }
3383 |
3384 | /**
3385 | * Get case-insensitive `field` value.
3386 | *
3387 | * @param {String} field
3388 | * @return {String}
3389 | * @api public
3390 | */
3391 |
3392 | Response.prototype.get = function(field){
3393 | return this.header[field.toLowerCase()];
3394 | };
3395 |
3396 | /**
3397 | * Set header related properties:
3398 | *
3399 | * - `.type` the content type without params
3400 | *
3401 | * A response of "Content-Type: text/plain; charset=utf-8"
3402 | * will provide you with a `.type` of "text/plain".
3403 | *
3404 | * @param {Object} header
3405 | * @api private
3406 | */
3407 |
3408 | Response.prototype.setHeaderProperties = function(header){
3409 | // content-type
3410 | var ct = this.header['content-type'] || '';
3411 | this.type = type(ct);
3412 |
3413 | // params
3414 | var obj = params(ct);
3415 | for (var key in obj) this[key] = obj[key];
3416 | };
3417 |
3418 | /**
3419 | * Parse the given body `str`.
3420 | *
3421 | * Used for auto-parsing of bodies. Parsers
3422 | * are defined on the `superagent.parse` object.
3423 | *
3424 | * @param {String} str
3425 | * @return {Mixed}
3426 | * @api private
3427 | */
3428 |
3429 | Response.prototype.parseBody = function(str){
3430 | var parse = request.parse[this.type];
3431 | return parse && str && str.length
3432 | ? parse(str)
3433 | : null;
3434 | };
3435 |
3436 | /**
3437 | * Set flags such as `.ok` based on `status`.
3438 | *
3439 | * For example a 2xx response will give you a `.ok` of __true__
3440 | * whereas 5xx will be __false__ and `.error` will be __true__. The
3441 | * `.clientError` and `.serverError` are also available to be more
3442 | * specific, and `.statusType` is the class of error ranging from 1..5
3443 | * sometimes useful for mapping respond colors etc.
3444 | *
3445 | * "sugar" properties are also defined for common cases. Currently providing:
3446 | *
3447 | * - .noContent
3448 | * - .badRequest
3449 | * - .unauthorized
3450 | * - .notAcceptable
3451 | * - .notFound
3452 | *
3453 | * @param {Number} status
3454 | * @api private
3455 | */
3456 |
3457 | Response.prototype.setStatusProperties = function(status){
3458 | var type = status / 100 | 0;
3459 |
3460 | // status / class
3461 | this.status = status;
3462 | this.statusType = type;
3463 |
3464 | // basics
3465 | this.info = 1 == type;
3466 | this.ok = 2 == type;
3467 | this.clientError = 4 == type;
3468 | this.serverError = 5 == type;
3469 | this.error = (4 == type || 5 == type)
3470 | ? this.toError()
3471 | : false;
3472 |
3473 | // sugar
3474 | this.accepted = 202 == status;
3475 | this.noContent = 204 == status || 1223 == status;
3476 | this.badRequest = 400 == status;
3477 | this.unauthorized = 401 == status;
3478 | this.notAcceptable = 406 == status;
3479 | this.notFound = 404 == status;
3480 | this.forbidden = 403 == status;
3481 | };
3482 |
3483 | /**
3484 | * Return an `Error` representative of this response.
3485 | *
3486 | * @return {Error}
3487 | * @api public
3488 | */
3489 |
3490 | Response.prototype.toError = function(){
3491 | var req = this.req;
3492 | var method = req.method;
3493 | var url = req.url;
3494 |
3495 | var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')';
3496 | var err = new Error(msg);
3497 | err.status = this.status;
3498 | err.method = method;
3499 | err.url = url;
3500 |
3501 | return err;
3502 | };
3503 |
3504 | /**
3505 | * Expose `Response`.
3506 | */
3507 |
3508 | request.Response = Response;
3509 |
3510 | /**
3511 | * Initialize a new `Request` with the given `method` and `url`.
3512 | *
3513 | * @param {String} method
3514 | * @param {String} url
3515 | * @api public
3516 | */
3517 |
3518 | function Request(method, url) {
3519 | var self = this;
3520 | Emitter.call(this);
3521 | this._query = this._query || [];
3522 | this.method = method;
3523 | this.url = url;
3524 | this.header = {};
3525 | this._header = {};
3526 | this.on('end', function(){
3527 | var err = null;
3528 | var res = null;
3529 |
3530 | try {
3531 | res = new Response(self);
3532 | } catch(e) {
3533 | err = new Error('Parser is unable to parse the response');
3534 | err.parse = true;
3535 | err.original = e;
3536 | }
3537 |
3538 | self.callback(err, res);
3539 | });
3540 | }
3541 |
3542 | /**
3543 | * Mixin `Emitter`.
3544 | */
3545 |
3546 | Emitter(Request.prototype);
3547 |
3548 | /**
3549 | * Allow for extension
3550 | */
3551 |
3552 | Request.prototype.use = function(fn) {
3553 | fn(this);
3554 | return this;
3555 | }
3556 |
3557 | /**
3558 | * Set timeout to `ms`.
3559 | *
3560 | * @param {Number} ms
3561 | * @return {Request} for chaining
3562 | * @api public
3563 | */
3564 |
3565 | Request.prototype.timeout = function(ms){
3566 | this._timeout = ms;
3567 | return this;
3568 | };
3569 |
3570 | /**
3571 | * Clear previous timeout.
3572 | *
3573 | * @return {Request} for chaining
3574 | * @api public
3575 | */
3576 |
3577 | Request.prototype.clearTimeout = function(){
3578 | this._timeout = 0;
3579 | clearTimeout(this._timer);
3580 | return this;
3581 | };
3582 |
3583 | /**
3584 | * Abort the request, and clear potential timeout.
3585 | *
3586 | * @return {Request}
3587 | * @api public
3588 | */
3589 |
3590 | Request.prototype.abort = function(){
3591 | if (this.aborted) return;
3592 | this.aborted = true;
3593 | this.xhr.abort();
3594 | this.clearTimeout();
3595 | this.emit('abort');
3596 | return this;
3597 | };
3598 |
3599 | /**
3600 | * Set header `field` to `val`, or multiple fields with one object.
3601 | *
3602 | * Examples:
3603 | *
3604 | * req.get('/')
3605 | * .set('Accept', 'application/json')
3606 | * .set('X-API-Key', 'foobar')
3607 | * .end(callback);
3608 | *
3609 | * req.get('/')
3610 | * .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })
3611 | * .end(callback);
3612 | *
3613 | * @param {String|Object} field
3614 | * @param {String} val
3615 | * @return {Request} for chaining
3616 | * @api public
3617 | */
3618 |
3619 | Request.prototype.set = function(field, val){
3620 | if (isObject(field)) {
3621 | for (var key in field) {
3622 | this.set(key, field[key]);
3623 | }
3624 | return this;
3625 | }
3626 | this._header[field.toLowerCase()] = val;
3627 | this.header[field] = val;
3628 | return this;
3629 | };
3630 |
3631 | /**
3632 | * Remove header `field`.
3633 | *
3634 | * Example:
3635 | *
3636 | * req.get('/')
3637 | * .unset('User-Agent')
3638 | * .end(callback);
3639 | *
3640 | * @param {String} field
3641 | * @return {Request} for chaining
3642 | * @api public
3643 | */
3644 |
3645 | Request.prototype.unset = function(field){
3646 | delete this._header[field.toLowerCase()];
3647 | delete this.header[field];
3648 | return this;
3649 | };
3650 |
3651 | /**
3652 | * Get case-insensitive header `field` value.
3653 | *
3654 | * @param {String} field
3655 | * @return {String}
3656 | * @api private
3657 | */
3658 |
3659 | Request.prototype.getHeader = function(field){
3660 | return this._header[field.toLowerCase()];
3661 | };
3662 |
3663 | /**
3664 | * Set Content-Type to `type`, mapping values from `request.types`.
3665 | *
3666 | * Examples:
3667 | *
3668 | * superagent.types.xml = 'application/xml';
3669 | *
3670 | * request.post('/')
3671 | * .type('xml')
3672 | * .send(xmlstring)
3673 | * .end(callback);
3674 | *
3675 | * request.post('/')
3676 | * .type('application/xml')
3677 | * .send(xmlstring)
3678 | * .end(callback);
3679 | *
3680 | * @param {String} type
3681 | * @return {Request} for chaining
3682 | * @api public
3683 | */
3684 |
3685 | Request.prototype.type = function(type){
3686 | this.set('Content-Type', request.types[type] || type);
3687 | return this;
3688 | };
3689 |
3690 | /**
3691 | * Set Accept to `type`, mapping values from `request.types`.
3692 | *
3693 | * Examples:
3694 | *
3695 | * superagent.types.json = 'application/json';
3696 | *
3697 | * request.get('/agent')
3698 | * .accept('json')
3699 | * .end(callback);
3700 | *
3701 | * request.get('/agent')
3702 | * .accept('application/json')
3703 | * .end(callback);
3704 | *
3705 | * @param {String} accept
3706 | * @return {Request} for chaining
3707 | * @api public
3708 | */
3709 |
3710 | Request.prototype.accept = function(type){
3711 | this.set('Accept', request.types[type] || type);
3712 | return this;
3713 | };
3714 |
3715 | /**
3716 | * Set Authorization field value with `user` and `pass`.
3717 | *
3718 | * @param {String} user
3719 | * @param {String} pass
3720 | * @return {Request} for chaining
3721 | * @api public
3722 | */
3723 |
3724 | Request.prototype.auth = function(user, pass){
3725 | var str = btoa(user + ':' + pass);
3726 | this.set('Authorization', 'Basic ' + str);
3727 | return this;
3728 | };
3729 |
3730 | /**
3731 | * Add query-string `val`.
3732 | *
3733 | * Examples:
3734 | *
3735 | * request.get('/shoes')
3736 | * .query('size=10')
3737 | * .query({ color: 'blue' })
3738 | *
3739 | * @param {Object|String} val
3740 | * @return {Request} for chaining
3741 | * @api public
3742 | */
3743 |
3744 | Request.prototype.query = function(val){
3745 | if ('string' != typeof val) val = serialize(val);
3746 | if (val) this._query.push(val);
3747 | return this;
3748 | };
3749 |
3750 | /**
3751 | * Write the field `name` and `val` for "multipart/form-data"
3752 | * request bodies.
3753 | *
3754 | * ``` js
3755 | * request.post('/upload')
3756 | * .field('foo', 'bar')
3757 | * .end(callback);
3758 | * ```
3759 | *
3760 | * @param {String} name
3761 | * @param {String|Blob|File} val
3762 | * @return {Request} for chaining
3763 | * @api public
3764 | */
3765 |
3766 | Request.prototype.field = function(name, val){
3767 | if (!this._formData) this._formData = new FormData();
3768 | this._formData.append(name, val);
3769 | return this;
3770 | };
3771 |
3772 | /**
3773 | * Queue the given `file` as an attachment to the specified `field`,
3774 | * with optional `filename`.
3775 | *
3776 | * ``` js
3777 | * request.post('/upload')
3778 | * .attach(new Blob(['hey!'], { type: "text/html"}))
3779 | * .end(callback);
3780 | * ```
3781 | *
3782 | * @param {String} field
3783 | * @param {Blob|File} file
3784 | * @param {String} filename
3785 | * @return {Request} for chaining
3786 | * @api public
3787 | */
3788 |
3789 | Request.prototype.attach = function(field, file, filename){
3790 | if (!this._formData) this._formData = new FormData();
3791 | this._formData.append(field, file, filename);
3792 | return this;
3793 | };
3794 |
3795 | /**
3796 | * Send `data`, defaulting the `.type()` to "json" when
3797 | * an object is given.
3798 | *
3799 | * Examples:
3800 | *
3801 | * // querystring
3802 | * request.get('/search')
3803 | * .end(callback)
3804 | *
3805 | * // multiple data "writes"
3806 | * request.get('/search')
3807 | * .send({ search: 'query' })
3808 | * .send({ range: '1..5' })
3809 | * .send({ order: 'desc' })
3810 | * .end(callback)
3811 | *
3812 | * // manual json
3813 | * request.post('/user')
3814 | * .type('json')
3815 | * .send('{"name":"tj"})
3816 | * .end(callback)
3817 | *
3818 | * // auto json
3819 | * request.post('/user')
3820 | * .send({ name: 'tj' })
3821 | * .end(callback)
3822 | *
3823 | * // manual x-www-form-urlencoded
3824 | * request.post('/user')
3825 | * .type('form')
3826 | * .send('name=tj')
3827 | * .end(callback)
3828 | *
3829 | * // auto x-www-form-urlencoded
3830 | * request.post('/user')
3831 | * .type('form')
3832 | * .send({ name: 'tj' })
3833 | * .end(callback)
3834 | *
3835 | * // defaults to x-www-form-urlencoded
3836 | * request.post('/user')
3837 | * .send('name=tobi')
3838 | * .send('species=ferret')
3839 | * .end(callback)
3840 | *
3841 | * @param {String|Object} data
3842 | * @return {Request} for chaining
3843 | * @api public
3844 | */
3845 |
3846 | Request.prototype.send = function(data){
3847 | var obj = isObject(data);
3848 | var type = this.getHeader('Content-Type');
3849 |
3850 | // merge
3851 | if (obj && isObject(this._data)) {
3852 | for (var key in data) {
3853 | this._data[key] = data[key];
3854 | }
3855 | } else if ('string' == typeof data) {
3856 | if (!type) this.type('form');
3857 | type = this.getHeader('Content-Type');
3858 | if ('application/x-www-form-urlencoded' == type) {
3859 | this._data = this._data
3860 | ? this._data + '&' + data
3861 | : data;
3862 | } else {
3863 | this._data = (this._data || '') + data;
3864 | }
3865 | } else {
3866 | this._data = data;
3867 | }
3868 |
3869 | if (!obj) return this;
3870 | if (!type) this.type('json');
3871 | return this;
3872 | };
3873 |
3874 | /**
3875 | * Invoke the callback with `err` and `res`
3876 | * and handle arity check.
3877 | *
3878 | * @param {Error} err
3879 | * @param {Response} res
3880 | * @api private
3881 | */
3882 |
3883 | Request.prototype.callback = function(err, res){
3884 | var fn = this._callback;
3885 | this.clearTimeout();
3886 | if (2 == fn.length) return fn(err, res);
3887 | if (err) return this.emit('error', err);
3888 | fn(res);
3889 | };
3890 |
3891 | /**
3892 | * Invoke callback with x-domain error.
3893 | *
3894 | * @api private
3895 | */
3896 |
3897 | Request.prototype.crossDomainError = function(){
3898 | var err = new Error('Origin is not allowed by Access-Control-Allow-Origin');
3899 | err.crossDomain = true;
3900 | this.callback(err);
3901 | };
3902 |
3903 | /**
3904 | * Invoke callback with timeout error.
3905 | *
3906 | * @api private
3907 | */
3908 |
3909 | Request.prototype.timeoutError = function(){
3910 | var timeout = this._timeout;
3911 | var err = new Error('timeout of ' + timeout + 'ms exceeded');
3912 | err.timeout = timeout;
3913 | this.callback(err);
3914 | };
3915 |
3916 | /**
3917 | * Enable transmission of cookies with x-domain requests.
3918 | *
3919 | * Note that for this to work the origin must not be
3920 | * using "Access-Control-Allow-Origin" with a wildcard,
3921 | * and also must set "Access-Control-Allow-Credentials"
3922 | * to "true".
3923 | *
3924 | * @api public
3925 | */
3926 |
3927 | Request.prototype.withCredentials = function(){
3928 | this._withCredentials = true;
3929 | return this;
3930 | };
3931 |
3932 | /**
3933 | * Initiate request, invoking callback `fn(res)`
3934 | * with an instanceof `Response`.
3935 | *
3936 | * @param {Function} fn
3937 | * @return {Request} for chaining
3938 | * @api public
3939 | */
3940 |
3941 | Request.prototype.end = function(fn){
3942 | var self = this;
3943 | var xhr = this.xhr = getXHR();
3944 | var query = this._query.join('&');
3945 | var timeout = this._timeout;
3946 | var data = this._formData || this._data;
3947 |
3948 | // store callback
3949 | this._callback = fn || noop;
3950 |
3951 | // state change
3952 | xhr.onreadystatechange = function(){
3953 | if (4 != xhr.readyState) return;
3954 | if (0 == xhr.status) {
3955 | if (self.aborted) return self.timeoutError();
3956 | return self.crossDomainError();
3957 | }
3958 | self.emit('end');
3959 | };
3960 |
3961 | // progress
3962 | if (xhr.upload) {
3963 | xhr.upload.onprogress = function(e){
3964 | e.percent = e.loaded / e.total * 100;
3965 | self.emit('progress', e);
3966 | };
3967 | }
3968 |
3969 | // timeout
3970 | if (timeout && !this._timer) {
3971 | this._timer = setTimeout(function(){
3972 | self.abort();
3973 | }, timeout);
3974 | }
3975 |
3976 | // querystring
3977 | if (query) {
3978 | query = request.serializeObject(query);
3979 | this.url += ~this.url.indexOf('?')
3980 | ? '&' + query
3981 | : '?' + query;
3982 | }
3983 |
3984 | // initiate request
3985 | xhr.open(this.method, this.url, true);
3986 |
3987 | // CORS
3988 | if (this._withCredentials) xhr.withCredentials = true;
3989 |
3990 | // body
3991 | if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !isHost(data)) {
3992 | // serialize stuff
3993 | var serialize = request.serialize[this.getHeader('Content-Type')];
3994 | if (serialize) data = serialize(data);
3995 | }
3996 |
3997 | // set header fields
3998 | for (var field in this.header) {
3999 | if (null == this.header[field]) continue;
4000 | xhr.setRequestHeader(field, this.header[field]);
4001 | }
4002 |
4003 | // send stuff
4004 | this.emit('request', this);
4005 | xhr.send(data);
4006 | return this;
4007 | };
4008 |
4009 | /**
4010 | * Expose `Request`.
4011 | */
4012 |
4013 | request.Request = Request;
4014 |
4015 | /**
4016 | * Issue a request:
4017 | *
4018 | * Examples:
4019 | *
4020 | * request('GET', '/users').end(callback)
4021 | * request('/users').end(callback)
4022 | * request('/users', callback)
4023 | *
4024 | * @param {String} method
4025 | * @param {String|Function} url or callback
4026 | * @return {Request}
4027 | * @api public
4028 | */
4029 |
4030 | function request(method, url) {
4031 | // callback
4032 | if ('function' == typeof url) {
4033 | return new Request('GET', method).end(url);
4034 | }
4035 |
4036 | // url first
4037 | if (1 == arguments.length) {
4038 | return new Request('GET', method);
4039 | }
4040 |
4041 | return new Request(method, url);
4042 | }
4043 |
4044 | /**
4045 | * GET `url` with optional callback `fn(res)`.
4046 | *
4047 | * @param {String} url
4048 | * @param {Mixed|Function} data or fn
4049 | * @param {Function} fn
4050 | * @return {Request}
4051 | * @api public
4052 | */
4053 |
4054 | request.get = function(url, data, fn){
4055 | var req = request('GET', url);
4056 | if ('function' == typeof data) fn = data, data = null;
4057 | if (data) req.query(data);
4058 | if (fn) req.end(fn);
4059 | return req;
4060 | };
4061 |
4062 | /**
4063 | * HEAD `url` with optional callback `fn(res)`.
4064 | *
4065 | * @param {String} url
4066 | * @param {Mixed|Function} data or fn
4067 | * @param {Function} fn
4068 | * @return {Request}
4069 | * @api public
4070 | */
4071 |
4072 | request.head = function(url, data, fn){
4073 | var req = request('HEAD', url);
4074 | if ('function' == typeof data) fn = data, data = null;
4075 | if (data) req.send(data);
4076 | if (fn) req.end(fn);
4077 | return req;
4078 | };
4079 |
4080 | /**
4081 | * DELETE `url` with optional callback `fn(res)`.
4082 | *
4083 | * @param {String} url
4084 | * @param {Function} fn
4085 | * @return {Request}
4086 | * @api public
4087 | */
4088 |
4089 | request.del = function(url, fn){
4090 | var req = request('DELETE', url);
4091 | if (fn) req.end(fn);
4092 | return req;
4093 | };
4094 |
4095 | /**
4096 | * PATCH `url` with optional `data` and callback `fn(res)`.
4097 | *
4098 | * @param {String} url
4099 | * @param {Mixed} data
4100 | * @param {Function} fn
4101 | * @return {Request}
4102 | * @api public
4103 | */
4104 |
4105 | request.patch = function(url, data, fn){
4106 | var req = request('PATCH', url);
4107 | if ('function' == typeof data) fn = data, data = null;
4108 | if (data) req.send(data);
4109 | if (fn) req.end(fn);
4110 | return req;
4111 | };
4112 |
4113 | /**
4114 | * POST `url` with optional `data` and callback `fn(res)`.
4115 | *
4116 | * @param {String} url
4117 | * @param {Mixed} data
4118 | * @param {Function} fn
4119 | * @return {Request}
4120 | * @api public
4121 | */
4122 |
4123 | request.post = function(url, data, fn){
4124 | var req = request('POST', url);
4125 | if ('function' == typeof data) fn = data, data = null;
4126 | if (data) req.send(data);
4127 | if (fn) req.end(fn);
4128 | return req;
4129 | };
4130 |
4131 | /**
4132 | * PUT `url` with optional `data` and callback `fn(res)`.
4133 | *
4134 | * @param {String} url
4135 | * @param {Mixed|Function} data or fn
4136 | * @param {Function} fn
4137 | * @return {Request}
4138 | * @api public
4139 | */
4140 |
4141 | request.put = function(url, data, fn){
4142 | var req = request('PUT', url);
4143 | if ('function' == typeof data) fn = data, data = null;
4144 | if (data) req.send(data);
4145 | if (fn) req.end(fn);
4146 | return req;
4147 | };
4148 |
4149 | /**
4150 | * Expose `request`.
4151 | */
4152 |
4153 | module.exports = request;
4154 |
4155 | },{"emitter":5,"reduce":8}]},{},[1])(1)
4156 | });
--------------------------------------------------------------------------------