2016-04-15 02:07:31 +03:00
/ *
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
2017-08-30 11:50:27 +03:00
"use strict" ;
2016-04-15 02:07:31 +03:00
/ *
2016-07-13 22:09:42 +03:00
* This file is generated from kinto - http . js - do not modify directly .
2016-04-15 02:07:31 +03:00
* /
2017-03-03 01:44:18 +03:00
2017-01-18 16:53:52 +03:00
const global = this ;
2016-04-15 02:07:31 +03:00
2018-02-23 22:50:01 +03:00
var EXPORTED _SYMBOLS = [ "KintoHttpClient" ] ;
2016-04-15 02:07:31 +03:00
/ *
2018-02-14 20:48:09 +03:00
* Version 4.5 . 3 - 5179 c56
2016-04-15 02:07:31 +03:00
* /
2018-02-14 20:48:09 +03:00
( 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 . KintoHttpClient = f ( ) } } ) ( function ( ) { var define , module , exports ; return ( function ( ) { 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 < r . length ; o ++ ) s ( r [ o ] ) ; return s } return e } ) ( ) ( { 1 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
/ *
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . default = undefined ;
var _base = require ( "../src/base" ) ;
var _base2 = _interopRequireDefault ( _base ) ;
2018-02-14 20:48:09 +03:00
var _errors = require ( "../src/errors" ) ;
var errors = _interopRequireWildcard ( _errors ) ;
function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
2016-04-15 02:07:31 +03:00
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
2018-01-30 02:20:18 +03:00
ChromeUtils . import ( "resource://gre/modules/Timer.jsm" ) ;
2018-05-26 03:02:29 +03:00
ChromeUtils . import ( "resource://gre/modules/XPCOMUtils.jsm" ) ;
XPCOMUtils . defineLazyGlobalGetters ( this , [ "fetch" ] ) ;
2018-01-30 02:20:18 +03:00
const { EventEmitter } = ChromeUtils . import ( "resource://gre/modules/EventEmitter.jsm" , { } ) ;
2016-04-15 02:07:31 +03:00
let KintoHttpClient = class KintoHttpClient extends _base2 . default {
constructor ( remote , options = { } ) {
const events = { } ;
EventEmitter . decorate ( events ) ;
2018-02-14 20:48:09 +03:00
super ( remote , { events , ... options } ) ;
2016-04-15 02:07:31 +03:00
}
} ;
2018-02-14 20:48:09 +03:00
exports . default = KintoHttpClient ;
KintoHttpClient . errors = errors ;
2016-04-15 02:07:31 +03:00
// This fixes compatibility with CommonJS required by browserify.
// See http://stackoverflow.com/questions/33505992/babel-6-changes-how-it-exports-default/33683495#33683495
if ( typeof module === "object" ) {
module . exports = KintoHttpClient ;
}
2018-02-14 20:48:09 +03:00
} , { "../src/base" : 7 , "../src/errors" : 12 } ] , 2 : [ function ( require , module , exports ) {
2017-03-03 01:44:18 +03:00
var v1 = require ( './v1' ) ;
var v4 = require ( './v4' ) ;
var uuid = v4 ;
uuid . v1 = v1 ;
uuid . v4 = v4 ;
module . exports = uuid ;
2017-01-18 16:53:52 +03:00
2017-03-03 01:44:18 +03:00
} , { "./v1" : 5 , "./v4" : 6 } ] , 3 : [ function ( require , module , exports ) {
/ * *
* Convert array of 16 byte values to UUID string format of the form :
2018-02-14 20:48:09 +03:00
* XXXXXXXX - XXXX - XXXX - XXXX - XXXXXXXXXXXX
2017-03-03 01:44:18 +03:00
* /
var byteToHex = [ ] ;
for ( var i = 0 ; i < 256 ; ++ i ) {
byteToHex [ i ] = ( i + 0x100 ) . toString ( 16 ) . substr ( 1 ) ;
}
function bytesToUuid ( buf , offset ) {
var i = offset || 0 ;
var bth = byteToHex ;
2018-02-14 20:48:09 +03:00
return bth [ buf [ i ++ ] ] + bth [ buf [ i ++ ] ] +
2017-03-03 01:44:18 +03:00
bth [ buf [ i ++ ] ] + bth [ buf [ i ++ ] ] + '-' +
bth [ buf [ i ++ ] ] + bth [ buf [ i ++ ] ] + '-' +
bth [ buf [ i ++ ] ] + bth [ buf [ i ++ ] ] + '-' +
bth [ buf [ i ++ ] ] + bth [ buf [ i ++ ] ] + '-' +
bth [ buf [ i ++ ] ] + bth [ buf [ i ++ ] ] +
bth [ buf [ i ++ ] ] + bth [ buf [ i ++ ] ] +
bth [ buf [ i ++ ] ] + bth [ buf [ i ++ ] ] ;
}
module . exports = bytesToUuid ;
} , { } ] , 4 : [ function ( require , module , exports ) {
// Unique ID creation requires a high quality random # generator. In the
// browser this is a little complicated due to unknown quality of Math.random()
// and inconsistent support for the `crypto` API. We do the best we can via
// feature-detection
2017-01-18 16:53:52 +03:00
2018-02-14 20:48:09 +03:00
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
var getRandomValues = ( typeof ( crypto ) != 'undefined' && crypto . getRandomValues . bind ( crypto ) ) ||
( typeof ( msCrypto ) != 'undefined' && msCrypto . getRandomValues . bind ( msCrypto ) ) ;
if ( getRandomValues ) {
2017-03-03 01:44:18 +03:00
// WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
2018-02-14 20:48:09 +03:00
var rnds8 = new Uint8Array ( 16 ) ; // eslint-disable-line no-undef
module . exports = function whatwgRNG ( ) {
getRandomValues ( rnds8 ) ;
2017-03-03 01:44:18 +03:00
return rnds8 ;
2017-01-18 16:53:52 +03:00
} ;
2018-02-14 20:48:09 +03:00
} else {
2017-01-18 16:53:52 +03:00
// Math.random()-based (RNG)
//
// If all else fails, use Math.random(). It's fast, but is of unspecified
// quality.
2018-02-14 20:48:09 +03:00
var rnds = new Array ( 16 ) ;
module . exports = function mathRNG ( ) {
2017-01-18 16:53:52 +03:00
for ( var i = 0 , r ; i < 16 ; i ++ ) {
if ( ( i & 0x03 ) === 0 ) r = Math . random ( ) * 0x100000000 ;
2017-03-03 01:44:18 +03:00
rnds [ i ] = r >>> ( ( i & 0x03 ) << 3 ) & 0xff ;
2017-01-18 16:53:52 +03:00
}
2017-03-03 01:44:18 +03:00
return rnds ;
2017-01-18 16:53:52 +03:00
} ;
}
2017-03-03 01:44:18 +03:00
} , { } ] , 5 : [ function ( require , module , exports ) {
var rng = require ( './lib/rng' ) ;
var bytesToUuid = require ( './lib/bytesToUuid' ) ;
2017-01-18 16:53:52 +03:00
// **`v1()` - Generate time-based UUID**
//
// Inspired by https://github.com/LiosK/UUID.js
// and http://docs.python.org/library/uuid.html
2018-02-14 20:48:09 +03:00
var _nodeId ;
var _clockseq ;
2017-01-18 16:53:52 +03:00
// Previous uuid creation time
2018-02-14 20:48:09 +03:00
var _lastMSecs = 0 ;
var _lastNSecs = 0 ;
2017-01-18 16:53:52 +03:00
// See https://github.com/broofa/node-uuid for API details
function v1 ( options , buf , offset ) {
var i = buf && offset || 0 ;
var b = buf || [ ] ;
options = options || { } ;
2018-02-14 20:48:09 +03:00
var node = options . node || _nodeId ;
2017-01-18 16:53:52 +03:00
var clockseq = options . clockseq !== undefined ? options . clockseq : _clockseq ;
2018-02-14 20:48:09 +03:00
// node and clockseq need to be initialized to random values if they're not
// specified. We do this lazily to minimize issues related to insufficient
// system entropy. See #189
if ( node == null || clockseq == null ) {
var seedBytes = rng ( ) ;
if ( node == null ) {
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
node = _nodeId = [
seedBytes [ 0 ] | 0x01 ,
seedBytes [ 1 ] , seedBytes [ 2 ] , seedBytes [ 3 ] , seedBytes [ 4 ] , seedBytes [ 5 ]
] ;
}
if ( clockseq == null ) {
// Per 4.2.2, randomize (14 bit) clockseq
clockseq = _clockseq = ( seedBytes [ 6 ] << 8 | seedBytes [ 7 ] ) & 0x3fff ;
}
}
2017-01-18 16:53:52 +03:00
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
var msecs = options . msecs !== undefined ? options . msecs : new Date ( ) . getTime ( ) ;
// Per 4.2.1.2, use count of uuid's generated during the current clock
// cycle to simulate higher resolution clock
var nsecs = options . nsecs !== undefined ? options . nsecs : _lastNSecs + 1 ;
// Time since last uuid creation (in msecs)
var dt = ( msecs - _lastMSecs ) + ( nsecs - _lastNSecs ) / 10000 ;
// Per 4.2.1.2, Bump clockseq on clock regression
if ( dt < 0 && options . clockseq === undefined ) {
clockseq = clockseq + 1 & 0x3fff ;
}
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
// time interval
if ( ( dt < 0 || msecs > _lastMSecs ) && options . nsecs === undefined ) {
nsecs = 0 ;
}
// Per 4.2.1.2 Throw error if too many uuids are requested
if ( nsecs >= 10000 ) {
throw new Error ( 'uuid.v1(): Can\'t create more than 10M uuids/sec' ) ;
}
_lastMSecs = msecs ;
_lastNSecs = nsecs ;
_clockseq = clockseq ;
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch
msecs += 12219292800000 ;
// `time_low`
var tl = ( ( msecs & 0xfffffff ) * 10000 + nsecs ) % 0x100000000 ;
b [ i ++ ] = tl >>> 24 & 0xff ;
b [ i ++ ] = tl >>> 16 & 0xff ;
b [ i ++ ] = tl >>> 8 & 0xff ;
b [ i ++ ] = tl & 0xff ;
// `time_mid`
var tmh = ( msecs / 0x100000000 * 10000 ) & 0xfffffff ;
b [ i ++ ] = tmh >>> 8 & 0xff ;
b [ i ++ ] = tmh & 0xff ;
// `time_high_and_version`
b [ i ++ ] = tmh >>> 24 & 0xf | 0x10 ; // include version
b [ i ++ ] = tmh >>> 16 & 0xff ;
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
b [ i ++ ] = clockseq >>> 8 | 0x80 ;
// `clock_seq_low`
b [ i ++ ] = clockseq & 0xff ;
// `node`
2017-03-03 01:44:18 +03:00
for ( var n = 0 ; n < 6 ; ++ n ) {
2017-01-18 16:53:52 +03:00
b [ i + n ] = node [ n ] ;
}
2017-03-03 01:44:18 +03:00
return buf ? buf : bytesToUuid ( b ) ;
2017-01-18 16:53:52 +03:00
}
2017-03-03 01:44:18 +03:00
module . exports = v1 ;
} , { "./lib/bytesToUuid" : 3 , "./lib/rng" : 4 } ] , 6 : [ function ( require , module , exports ) {
var rng = require ( './lib/rng' ) ;
var bytesToUuid = require ( './lib/bytesToUuid' ) ;
2017-01-18 16:53:52 +03:00
function v4 ( options , buf , offset ) {
var i = buf && offset || 0 ;
if ( typeof ( options ) == 'string' ) {
2018-02-14 20:48:09 +03:00
buf = options === 'binary' ? new Array ( 16 ) : null ;
2017-01-18 16:53:52 +03:00
options = null ;
}
options = options || { } ;
2017-03-03 01:44:18 +03:00
var rnds = options . random || ( options . rng || rng ) ( ) ;
2017-01-18 16:53:52 +03:00
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds [ 6 ] = ( rnds [ 6 ] & 0x0f ) | 0x40 ;
rnds [ 8 ] = ( rnds [ 8 ] & 0x3f ) | 0x80 ;
// Copy bytes to buffer, if provided
if ( buf ) {
2017-03-03 01:44:18 +03:00
for ( var ii = 0 ; ii < 16 ; ++ ii ) {
2017-01-18 16:53:52 +03:00
buf [ i + ii ] = rnds [ ii ] ;
}
}
2017-03-03 01:44:18 +03:00
return buf || bytesToUuid ( rnds ) ;
2017-01-18 16:53:52 +03:00
}
2017-03-03 01:44:18 +03:00
module . exports = v4 ;
2017-01-18 16:53:52 +03:00
2017-03-03 01:44:18 +03:00
} , { "./lib/bytesToUuid" : 3 , "./lib/rng" : 4 } ] , 7 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . default = exports . SUPPORTED _PROTOCOL _VERSION = undefined ;
2017-01-18 16:53:52 +03:00
var _dec , _dec2 , _dec3 , _dec4 , _dec5 , _dec6 , _dec7 , _desc , _value , _class ;
2016-04-15 02:07:31 +03:00
var _utils = require ( "./utils" ) ;
var _http = require ( "./http" ) ;
var _http2 = _interopRequireDefault ( _http ) ;
var _endpoint = require ( "./endpoint" ) ;
var _endpoint2 = _interopRequireDefault ( _endpoint ) ;
var _requests = require ( "./requests" ) ;
var requests = _interopRequireWildcard ( _requests ) ;
var _batch = require ( "./batch" ) ;
2016-07-13 22:09:42 +03:00
var _bucket = require ( "./bucket" ) ;
2016-04-15 02:07:31 +03:00
2016-07-13 22:09:42 +03:00
var _bucket2 = _interopRequireDefault ( _bucket ) ;
2016-04-15 02:07:31 +03:00
function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
function _applyDecoratedDescriptor ( target , property , decorators , descriptor , context ) {
var desc = { } ;
Object [ 'ke' + 'ys' ] ( descriptor ) . forEach ( function ( key ) {
desc [ key ] = descriptor [ key ] ;
} ) ;
desc . enumerable = ! ! desc . enumerable ;
desc . configurable = ! ! desc . configurable ;
if ( 'value' in desc || desc . initializer ) {
desc . writable = true ;
}
desc = decorators . slice ( ) . reverse ( ) . reduce ( function ( desc , decorator ) {
return decorator ( target , property , desc ) || desc ;
} , desc ) ;
if ( context && desc . initializer !== void 0 ) {
desc . value = desc . initializer ? desc . initializer . call ( context ) : void 0 ;
desc . initializer = undefined ;
}
if ( desc . initializer === void 0 ) {
Object [ 'define' + 'Property' ] ( target , property , desc ) ;
desc = null ;
}
return desc ;
}
/ * *
* Currently supported protocol version .
* @ type { String }
* /
const SUPPORTED _PROTOCOL _VERSION = exports . SUPPORTED _PROTOCOL _VERSION = "v1" ;
/ * *
* High level HTTP client for the Kinto API .
*
* @ example
* const client = new KintoClient ( "https://kinto.dev.mozaws.net/v1" ) ;
* client . bucket ( "default" )
2018-02-14 20:48:09 +03:00
* . collection ( "my-blog" )
* . createRecord ( { title : "First article" } )
2018-03-15 00:33:47 +03:00
* . then ( console . log )
* . catch ( console . error ) ;
2016-04-15 02:07:31 +03:00
* /
2017-01-18 16:53:52 +03:00
let KintoClientBase = ( _dec = ( 0 , _utils . nobatch ) ( "This operation is not supported within a batch operation." ) , _dec2 = ( 0 , _utils . nobatch ) ( "This operation is not supported within a batch operation." ) , _dec3 = ( 0 , _utils . nobatch ) ( "This operation is not supported within a batch operation." ) , _dec4 = ( 0 , _utils . nobatch ) ( "This operation is not supported within a batch operation." ) , _dec5 = ( 0 , _utils . nobatch ) ( "Can't use batch within a batch!" ) , _dec6 = ( 0 , _utils . capable ) ( [ "permissions_endpoint" ] ) , _dec7 = ( 0 , _utils . support ) ( "1.4" , "2.0" ) , ( _class = class KintoClientBase {
2016-04-15 02:07:31 +03:00
/ * *
* Constructor .
*
2016-07-13 22:09:42 +03:00
* @ param { String } remote The remote URL .
* @ param { Object } [ options = { } ] The options object .
* @ param { Boolean } [ options . safe = true ] Adds concurrency headers to every requests .
* @ param { EventEmitter } [ options . events = EventEmitter ] The events handler instance .
* @ param { Object } [ options . headers = { } ] The key - value headers to pass to each request .
2017-01-18 16:53:52 +03:00
* @ param { Object } [ options . retry = 0 ] Number of retries when request fails ( default : 0 )
2016-07-13 22:09:42 +03:00
* @ param { String } [ options . bucket = "default" ] The default bucket to use .
* @ param { String } [ options . requestMode = "cors" ] The HTTP request mode ( from ES6 fetch spec ) .
2017-03-03 01:44:18 +03:00
* @ param { Number } [ options . timeout = null ] The request timeout in ms , if any .
2016-04-15 02:07:31 +03:00
* /
constructor ( remote , options = { } ) {
if ( typeof remote !== "string" || ! remote . length ) {
throw new Error ( "Invalid remote URL: " + remote ) ;
}
if ( remote [ remote . length - 1 ] === "/" ) {
remote = remote . slice ( 0 , - 1 ) ;
}
this . _backoffReleaseTime = null ;
this . _requests = [ ] ;
this . _isBatch = ! ! options . batch ;
2017-05-09 19:27:11 +03:00
this . _retry = options . retry || 0 ;
this . _safe = ! ! options . safe ;
this . _headers = options . headers || { } ;
2016-04-15 02:07:31 +03:00
// public properties
/ * *
* The remote server base URL .
* @ type { String }
* /
this . remote = remote ;
/ * *
* Current server information .
* @ ignore
* @ type { Object | null }
* /
this . serverInfo = null ;
/ * *
* The event emitter instance . Should comply with the ` EventEmitter `
* interface .
* @ ignore
* @ type { Class }
* /
this . events = options . events ;
2016-07-13 22:09:42 +03:00
const { requestMode , timeout } = options ;
2016-04-15 02:07:31 +03:00
/ * *
* The HTTP instance .
* @ ignore
* @ type { HTTP }
* /
2016-07-13 22:09:42 +03:00
this . http = new _http2 . default ( this . events , { requestMode , timeout } ) ;
2016-04-15 02:07:31 +03:00
this . _registerHTTPEvents ( ) ;
}
/ * *
* The remote endpoint base URL . Setting the value will also extract and
* validate the version .
* @ type { String }
* /
get remote ( ) {
return this . _remote ;
}
/ * *
* @ ignore
* /
set remote ( url ) {
let version ;
try {
version = url . match ( /\/(v\d+)\/?$/ ) [ 1 ] ;
} catch ( err ) {
throw new Error ( "The remote URL must contain the version: " + url ) ;
}
if ( version !== SUPPORTED _PROTOCOL _VERSION ) {
2017-03-03 01:44:18 +03:00
throw new Error ( ` Unsupported protocol version: ${ version } ` ) ;
2016-04-15 02:07:31 +03:00
}
this . _remote = url ;
this . _version = version ;
}
/ * *
* The current server protocol version , eg . ` v1 ` .
* @ type { String }
* /
get version ( ) {
return this . _version ;
}
/ * *
* Backoff remaining time , in milliseconds . Defaults to zero if no backoff is
* ongoing .
*
* @ type { Number }
* /
get backoff ( ) {
const currentTime = new Date ( ) . getTime ( ) ;
if ( this . _backoffReleaseTime && currentTime < this . _backoffReleaseTime ) {
return this . _backoffReleaseTime - currentTime ;
}
return 0 ;
}
/ * *
* Registers HTTP events .
* @ private
* /
_registerHTTPEvents ( ) {
2016-07-13 22:09:42 +03:00
// Prevent registering event from a batch client instance
if ( ! this . _isBatch ) {
this . events . on ( "backoff" , backoffMs => {
this . _backoffReleaseTime = backoffMs ;
} ) ;
}
2016-04-15 02:07:31 +03:00
}
/ * *
* Retrieve a bucket object to perform operations on it .
*
2016-07-13 22:09:42 +03:00
* @ param { String } name The bucket name .
* @ param { Object } [ options = { } ] The request options .
* @ param { Boolean } [ options . safe ] The resulting safe option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry ] The resulting retry option .
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options . headers ] The extended headers object option .
2016-04-15 02:07:31 +03:00
* @ return { Bucket }
* /
bucket ( name , options = { } ) {
2017-05-09 19:27:11 +03:00
return new _bucket2 . default ( this , name , {
batch : this . _isBatch ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options ) ,
retry : this . _getRetry ( options )
} ) ;
2016-04-15 02:07:31 +03:00
}
2018-02-14 20:48:09 +03:00
/ * *
* Set client "headers" for every request , updating previous headers ( if any ) .
*
* @ param { Object } headers The headers to merge with existing ones .
* /
setHeaders ( headers ) {
this . _headers = {
... this . _headers ,
... headers
} ;
this . serverInfo = null ;
}
2016-04-15 02:07:31 +03:00
/ * *
2017-05-09 19:27:11 +03:00
* Get the value of "headers" for a given request , merging the
* per - request headers with our own "default" headers .
2016-04-15 02:07:31 +03:00
*
2017-05-09 19:27:11 +03:00
* Note that unlike other options , headers aren ' t overridden , but
* merged instead .
2016-04-15 02:07:31 +03:00
*
* @ private
2017-05-09 19:27:11 +03:00
* @ param { Object } options The options for a request .
* @ returns { Object }
* /
_getHeaders ( options ) {
2018-02-14 20:48:09 +03:00
return {
... this . _headers ,
... options . headers
} ;
2017-05-09 19:27:11 +03:00
}
/ * *
* Get the value of "safe" for a given request , using the
* per - request option if present or falling back to our default
* otherwise .
*
* @ private
* @ param { Object } options The options for a request .
* @ returns { Boolean }
* /
_getSafe ( options ) {
2018-02-14 20:48:09 +03:00
return { safe : this . _safe , ... options } . safe ;
2017-05-09 19:27:11 +03:00
}
/ * *
* As _getSafe , but for "retry" .
*
* @ private
* /
_getRetry ( options ) {
2018-02-14 20:48:09 +03:00
return { retry : this . _retry , ... options } . retry ;
2017-05-09 19:27:11 +03:00
}
/ * *
* Retrieves the server ' s "hello" endpoint . This endpoint reveals
* server capabilities and settings as well as telling the client
* "who they are" according to their given authorization headers .
*
* @ private
* @ param { Object } [ options = { } ] The request options .
* @ param { Object } [ options . headers = { } ] Headers to use when making
* this request .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
* @ return { Promise < Object , Error > }
* /
async _getHello ( options = { } ) {
const path = this . remote + ( 0 , _endpoint2 . default ) ( "root" ) ;
const { json } = await this . http . request ( path , { headers : this . _getHeaders ( options ) } , { retry : this . _getRetry ( options ) } ) ;
return json ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Retrieves server information and persist them locally . This operation is
* usually performed a single time during the instance lifecycle .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The request options .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async fetchServerInfo ( options = { } ) {
2016-04-15 02:07:31 +03:00
if ( this . serverInfo ) {
return this . serverInfo ;
2017-05-09 19:27:11 +03:00
}
this . serverInfo = await this . _getHello ( { retry : this . _getRetry ( options ) } ) ;
return this . serverInfo ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Retrieves Kinto server settings .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The request options .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async fetchServerSettings ( options ) {
const { settings } = await this . fetchServerInfo ( options ) ;
return settings ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Retrieve server capabilities information .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The request options .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async fetchServerCapabilities ( options = { } ) {
const { capabilities } = await this . fetchServerInfo ( options ) ;
return capabilities ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Retrieve authenticated user information .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The request options .
2017-05-09 19:27:11 +03:00
* @ param { Object } [ options . headers = { } ] Headers to use when making
* this request .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async fetchUser ( options = { } ) {
const { user } = await this . _getHello ( options ) ;
return user ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Retrieve authenticated user information .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The request options .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async fetchHTTPApiVersion ( options = { } ) {
const { http _api _version } = await this . fetchServerInfo ( options ) ;
return http _api _version ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Process batch requests , chunking them according to the batch _max _requests
* server setting when needed .
*
2016-07-13 22:09:42 +03:00
* @ param { Array } requests The list of batch subrequests to perform .
* @ param { Object } [ options = { } ] The options object .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async _batchRequests ( requests , options = { } ) {
const headers = this . _getHeaders ( options ) ;
2016-04-15 02:07:31 +03:00
if ( ! requests . length ) {
2017-05-09 19:27:11 +03:00
return [ ] ;
2016-04-15 02:07:31 +03:00
}
2017-05-09 19:27:11 +03:00
const serverSettings = await this . fetchServerSettings ( {
retry : this . _getRetry ( options )
2016-04-15 02:07:31 +03:00
} ) ;
2017-05-09 19:27:11 +03:00
const maxRequests = serverSettings [ "batch_max_requests" ] ;
if ( maxRequests && requests . length > maxRequests ) {
const chunks = ( 0 , _utils . partition ) ( requests , maxRequests ) ;
return ( 0 , _utils . pMap ) ( chunks , chunk => this . _batchRequests ( chunk , options ) ) ;
}
const { responses } = await this . execute ( {
// FIXME: is this really necessary, since it's also present in
// the "defaults"?
headers ,
path : ( 0 , _endpoint2 . default ) ( "batch" ) ,
method : "POST" ,
body : {
defaults : { headers } ,
requests
}
} , { retry : this . _getRetry ( options ) } ) ;
return responses ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Sends batch requests to the remote server .
*
* Note : Reserved for internal use only .
*
* @ ignore
2016-07-13 22:09:42 +03:00
* @ param { Function } fn The function to use for describing batch ops .
* @ param { Object } [ options = { } ] The options object .
* @ param { Boolean } [ options . safe ] The safe option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry ] The retry option .
2016-07-13 22:09:42 +03:00
* @ param { String } [ options . bucket ] The bucket name option .
2017-01-18 16:53:52 +03:00
* @ param { String } [ options . collection ] The collection name option .
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Boolean } [ options . aggregate = false ] Produces an aggregated result object .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async batch ( fn , options = { } ) {
const rootBatch = new KintoClientBase ( this . remote , {
events : this . events ,
batch : true ,
safe : this . _getSafe ( options ) ,
retry : this . _getRetry ( options )
} ) ;
2016-04-15 02:07:31 +03:00
let bucketBatch , collBatch ;
if ( options . bucket ) {
bucketBatch = rootBatch . bucket ( options . bucket ) ;
if ( options . collection ) {
collBatch = bucketBatch . collection ( options . collection ) ;
}
}
const batchClient = collBatch || bucketBatch || rootBatch ;
2017-05-09 19:27:11 +03:00
fn ( batchClient ) ;
const responses = await this . _batchRequests ( rootBatch . _requests , options ) ;
if ( options . aggregate ) {
return ( 0 , _batch . aggregate ) ( responses , rootBatch . _requests ) ;
} else {
2016-04-15 02:07:31 +03:00
return responses ;
2017-05-09 19:27:11 +03:00
}
2016-04-15 02:07:31 +03:00
}
/ * *
* Executes an atomic HTTP request .
*
* @ private
2016-07-13 22:09:42 +03:00
* @ param { Object } request The request object .
2017-05-09 19:27:11 +03:00
* @ param { String } request . path The path to fetch , relative
* to the Kinto server root .
* @ param { String } [ request . method = "GET" ] The method to use in the
* request .
* @ param { Body } [ request . body ] The request body .
* @ param { Object } [ request . headers = { } ] The request headers .
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The options object .
2017-01-18 16:53:52 +03:00
* @ param { Boolean } [ options . raw = false ] If true , resolve with full response
* @ param { Boolean } [ options . stringify = true ] If true , serialize body data to
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] The number of times to
* retry a request if the server responds with Retry - After .
2017-01-18 16:53:52 +03:00
* JSON .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async execute ( request , options = { } ) {
const { raw = false , stringify = true } = options ;
2016-04-15 02:07:31 +03:00
// If we're within a batch, add the request to the stack to send at once.
if ( this . _isBatch ) {
this . _requests . push ( request ) ;
// Resolve with a message in case people attempt at consuming the result
// from within a batch operation.
const msg = "This result is generated from within a batch " + "operation and should not be consumed." ;
2017-05-09 19:27:11 +03:00
return raw ? { json : msg , headers : { get ( ) { } } } : msg ;
2016-04-15 02:07:31 +03:00
}
2017-05-09 19:27:11 +03:00
const result = await this . http . request ( this . remote + request . path , ( 0 , _utils . cleanUndefinedProperties ) ( {
// Limit requests to only those parts that would be allowed in
// a batch request -- don't pass through other fancy fetch()
// options like integrity, redirect, mode because they will
// break on a batch request. A batch request only allows
// headers, method, path (above), and body.
method : request . method ,
headers : request . headers ,
body : stringify ? JSON . stringify ( request . body ) : request . body
} ) , { retry : this . _getRetry ( options ) } ) ;
return raw ? result : result . json ;
2017-01-18 16:53:52 +03:00
}
2017-05-09 19:27:11 +03:00
/ * *
* Fetch some pages from a paginated list , following the ` next-page `
* header automatically until we have fetched the requested number
* of pages . Return a response with a ` .next() ` method that can be
* called to fetch more results .
*
* @ private
* @ param { String } path
* The path to make the request to .
* @ param { Object } params
* The parameters to use when making the request .
* @ param { String } [ params . sort = "-last_modified" ]
* The sorting order to use when fetching .
* @ param { Object } [ params . filters = { } ]
* The filters to send in the request .
* @ param { Number } [ params . limit = undefined ]
* The limit to send in the request . Undefined means no limit .
* @ param { Number } [ params . pages = undefined ]
* The number of pages to fetch . Undefined means one page . Pass
* Infinity to fetch everything .
* @ param { String } [ params . since = undefined ]
* The ETag from which to start fetching .
* @ param { Object } [ options = { } ]
* Additional request - level parameters to use in all requests .
* @ param { Object } [ options . headers = { } ]
* Headers to use during all requests .
* @ param { Number } [ options . retry = 0 ]
* Number of times to retry each request if the server responds
* with Retry - After .
* /
async paginatedList ( path , params , options = { } ) {
// FIXME: this is called even in batch requests, which doesn't
// make any sense (since all batch requests get a "dummy"
// response; see execute() above).
2018-02-14 20:48:09 +03:00
const { sort , filters , limit , pages , since } = {
sort : "-last_modified" ,
... params
} ;
2017-01-18 16:53:52 +03:00
// Safety/Consistency check on ETag value.
if ( since && typeof since !== "string" ) {
2017-03-03 01:44:18 +03:00
throw new Error ( ` Invalid value for since ( ${ since } ), should be ETag value. ` ) ;
2017-01-18 16:53:52 +03:00
}
2018-02-14 20:48:09 +03:00
const querystring = ( 0 , _utils . qsify ) ( {
... filters ,
2017-01-18 16:53:52 +03:00
_sort : sort ,
_limit : limit ,
_since : since
2018-02-14 20:48:09 +03:00
} ) ;
2017-01-18 16:53:52 +03:00
let results = [ ] ,
current = 0 ;
2017-05-09 19:27:11 +03:00
const next = async function ( nextPage ) {
2017-01-18 16:53:52 +03:00
if ( ! nextPage ) {
throw new Error ( "Pagination exhausted." ) ;
}
return processNextPage ( nextPage ) ;
} ;
2017-06-22 13:51:42 +03:00
const processNextPage = async nextPage => {
2017-01-18 16:53:52 +03:00
const { headers } = options ;
2017-05-09 19:27:11 +03:00
return handleResponse ( ( await this . http . request ( nextPage , { headers } ) ) ) ;
2017-06-22 13:51:42 +03:00
} ;
2017-01-18 16:53:52 +03:00
const pageResults = ( results , nextPage , etag , totalRecords ) => {
// ETag string is supposed to be opaque and stored «as-is».
// ETag header values are quoted (because of * and W/"foo").
return {
last _modified : etag ? etag . replace ( /"/g , "" ) : etag ,
data : results ,
next : next . bind ( null , nextPage ) ,
hasNextPage : ! ! nextPage ,
totalRecords
} ;
} ;
2017-05-09 19:27:11 +03:00
const handleResponse = async function ( { headers , json } ) {
2017-01-18 16:53:52 +03:00
const nextPage = headers . get ( "Next-Page" ) ;
const etag = headers . get ( "ETag" ) ;
const totalRecords = parseInt ( headers . get ( "Total-Records" ) , 10 ) ;
if ( ! pages ) {
return pageResults ( json . data , nextPage , etag , totalRecords ) ;
}
// Aggregate new results with previous ones
results = results . concat ( json . data ) ;
current += 1 ;
if ( current >= pages || ! nextPage ) {
// Pagination exhausted
return pageResults ( results , nextPage , etag , totalRecords ) ;
}
// Follow next page
return processNextPage ( nextPage ) ;
} ;
2017-05-09 19:27:11 +03:00
return handleResponse ( ( await this . execute (
// N.B.: This doesn't use _getHeaders, because all calls to
// `paginatedList` are assumed to come from calls that already
// have headers merged at e.g. the bucket or collection level.
{ headers : options . headers , path : path + "?" + querystring } ,
// N.B. This doesn't use _getRetry, because all calls to
// `paginatedList` are assumed to come from calls that already
// used `_getRetry` at e.g. the bucket or collection level.
{ raw : true , retry : options . retry || 0 } ) ) ) ;
2017-01-18 16:53:52 +03:00
}
/ * *
* Lists all permissions .
*
* @ param { Object } [ options = { } ] The options object .
2017-05-09 19:27:11 +03:00
* @ param { Object } [ options . headers = { } ] Headers to use when making
* this request .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2017-01-18 16:53:52 +03:00
* @ return { Promise < Object [ ] , Error > }
* /
2017-05-09 19:27:11 +03:00
async listPermissions ( options = { } ) {
const path = ( 0 , _endpoint2 . default ) ( "permissions" ) ;
// Ensure the default sort parameter is something that exists in permissions
// entries, as `last_modified` doesn't; here, we pick "id".
2018-02-14 20:48:09 +03:00
const paginationOptions = { sort : "id" , ... options } ;
2017-05-09 19:27:11 +03:00
return this . paginatedList ( path , paginationOptions , {
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options )
} ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Retrieves the list of buckets .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The options object .
2017-05-09 19:27:11 +03:00
* @ param { Object } [ options . headers = { } ] Headers to use when making
* this request .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object [ ] , Error > }
* /
2017-05-09 19:27:11 +03:00
async listBuckets ( options = { } ) {
2017-01-18 16:53:52 +03:00
const path = ( 0 , _endpoint2 . default ) ( "bucket" ) ;
2017-05-09 19:27:11 +03:00
return this . paginatedList ( path , options , {
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options )
} ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Creates a new bucket on the server .
*
2017-05-09 19:27:11 +03:00
* @ param { String | null } id The bucket name ( optional ) .
* @ param { Object } [ options = { } ] The options object .
* @ param { Boolean } [ options . data ] The bucket data option .
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async createBucket ( id , options = { } ) {
const { data = { } , permissions } = options ;
if ( id != null ) {
data . id = id ;
2016-07-13 22:09:42 +03:00
}
2017-05-09 19:27:11 +03:00
const path = data . id ? ( 0 , _endpoint2 . default ) ( "bucket" , data . id ) : ( 0 , _endpoint2 . default ) ( "bucket" ) ;
return this . execute ( requests . createRequest ( path , { data , permissions } , {
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Deletes a bucket from the server .
*
* @ ignore
2016-07-13 22:09:42 +03:00
* @ param { Object | String } bucket The bucket to delete .
* @ param { Object } [ options = { } ] The options object .
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Number } [ options . last _modified ] The last _modified option .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async deleteBucket ( bucket , options = { } ) {
2016-07-13 22:09:42 +03:00
const bucketObj = ( 0 , _utils . toDataBody ) ( bucket ) ;
if ( ! bucketObj . id ) {
throw new Error ( "A bucket id is required." ) ;
}
const path = ( 0 , _endpoint2 . default ) ( "bucket" , bucketObj . id ) ;
2018-02-14 20:48:09 +03:00
const { last _modified } = { ... bucketObj , ... options } ;
2017-05-09 19:27:11 +03:00
return this . execute ( requests . deleteRequest ( path , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Deletes all buckets on the server .
*
* @ ignore
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The options object .
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Number } [ options . last _modified ] The last _modified option .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async deleteBuckets ( options = { } ) {
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "bucket" ) ;
2017-05-09 19:27:11 +03:00
return this . execute ( requests . deleteRequest ( path , {
last _modified : options . last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
2017-01-18 16:53:52 +03:00
} , ( _applyDecoratedDescriptor ( _class . prototype , "fetchServerSettings" , [ _dec ] , Object . getOwnPropertyDescriptor ( _class . prototype , "fetchServerSettings" ) , _class . prototype ) , _applyDecoratedDescriptor ( _class . prototype , "fetchServerCapabilities" , [ _dec2 ] , Object . getOwnPropertyDescriptor ( _class . prototype , "fetchServerCapabilities" ) , _class . prototype ) , _applyDecoratedDescriptor ( _class . prototype , "fetchUser" , [ _dec3 ] , Object . getOwnPropertyDescriptor ( _class . prototype , "fetchUser" ) , _class . prototype ) , _applyDecoratedDescriptor ( _class . prototype , "fetchHTTPApiVersion" , [ _dec4 ] , Object . getOwnPropertyDescriptor ( _class . prototype , "fetchHTTPApiVersion" ) , _class . prototype ) , _applyDecoratedDescriptor ( _class . prototype , "batch" , [ _dec5 ] , Object . getOwnPropertyDescriptor ( _class . prototype , "batch" ) , _class . prototype ) , _applyDecoratedDescriptor ( _class . prototype , "listPermissions" , [ _dec6 ] , Object . getOwnPropertyDescriptor ( _class . prototype , "listPermissions" ) , _class . prototype ) , _applyDecoratedDescriptor ( _class . prototype , "deleteBuckets" , [ _dec7 ] , Object . getOwnPropertyDescriptor ( _class . prototype , "deleteBuckets" ) , _class . prototype ) ) , _class ) ) ;
2016-04-15 02:07:31 +03:00
exports . default = KintoClientBase ;
2017-03-03 01:44:18 +03:00
} , { "./batch" : 8 , "./bucket" : 9 , "./endpoint" : 11 , "./http" : 13 , "./requests" : 14 , "./utils" : 15 } ] , 8 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . aggregate = aggregate ;
/ * *
* Exports batch responses as a result object .
*
* @ private
* @ param { Array } responses The batch subrequest responses .
* @ param { Array } requests The initial issued requests .
* @ return { Object }
* /
function aggregate ( responses = [ ] , requests = [ ] ) {
if ( responses . length !== requests . length ) {
throw new Error ( "Responses length should match requests one." ) ;
}
const results = {
errors : [ ] ,
published : [ ] ,
conflicts : [ ] ,
skipped : [ ]
} ;
return responses . reduce ( ( acc , response , index ) => {
const { status } = response ;
2017-01-18 16:53:52 +03:00
const request = requests [ index ] ;
2016-04-15 02:07:31 +03:00
if ( status >= 200 && status < 400 ) {
acc . published . push ( response . body ) ;
} else if ( status === 404 ) {
2017-01-18 16:53:52 +03:00
// Extract the id manually from request path while waiting for Kinto/kinto#818
2018-02-14 20:48:09 +03:00
const regex = /(buckets|groups|collections|records)\/([^/]+)$/ ;
2017-05-09 19:27:11 +03:00
const extracts = request . path . match ( regex ) ;
2017-01-18 16:53:52 +03:00
const id = extracts . length === 3 ? extracts [ 2 ] : undefined ;
acc . skipped . push ( {
id ,
path : request . path ,
error : response . body
} ) ;
2016-04-15 02:07:31 +03:00
} else if ( status === 412 ) {
acc . conflicts . push ( {
// XXX: specifying the type is probably superfluous
type : "outgoing" ,
2017-01-18 16:53:52 +03:00
local : request . body ,
2016-04-15 02:07:31 +03:00
remote : response . body . details && response . body . details . existing || null
} ) ;
} else {
acc . errors . push ( {
2017-01-18 16:53:52 +03:00
path : request . path ,
sent : request ,
2016-04-15 02:07:31 +03:00
error : response . body
} ) ;
}
return acc ;
} , results ) ;
}
2017-03-03 01:44:18 +03:00
} , { } ] , 9 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . default = undefined ;
2017-01-18 16:53:52 +03:00
var _dec , _desc , _value , _class ;
2016-04-15 02:07:31 +03:00
var _utils = require ( "./utils" ) ;
var _collection = require ( "./collection" ) ;
var _collection2 = _interopRequireDefault ( _collection ) ;
var _requests = require ( "./requests" ) ;
var requests = _interopRequireWildcard ( _requests ) ;
var _endpoint = require ( "./endpoint" ) ;
var _endpoint2 = _interopRequireDefault ( _endpoint ) ;
function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
2017-01-18 16:53:52 +03:00
function _applyDecoratedDescriptor ( target , property , decorators , descriptor , context ) {
var desc = { } ;
Object [ 'ke' + 'ys' ] ( descriptor ) . forEach ( function ( key ) {
desc [ key ] = descriptor [ key ] ;
} ) ;
desc . enumerable = ! ! desc . enumerable ;
desc . configurable = ! ! desc . configurable ;
if ( 'value' in desc || desc . initializer ) {
desc . writable = true ;
}
desc = decorators . slice ( ) . reverse ( ) . reduce ( function ( desc , decorator ) {
return decorator ( target , property , desc ) || desc ;
} , desc ) ;
if ( context && desc . initializer !== void 0 ) {
desc . value = desc . initializer ? desc . initializer . call ( context ) : void 0 ;
desc . initializer = undefined ;
}
if ( desc . initializer === void 0 ) {
Object [ 'define' + 'Property' ] ( target , property , desc ) ;
desc = null ;
}
return desc ;
}
2016-04-15 02:07:31 +03:00
/ * *
* Abstract representation of a selected bucket .
*
* /
2017-01-18 16:53:52 +03:00
let Bucket = ( _dec = ( 0 , _utils . capable ) ( [ "history" ] ) , ( _class = class Bucket {
2016-04-15 02:07:31 +03:00
/ * *
* Constructor .
*
2016-07-13 22:09:42 +03:00
* @ param { KintoClient } client The client instance .
* @ param { String } name The bucket name .
* @ param { Object } [ options = { } ] The headers object option .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Boolean } [ options . safe ] The safe option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry ] The retry option .
2016-04-15 02:07:31 +03:00
* /
constructor ( client , name , options = { } ) {
/ * *
* @ ignore
* /
this . client = client ;
/ * *
* The bucket name .
* @ type { String }
* /
this . name = name ;
/ * *
* @ ignore
* /
2017-05-09 19:27:11 +03:00
this . _isBatch = ! ! options . batch ;
2016-04-15 02:07:31 +03:00
/ * *
* @ ignore
* /
2017-05-09 19:27:11 +03:00
this . _headers = options . headers || { } ;
this . _retry = options . retry || 0 ;
this . _safe = ! ! options . safe ;
2016-04-15 02:07:31 +03:00
}
/ * *
2017-05-09 19:27:11 +03:00
* Get the value of "headers" for a given request , merging the
* per - request headers with our own "default" headers .
2016-04-15 02:07:31 +03:00
*
* @ private
* /
2017-05-09 19:27:11 +03:00
_getHeaders ( options ) {
2018-02-14 20:48:09 +03:00
return {
... this . _headers ,
... options . headers
} ;
2017-05-09 19:27:11 +03:00
}
/ * *
* Get the value of "safe" for a given request , using the
* per - request option if present or falling back to our default
* otherwise .
*
* @ private
* @ param { Object } options The options for a request .
* @ returns { Boolean }
* /
_getSafe ( options ) {
2018-02-14 20:48:09 +03:00
return { safe : this . _safe , ... options } . safe ;
2017-05-09 19:27:11 +03:00
}
/ * *
* As _getSafe , but for "retry" .
*
* @ private
* /
_getRetry ( options ) {
2018-02-14 20:48:09 +03:00
return { retry : this . _retry , ... options } . retry ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Selects a collection .
*
2016-07-13 22:09:42 +03:00
* @ param { String } name The collection name .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Boolean } [ options . safe ] The safe option .
2016-04-15 02:07:31 +03:00
* @ return { Collection }
* /
2016-07-13 22:09:42 +03:00
collection ( name , options = { } ) {
2017-05-09 19:27:11 +03:00
return new _collection2 . default ( this . client , this , name , {
batch : this . _isBatch ,
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
2016-07-13 22:09:42 +03:00
* Retrieves bucket data .
2016-04-15 02:07:31 +03:00
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async getData ( options = { } ) {
const request = {
headers : this . _getHeaders ( options ) ,
path : ( 0 , _endpoint2 . default ) ( "bucket" , this . name )
} ;
const { data } = await this . client . execute ( request , {
retry : this . _getRetry ( options )
} ) ;
return data ;
2016-07-13 22:09:42 +03:00
}
/ * *
* Set bucket data .
* @ param { Object } data The bucket data object .
* @ param { Object } [ options = { } ] The options object .
2017-05-09 19:27:11 +03:00
* @ param { Object } [ options . headers = { } ] The headers object option .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . patch ] The patch option .
* @ param { Number } [ options . last _modified ] The last _modified option .
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async setData ( data , options = { } ) {
2016-07-13 22:09:42 +03:00
if ( ! ( 0 , _utils . isObject ) ( data ) ) {
throw new Error ( "A bucket object is required." ) ;
}
2018-02-14 20:48:09 +03:00
const bucket = { ... data , id : this . name } ;
2016-07-13 22:09:42 +03:00
// For default bucket, we need to drop the id from the data object.
// Bug in Kinto < 3.1.1
const bucketId = bucket . id ;
if ( bucket . id === "default" ) {
delete bucket . id ;
}
const path = ( 0 , _endpoint2 . default ) ( "bucket" , bucketId ) ;
2017-05-09 19:27:11 +03:00
const { patch , permissions } = options ;
2018-02-14 20:48:09 +03:00
const { last _modified } = { ... data , ... options } ;
2017-05-09 19:27:11 +03:00
const request = requests . updateRequest ( path , { data : bucket , permissions } , {
last _modified ,
patch ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
2017-01-18 16:53:52 +03:00
/ * *
* Retrieves the list of history entries in the current bucket .
*
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2017-01-18 16:53:52 +03:00
* @ return { Promise < Array < Object > , Error > }
* /
2017-05-09 19:27:11 +03:00
async listHistory ( options = { } ) {
2017-01-18 16:53:52 +03:00
const path = ( 0 , _endpoint2 . default ) ( "history" , this . name ) ;
2017-05-09 19:27:11 +03:00
return this . client . paginatedList ( path , options , {
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options )
} ) ;
2017-01-18 16:53:52 +03:00
}
2016-04-15 02:07:31 +03:00
/ * *
* Retrieves the list of collections in the current bucket .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Array < Object > , Error > }
* /
2017-05-09 19:27:11 +03:00
async listCollections ( options = { } ) {
2017-01-18 16:53:52 +03:00
const path = ( 0 , _endpoint2 . default ) ( "collection" , this . name ) ;
2017-05-09 19:27:11 +03:00
return this . client . paginatedList ( path , options , {
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options )
} ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Creates a new collection in current bucket .
*
2016-07-13 22:09:42 +03:00
* @ param { String | undefined } id The collection id .
* @ param { Object } [ options = { } ] The options object .
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options . permissions ] The permissions object .
* @ param { Object } [ options . data ] The data object .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async createCollection ( id , options = { } ) {
const { permissions , data = { } } = options ;
2016-07-13 22:09:42 +03:00
data . id = id ;
const path = ( 0 , _endpoint2 . default ) ( "collection" , this . name , id ) ;
2017-05-09 19:27:11 +03:00
const request = requests . createRequest ( path , { data , permissions } , {
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Deletes a collection from the current bucket .
*
2016-07-13 22:09:42 +03:00
* @ param { Object | String } collection The collection to delete .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Number } [ options . last _modified ] The last _modified option .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async deleteCollection ( collection , options = { } ) {
2016-07-13 22:09:42 +03:00
const collectionObj = ( 0 , _utils . toDataBody ) ( collection ) ;
if ( ! collectionObj . id ) {
throw new Error ( "A collection id is required." ) ;
}
2017-05-09 19:27:11 +03:00
const { id } = collectionObj ;
2018-02-14 20:48:09 +03:00
const { last _modified } = { ... collectionObj , ... options } ;
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "collection" , this . name , id ) ;
2017-05-09 19:27:11 +03:00
const request = requests . deleteRequest ( path , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-07-13 22:09:42 +03:00
}
/ * *
* Retrieves the list of groups in the current bucket .
*
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ return { Promise < Array < Object > , Error > }
* /
2017-05-09 19:27:11 +03:00
async listGroups ( options = { } ) {
2017-01-18 16:53:52 +03:00
const path = ( 0 , _endpoint2 . default ) ( "group" , this . name ) ;
2017-05-09 19:27:11 +03:00
return this . client . paginatedList ( path , options , {
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options )
} ) ;
2016-07-13 22:09:42 +03:00
}
/ * *
* Creates a new group in current bucket .
*
* @ param { String } id The group id .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async getGroup ( id , options = { } ) {
const request = {
headers : this . _getHeaders ( options ) ,
path : ( 0 , _endpoint2 . default ) ( "group" , this . name , id )
} ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-07-13 22:09:42 +03:00
}
/ * *
* Creates a new group in current bucket .
*
* @ param { String | undefined } id The group id .
* @ param { Array < String > } [ members = [ ] ] The list of principals .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . data ] The data object .
* @ param { Object } [ options . permissions ] The permissions object .
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async createGroup ( id , members = [ ] , options = { } ) {
2018-02-14 20:48:09 +03:00
const data = {
... options . data ,
2016-07-13 22:09:42 +03:00
id ,
members
2018-02-14 20:48:09 +03:00
} ;
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "group" , this . name , id ) ;
const { permissions } = options ;
2017-05-09 19:27:11 +03:00
const request = requests . createRequest ( path , { data , permissions } , {
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-07-13 22:09:42 +03:00
}
/ * *
* Updates an existing group in current bucket .
*
* @ param { Object } group The group object .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . data ] The data object .
* @ param { Object } [ options . permissions ] The permissions object .
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Number } [ options . last _modified ] The last _modified option .
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async updateGroup ( group , options = { } ) {
2016-07-13 22:09:42 +03:00
if ( ! ( 0 , _utils . isObject ) ( group ) ) {
throw new Error ( "A group object is required." ) ;
}
if ( ! group . id ) {
throw new Error ( "A group id is required." ) ;
}
2018-02-14 20:48:09 +03:00
const data = {
... options . data ,
... group
} ;
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "group" , this . name , group . id ) ;
2017-05-09 19:27:11 +03:00
const { patch , permissions } = options ;
2018-02-14 20:48:09 +03:00
const { last _modified } = { ... data , ... options } ;
2017-05-09 19:27:11 +03:00
const request = requests . updateRequest ( path , { data , permissions } , {
last _modified ,
patch ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-07-13 22:09:42 +03:00
}
/ * *
* Deletes a group from the current bucket .
*
* @ param { Object | String } group The group to delete .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Number } [ options . last _modified ] The last _modified option .
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async deleteGroup ( group , options = { } ) {
2016-07-13 22:09:42 +03:00
const groupObj = ( 0 , _utils . toDataBody ) ( group ) ;
2017-05-09 19:27:11 +03:00
const { id } = groupObj ;
2018-02-14 20:48:09 +03:00
const { last _modified } = { ... groupObj , ... options } ;
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "group" , this . name , id ) ;
2017-05-09 19:27:11 +03:00
const request = requests . deleteRequest ( path , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Retrieves the list of permissions for this bucket .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async getPermissions ( options = { } ) {
const request = {
headers : this . _getHeaders ( options ) ,
path : ( 0 , _endpoint2 . default ) ( "bucket" , this . name )
} ;
const { permissions } = await this . client . execute ( request , {
retry : this . _getRetry ( options )
} ) ;
return permissions ;
2016-04-15 02:07:31 +03:00
}
/ * *
2016-07-13 22:09:42 +03:00
* Replaces all existing bucket permissions with the ones provided .
2016-04-15 02:07:31 +03:00
*
2016-07-13 22:09:42 +03:00
* @ param { Object } permissions The permissions object .
* @ param { Object } [ options = { } ] The options object
* @ param { Boolean } [ options . safe ] The safe option .
2017-05-09 19:27:11 +03:00
* @ param { Object } [ options . headers = { } ] The headers object option .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options . last _modified ] The last _modified option .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async setPermissions ( permissions , options = { } ) {
2016-07-13 22:09:42 +03:00
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
const path = ( 0 , _endpoint2 . default ) ( "bucket" , this . name ) ;
const { last _modified } = options ;
const data = { last _modified } ;
2017-05-09 19:27:11 +03:00
const request = requests . updateRequest ( path , { data , permissions } , {
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
}
/ * *
* Append principals to the bucket permissions .
*
* @ param { Object } permissions The permissions object .
* @ param { Object } [ options = { } ] The options object
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
* @ param { Object } [ options . last _modified ] The last _modified option .
* @ return { Promise < Object , Error > }
* /
async addPermissions ( permissions , options = { } ) {
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
const path = ( 0 , _endpoint2 . default ) ( "bucket" , this . name ) ;
const { last _modified } = options ;
const request = requests . jsonPatchPermissionsRequest ( path , permissions , "add" , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
}
/ * *
* Remove principals from the bucket permissions .
*
* @ param { Object } permissions The permissions object .
* @ param { Object } [ options = { } ] The options object
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
* @ param { Object } [ options . last _modified ] The last _modified option .
* @ return { Promise < Object , Error > }
* /
async removePermissions ( permissions , options = { } ) {
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
const path = ( 0 , _endpoint2 . default ) ( "bucket" , this . name ) ;
const { last _modified } = options ;
const request = requests . jsonPatchPermissionsRequest ( path , permissions , "remove" , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Performs batch operations at the current bucket level .
*
2016-07-13 22:09:42 +03:00
* @ param { Function } fn The batch operation function .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Boolean } [ options . safe ] The safe option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] The retry option .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . aggregate ] Produces a grouped result object .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async batch ( fn , options = { } ) {
return this . client . batch ( fn , {
bucket : this . name ,
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options ) ,
safe : this . _getSafe ( options ) ,
aggregate : ! ! options . aggregate
} ) ;
2016-04-15 02:07:31 +03:00
}
2017-01-18 16:53:52 +03:00
} , ( _applyDecoratedDescriptor ( _class . prototype , "listHistory" , [ _dec ] , Object . getOwnPropertyDescriptor ( _class . prototype , "listHistory" ) , _class . prototype ) ) , _class ) ) ;
2016-04-15 02:07:31 +03:00
exports . default = Bucket ;
2017-03-03 01:44:18 +03:00
} , { "./collection" : 10 , "./endpoint" : 11 , "./requests" : 14 , "./utils" : 15 } ] , 10 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . default = undefined ;
2017-05-09 19:27:11 +03:00
var _dec , _dec2 , _dec3 , _desc , _value , _class ;
2017-01-18 16:53:52 +03:00
var _uuid = require ( "uuid" ) ;
2016-04-15 02:07:31 +03:00
var _utils = require ( "./utils" ) ;
var _requests = require ( "./requests" ) ;
var requests = _interopRequireWildcard ( _requests ) ;
var _endpoint = require ( "./endpoint" ) ;
var _endpoint2 = _interopRequireDefault ( _endpoint ) ;
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
2017-01-18 16:53:52 +03:00
function _applyDecoratedDescriptor ( target , property , decorators , descriptor , context ) {
var desc = { } ;
Object [ 'ke' + 'ys' ] ( descriptor ) . forEach ( function ( key ) {
desc [ key ] = descriptor [ key ] ;
} ) ;
desc . enumerable = ! ! desc . enumerable ;
desc . configurable = ! ! desc . configurable ;
if ( 'value' in desc || desc . initializer ) {
desc . writable = true ;
}
desc = decorators . slice ( ) . reverse ( ) . reduce ( function ( desc , decorator ) {
return decorator ( target , property , desc ) || desc ;
} , desc ) ;
if ( context && desc . initializer !== void 0 ) {
desc . value = desc . initializer ? desc . initializer . call ( context ) : void 0 ;
desc . initializer = undefined ;
}
if ( desc . initializer === void 0 ) {
Object [ 'define' + 'Property' ] ( target , property , desc ) ;
desc = null ;
}
return desc ;
}
2016-04-15 02:07:31 +03:00
/ * *
* Abstract representation of a selected collection .
*
* /
2017-05-09 19:27:11 +03:00
let Collection = ( _dec = ( 0 , _utils . capable ) ( [ "attachments" ] ) , _dec2 = ( 0 , _utils . capable ) ( [ "attachments" ] ) , _dec3 = ( 0 , _utils . capable ) ( [ "history" ] ) , ( _class = class Collection {
2016-04-15 02:07:31 +03:00
/ * *
* Constructor .
*
2016-07-13 22:09:42 +03:00
* @ param { KintoClient } client The client instance .
* @ param { Bucket } bucket The bucket instance .
* @ param { String } name The collection name .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Boolean } [ options . safe ] The safe option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry ] The retry option .
* @ param { Boolean } [ options . batch ] ( Private ) Whether this
* Collection is operating as part of a batch .
2016-04-15 02:07:31 +03:00
* /
constructor ( client , bucket , name , options = { } ) {
/ * *
* @ ignore
* /
this . client = client ;
/ * *
* @ ignore
* /
this . bucket = bucket ;
/ * *
* The collection name .
* @ type { String }
* /
this . name = name ;
/ * *
* @ ignore
* /
2017-05-09 19:27:11 +03:00
this . _isBatch = ! ! options . batch ;
2016-04-15 02:07:31 +03:00
/ * *
* @ ignore
* /
2017-05-09 19:27:11 +03:00
this . _retry = options . retry || 0 ;
this . _safe = ! ! options . safe ;
// FIXME: This is kind of ugly; shouldn't the bucket be responsible
// for doing the merge?
2018-02-14 20:48:09 +03:00
this . _headers = {
... this . bucket . _headers ,
... options . headers
} ;
2016-04-15 02:07:31 +03:00
}
/ * *
2017-05-09 19:27:11 +03:00
* Get the value of "headers" for a given request , merging the
* per - request headers with our own "default" headers .
2016-04-15 02:07:31 +03:00
*
* @ private
* /
2017-05-09 19:27:11 +03:00
_getHeaders ( options ) {
2018-02-14 20:48:09 +03:00
return {
... this . _headers ,
... options . headers
} ;
2017-05-09 19:27:11 +03:00
}
/ * *
* Get the value of "safe" for a given request , using the
* per - request option if present or falling back to our default
* otherwise .
*
* @ private
* @ param { Object } options The options for a request .
* @ returns { Boolean }
* /
_getSafe ( options ) {
2018-02-14 20:48:09 +03:00
return { safe : this . _safe , ... options } . safe ;
2017-05-09 19:27:11 +03:00
}
/ * *
* As _getSafe , but for "retry" .
*
* @ private
* /
_getRetry ( options ) {
2018-02-14 20:48:09 +03:00
return { retry : this . _retry , ... options } . retry ;
2016-04-15 02:07:31 +03:00
}
2017-01-18 16:53:52 +03:00
/ * *
* Retrieves the total number of records in this collection .
*
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2017-01-18 16:53:52 +03:00
* @ return { Promise < Number , Error > }
* /
2017-05-09 19:27:11 +03:00
async getTotalRecords ( options = { } ) {
2017-01-18 16:53:52 +03:00
const path = ( 0 , _endpoint2 . default ) ( "record" , this . bucket . name , this . name ) ;
2017-05-09 19:27:11 +03:00
const request = {
headers : this . _getHeaders ( options ) ,
path ,
method : "HEAD"
} ;
const { headers } = await this . client . execute ( request , {
raw : true ,
retry : this . _getRetry ( options )
} ) ;
return parseInt ( headers . get ( "Total-Records" ) , 10 ) ;
2017-01-18 16:53:52 +03:00
}
2016-04-15 02:07:31 +03:00
/ * *
2016-07-13 22:09:42 +03:00
* Retrieves collection data .
2016-04-15 02:07:31 +03:00
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async getData ( options = { } ) {
2017-01-18 16:53:52 +03:00
const path = ( 0 , _endpoint2 . default ) ( "collection" , this . bucket . name , this . name ) ;
2017-05-09 19:27:11 +03:00
const request = { headers : this . _getHeaders ( options ) , path } ;
const { data } = await this . client . execute ( request , {
retry : this . _getRetry ( options )
} ) ;
return data ;
2016-04-15 02:07:31 +03:00
}
/ * *
2016-07-13 22:09:42 +03:00
* Set collection data .
* @ param { Object } data The collection data object .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Boolean } [ options . patch ] The patch option .
* @ param { Number } [ options . last _modified ] The last _modified option .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async setData ( data , options = { } ) {
2016-07-13 22:09:42 +03:00
if ( ! ( 0 , _utils . isObject ) ( data ) ) {
throw new Error ( "A collection object is required." ) ;
}
2017-05-09 19:27:11 +03:00
const { patch , permissions } = options ;
2018-02-14 20:48:09 +03:00
const { last _modified } = { ... data , ... options } ;
2016-04-15 02:07:31 +03:00
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "collection" , this . bucket . name , this . name ) ;
2017-05-09 19:27:11 +03:00
const request = requests . updateRequest ( path , { data , permissions } , {
last _modified ,
patch ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
2016-07-13 22:09:42 +03:00
* Retrieves the list of permissions for this collection .
2016-04-15 02:07:31 +03:00
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async getPermissions ( options = { } ) {
2017-01-18 16:53:52 +03:00
const path = ( 0 , _endpoint2 . default ) ( "collection" , this . bucket . name , this . name ) ;
2017-05-09 19:27:11 +03:00
const request = { headers : this . _getHeaders ( options ) , path } ;
const { permissions } = await this . client . execute ( request , {
retry : this . _getRetry ( options )
} ) ;
return permissions ;
2016-04-15 02:07:31 +03:00
}
/ * *
2016-07-13 22:09:42 +03:00
* Replaces all existing collection permissions with the ones provided .
2016-04-15 02:07:31 +03:00
*
2016-07-13 22:09:42 +03:00
* @ param { Object } permissions The permissions object .
* @ param { Object } [ options = { } ] The options object
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Number } [ options . last _modified ] The last _modified option .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async setPermissions ( permissions , options = { } ) {
2016-07-13 22:09:42 +03:00
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
const path = ( 0 , _endpoint2 . default ) ( "collection" , this . bucket . name , this . name ) ;
const data = { last _modified : options . last _modified } ;
2017-05-09 19:27:11 +03:00
const request = requests . updateRequest ( path , { data , permissions } , {
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
}
/ * *
* Append principals to the collection permissions .
*
* @ param { Object } permissions The permissions object .
* @ param { Object } [ options = { } ] The options object
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
* @ param { Object } [ options . last _modified ] The last _modified option .
* @ return { Promise < Object , Error > }
* /
async addPermissions ( permissions , options = { } ) {
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
const path = ( 0 , _endpoint2 . default ) ( "collection" , this . bucket . name , this . name ) ;
const { last _modified } = options ;
const request = requests . jsonPatchPermissionsRequest ( path , permissions , "add" , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
}
/ * *
* Remove principals from the collection permissions .
*
* @ param { Object } permissions The permissions object .
* @ param { Object } [ options = { } ] The options object
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
* @ param { Object } [ options . last _modified ] The last _modified option .
* @ return { Promise < Object , Error > }
* /
async removePermissions ( permissions , options = { } ) {
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
const path = ( 0 , _endpoint2 . default ) ( "collection" , this . bucket . name , this . name ) ;
const { last _modified } = options ;
const request = requests . jsonPatchPermissionsRequest ( path , permissions , "remove" , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Creates a record in current collection .
*
2017-01-18 16:53:52 +03:00
* @ param { Object } record The record to create .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2017-01-18 16:53:52 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Object } [ options . permissions ] The permissions option .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async createRecord ( record , options = { } ) {
const { permissions } = options ;
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "record" , this . bucket . name , this . name , record . id ) ;
2017-05-09 19:27:11 +03:00
const request = requests . createRequest ( path , { data : record , permissions } , {
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
2017-01-18 16:53:52 +03:00
/ * *
* Adds an attachment to a record , creating the record when it doesn ' t exist .
*
* @ param { String } dataURL The data url .
* @ param { Object } [ record = { } ] The record data .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2017-01-18 16:53:52 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Number } [ options . last _modified ] The last _modified option .
* @ param { Object } [ options . permissions ] The permissions option .
* @ param { String } [ options . filename ] Force the attachment filename .
* @ param { String } [ options . gzipped ] Force the attachment to be gzipped or not .
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async addAttachment ( dataURI , record = { } , options = { } ) {
const { permissions } = options ;
2017-01-18 16:53:52 +03:00
const id = record . id || _uuid . v4 . v4 ( ) ;
const path = ( 0 , _endpoint2 . default ) ( "attachment" , this . bucket . name , this . name , id ) ;
2018-02-14 20:48:09 +03:00
const { last _modified } = { ... record , ... options } ;
2017-05-09 19:27:11 +03:00
const addAttachmentRequest = requests . addAttachmentRequest ( path , dataURI , { data : record , permissions } , {
last _modified ,
filename : options . filename ,
gzipped : options . gzipped ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
await this . client . execute ( addAttachmentRequest , {
stringify : false ,
retry : this . _getRetry ( options )
} ) ;
return this . getRecord ( id ) ;
2017-01-18 16:53:52 +03:00
}
/ * *
* Removes an attachment from a given record .
*
* @ param { Object } recordId The record id .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2017-01-18 16:53:52 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Number } [ options . last _modified ] The last _modified option .
* /
2017-05-09 19:27:11 +03:00
async removeAttachment ( recordId , options = { } ) {
const { last _modified } = options ;
2017-01-18 16:53:52 +03:00
const path = ( 0 , _endpoint2 . default ) ( "attachment" , this . bucket . name , this . name , recordId ) ;
2017-05-09 19:27:11 +03:00
const request = requests . deleteRequest ( path , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2017-01-18 16:53:52 +03:00
}
2016-04-15 02:07:31 +03:00
/ * *
* Updates a record in current collection .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } record The record to update .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Number } [ options . last _modified ] The last _modified option .
2017-01-18 16:53:52 +03:00
* @ param { Object } [ options . permissions ] The permissions option .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async updateRecord ( record , options = { } ) {
2016-07-13 22:09:42 +03:00
if ( ! ( 0 , _utils . isObject ) ( record ) ) {
throw new Error ( "A record object is required." ) ;
}
if ( ! record . id ) {
throw new Error ( "A record id is required." ) ;
}
2017-05-09 19:27:11 +03:00
const { permissions } = options ;
2018-02-14 20:48:09 +03:00
const { last _modified } = { ... record , ... options } ;
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "record" , this . bucket . name , this . name , record . id ) ;
2017-05-09 19:27:11 +03:00
const request = requests . updateRequest ( path , { data : record , permissions } , {
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options ) ,
last _modified ,
patch : ! ! options . patch
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Deletes a record from the current collection .
*
2016-07-13 22:09:42 +03:00
* @ param { Object | String } record The record to delete .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . safe ] The safe option .
* @ param { Number } [ options . last _modified ] The last _modified option .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async deleteRecord ( record , options = { } ) {
2016-07-13 22:09:42 +03:00
const recordObj = ( 0 , _utils . toDataBody ) ( record ) ;
if ( ! recordObj . id ) {
throw new Error ( "A record id is required." ) ;
}
2017-05-09 19:27:11 +03:00
const { id } = recordObj ;
2018-02-14 20:48:09 +03:00
const { last _modified } = { ... recordObj , ... options } ;
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "record" , this . bucket . name , this . name , id ) ;
2017-05-09 19:27:11 +03:00
const request = requests . deleteRequest ( path , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Retrieves a record from the current collection .
*
2016-07-13 22:09:42 +03:00
* @ param { String } id The record id to retrieve .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async getRecord ( id , options = { } ) {
2017-01-18 16:53:52 +03:00
const path = ( 0 , _endpoint2 . default ) ( "record" , this . bucket . name , this . name , id ) ;
2017-05-09 19:27:11 +03:00
const request = { headers : this . _getHeaders ( options ) , path } ;
return this . client . execute ( request , { retry : this . _getRetry ( options ) } ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Lists records from the current collection .
*
* Sorting is done by passing a ` sort ` string option :
*
* - The field to order the results by , prefixed with ` - ` for descending .
* Default : ` -last_modified ` .
*
2017-01-18 16:53:52 +03:00
* @ see http : //kinto.readthedocs.io/en/stable/api/1.x/sorting.html
2016-04-15 02:07:31 +03:00
*
* Filtering is done by passing a ` filters ` option object :
*
* - ` {fieldname: "value"} `
* - ` {min_fieldname: 4000} `
* - ` {in_fieldname: "1,2,3"} `
* - ` {not_fieldname: 0} `
* - ` {exclude_fieldname: "0,1"} `
*
2017-01-18 16:53:52 +03:00
* @ see http : //kinto.readthedocs.io/en/stable/api/1.x/filtering.html
2016-04-15 02:07:31 +03:00
*
* Paginating is done by passing a ` limit ` option , then calling the ` next() `
* method from the resolved result object to fetch the next page , if any .
*
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
2016-07-13 22:09:42 +03:00
* @ param { Object } [ options . filters = [ ] ] The filters object .
* @ param { String } [ options . sort = "-last_modified" ] The sort field .
2017-03-03 01:44:18 +03:00
* @ param { String } [ options . at ] The timestamp to get a snapshot at .
2016-07-13 22:09:42 +03:00
* @ param { String } [ options . limit = null ] The limit field .
* @ param { String } [ options . pages = 1 ] The number of result pages to aggregate .
* @ param { Number } [ options . since = null ] Only retrieve records modified since the provided timestamp .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async listRecords ( options = { } ) {
2016-07-13 22:09:42 +03:00
const path = ( 0 , _endpoint2 . default ) ( "record" , this . bucket . name , this . name ) ;
2017-03-03 01:44:18 +03:00
if ( options . hasOwnProperty ( "at" ) ) {
2017-05-09 19:27:11 +03:00
return this . getSnapshot ( options . at ) ;
2017-03-03 01:44:18 +03:00
} else {
2017-05-09 19:27:11 +03:00
return this . client . paginatedList ( path , options , {
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options )
} ) ;
2017-03-03 01:44:18 +03:00
}
}
/ * *
* @ private
* /
2017-05-09 19:27:11 +03:00
async isHistoryComplete ( ) {
// We consider that if we have the collection creation event part of the
// history, then all records change events have been tracked.
const { data : [ oldestHistoryEntry ] } = await this . bucket . listHistory ( {
limit : 1 ,
filters : {
action : "create" ,
resource _name : "collection" ,
collection _id : this . name
}
} ) ;
return ! ! oldestHistoryEntry ;
}
/ * *
* @ private
* /
async listChangesBackTo ( at ) {
// Ensure we have enough history data to retrieve the complete list of
// changes.
if ( ! ( await this . isHistoryComplete ( ) ) ) {
throw new Error ( "Computing a snapshot is only possible when the full history for a " + "collection is available. Here, the history plugin seems to have " + "been enabled after the creation of the collection." ) ;
2017-03-03 01:44:18 +03:00
}
2017-05-09 19:27:11 +03:00
const { data : changes } = await this . bucket . listHistory ( {
2017-03-03 01:44:18 +03:00
pages : Infinity , // all pages up to target timestamp are required
sort : "-target.data.last_modified" ,
filters : {
resource _name : "record" ,
collection _id : this . name ,
2018-02-14 20:48:09 +03:00
"max_target.data.last_modified" : String ( at ) // eq. to <=
}
2017-03-03 01:44:18 +03:00
} ) ;
2017-05-09 19:27:11 +03:00
return changes ;
}
/ * *
* @ private
* /
async getSnapshot ( at ) {
if ( ! Number . isInteger ( at ) || at <= 0 ) {
throw new Error ( "Invalid argument, expected a positive integer." ) ;
}
// Retrieve history and check it covers the required time range.
const changes = await this . listChangesBackTo ( at ) ;
// Replay changes to compute the requested snapshot.
const seenIds = new Set ( ) ;
let snapshot = [ ] ;
2018-02-14 20:48:09 +03:00
for ( const { action , target : { data : record } } of changes ) {
2017-05-09 19:27:11 +03:00
if ( action == "delete" ) {
seenIds . add ( record . id ) ; // ensure not reprocessing deleted entries
snapshot = snapshot . filter ( r => r . id !== record . id ) ;
} else if ( ! seenIds . has ( record . id ) ) {
seenIds . add ( record . id ) ;
snapshot . push ( record ) ;
}
}
return {
last _modified : String ( at ) ,
data : snapshot . sort ( ( a , b ) => b . last _modified - a . last _modified ) ,
next : ( ) => {
throw new Error ( "Snapshots don't support pagination" ) ;
} ,
hasNextPage : false ,
totalRecords : snapshot . length
} ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Performs batch operations at the current collection level .
*
2016-07-13 22:09:42 +03:00
* @ param { Function } fn The batch operation function .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Boolean } [ options . safe ] The safe option .
2017-05-09 19:27:11 +03:00
* @ param { Number } [ options . retry ] The retry option .
2016-07-13 22:09:42 +03:00
* @ param { Boolean } [ options . aggregate ] Produces a grouped result object .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2017-05-09 19:27:11 +03:00
async batch ( fn , options = { } ) {
return this . client . batch ( fn , {
2016-07-13 22:09:42 +03:00
bucket : this . bucket . name ,
2017-05-09 19:27:11 +03:00
collection : this . name ,
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options ) ,
safe : this . _getSafe ( options ) ,
aggregate : ! ! options . aggregate
} ) ;
2016-04-15 02:07:31 +03:00
}
2017-05-09 19:27:11 +03:00
} , ( _applyDecoratedDescriptor ( _class . prototype , "addAttachment" , [ _dec ] , Object . getOwnPropertyDescriptor ( _class . prototype , "addAttachment" ) , _class . prototype ) , _applyDecoratedDescriptor ( _class . prototype , "removeAttachment" , [ _dec2 ] , Object . getOwnPropertyDescriptor ( _class . prototype , "removeAttachment" ) , _class . prototype ) , _applyDecoratedDescriptor ( _class . prototype , "getSnapshot" , [ _dec3 ] , Object . getOwnPropertyDescriptor ( _class . prototype , "getSnapshot" ) , _class . prototype ) ) , _class ) ) ;
2016-04-15 02:07:31 +03:00
exports . default = Collection ;
2017-03-03 01:44:18 +03:00
} , { "./endpoint" : 11 , "./requests" : 14 , "./utils" : 15 , "uuid" : 2 } ] , 11 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . default = endpoint ;
/ * *
* Endpoints templates .
* @ type { Object }
* /
const ENDPOINTS = {
root : ( ) => "/" ,
batch : ( ) => "/batch" ,
2017-01-18 16:53:52 +03:00
permissions : ( ) => "/permissions" ,
2017-03-03 01:44:18 +03:00
bucket : bucket => "/buckets" + ( bucket ? ` / ${ bucket } ` : "" ) ,
history : bucket => ` ${ ENDPOINTS . bucket ( bucket ) } /history ` ,
collection : ( bucket , coll ) => ` ${ ENDPOINTS . bucket ( bucket ) } /collections ` + ( coll ? ` / ${ coll } ` : "" ) ,
group : ( bucket , group ) => ` ${ ENDPOINTS . bucket ( bucket ) } /groups ` + ( group ? ` / ${ group } ` : "" ) ,
record : ( bucket , coll , id ) => ` ${ ENDPOINTS . collection ( bucket , coll ) } /records ` + ( id ? ` / ${ id } ` : "" ) ,
attachment : ( bucket , coll , id ) => ` ${ ENDPOINTS . record ( bucket , coll , id ) } /attachment `
2016-04-15 02:07:31 +03:00
} ;
/ * *
* Retrieves a server enpoint by its name .
*
* @ private
* @ param { String } name The endpoint name .
* @ param { ... string } args The endpoint parameters .
* @ return { String }
* /
function endpoint ( name , ... args ) {
return ENDPOINTS [ name ] ( ... args ) ;
}
2017-03-03 01:44:18 +03:00
} , { } ] , 12 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
/ * *
* Kinto server error code descriptors .
* @ type { Object }
* /
2018-02-14 20:48:09 +03:00
const ERROR _CODES = {
2016-04-15 02:07:31 +03:00
104 : "Missing Authorization Token" ,
105 : "Invalid Authorization Token" ,
106 : "Request body was not valid JSON" ,
107 : "Invalid request parameter" ,
108 : "Missing request parameter" ,
109 : "Invalid posted data" ,
110 : "Invalid Token / id" ,
111 : "Missing Token / id" ,
112 : "Content-Length header was not provided" ,
113 : "Request body too large" ,
2017-01-18 16:53:52 +03:00
114 : "Resource was created, updated or deleted meanwhile" ,
2016-07-13 22:09:42 +03:00
115 : "Method not allowed on this end point (hint: server may be readonly)" ,
2016-04-15 02:07:31 +03:00
116 : "Requested version not available on this server" ,
117 : "Client has sent too many requests" ,
121 : "Resource access is forbidden for this user" ,
122 : "Another resource violates constraint" ,
201 : "Service Temporary unavailable due to high load" ,
202 : "Service deprecated" ,
999 : "Internal Server Error"
} ;
2018-02-14 20:48:09 +03:00
exports . default = ERROR _CODES ;
let NetworkTimeoutError = class NetworkTimeoutError extends Error {
constructor ( url , options ) {
super ( ` Timeout while trying to access ${ url } with ${ JSON . stringify ( options ) } ` ) ;
if ( Error . captureStackTrace ) {
Error . captureStackTrace ( this , NetworkTimeoutError ) ;
}
this . url = url ;
this . options = options ;
}
} ;
let UnparseableResponseError = class UnparseableResponseError extends Error {
constructor ( response , body , error ) {
const { status } = response ;
super ( ` Response from server unparseable (HTTP ${ status || 0 } ; ${ error } ): ${ body } ` ) ;
if ( Error . captureStackTrace ) {
Error . captureStackTrace ( this , UnparseableResponseError ) ;
}
this . status = status ;
this . response = response ;
this . stack = error . stack ;
this . error = error ;
}
} ;
/ * *
* "Error" subclass representing a >= 400 response from the server .
*
* Whether or not this is an error depends on your application .
*
* The ` json ` field can be undefined if the server responded with an
* empty response body . This shouldn ' t generally happen . Most "bad"
* responses come with a JSON error description , or ( if they ' re
* fronted by a CDN or nginx or something ) occasionally non - JSON
* responses ( which become UnparseableResponseErrors , above ) .
* /
let ServerResponse = class ServerResponse extends Error {
constructor ( response , json ) {
const { status } = response ;
let { statusText } = response ;
let errnoMsg ;
if ( json ) {
// Try to fill in information from the JSON error.
statusText = json . error || statusText ;
// Take errnoMsg from either ERROR_CODES or json.message.
if ( json . errno && json . errno in ERROR _CODES ) {
errnoMsg = ERROR _CODES [ json . errno ] ;
} else if ( json . message ) {
errnoMsg = json . message ;
}
// If we had both ERROR_CODES and json.message, and they differ,
// combine them.
if ( errnoMsg && json . message && json . message !== errnoMsg ) {
errnoMsg += ` ( ${ json . message } ) ` ;
}
}
let message = ` HTTP ${ status } ${ statusText } ` ;
if ( errnoMsg ) {
message += ` : ${ errnoMsg } ` ;
}
super ( message . trim ( ) ) ;
if ( Error . captureStackTrace ) {
Error . captureStackTrace ( this , ServerResponse ) ;
}
this . response = response ;
this . data = json ;
}
} ;
exports . NetworkTimeoutError = NetworkTimeoutError ;
exports . ServerResponse = ServerResponse ;
exports . UnparseableResponseError = UnparseableResponseError ;
2017-03-03 01:44:18 +03:00
} , { } ] , 13 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . default = undefined ;
2017-05-09 19:27:11 +03:00
var _utils = require ( "./utils" ) ;
2016-04-15 02:07:31 +03:00
var _errors = require ( "./errors" ) ;
/ * *
* Enhanced HTTP client for the Kinto protocol .
* @ private
* /
let HTTP = class HTTP {
/ * *
* Default HTTP request headers applied to each outgoing request .
*
* @ type { Object }
* /
static get DEFAULT _REQUEST _HEADERS ( ) {
return {
2017-05-09 19:27:11 +03:00
Accept : "application/json" ,
2016-04-15 02:07:31 +03:00
"Content-Type" : "application/json"
} ;
}
/ * *
* Default options .
*
* @ type { Object }
* /
static get defaultOptions ( ) {
2017-03-03 01:44:18 +03:00
return { timeout : null , requestMode : "cors" } ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Constructor .
*
2016-07-13 22:09:42 +03:00
* @ param { EventEmitter } events The event handler .
* @ param { Object } [ options = { } } The options object .
2017-03-03 01:44:18 +03:00
* @ param { Number } [ options . timeout = null ] The request timeout in ms , if any ( default : ` null ` ) .
2016-07-13 22:09:42 +03:00
* @ param { String } [ options . requestMode = "cors" ] The HTTP request mode ( default : ` "cors" ` ) .
2016-04-15 02:07:31 +03:00
* /
constructor ( events , options = { } ) {
// public properties
/ * *
* The event emitter instance .
* @ type { EventEmitter }
* /
if ( ! events ) {
throw new Error ( "No events handler provided" ) ;
}
this . events = events ;
/ * *
* The request mode .
* @ see https : //fetch.spec.whatwg.org/#requestmode
* @ type { String }
* /
2016-07-13 22:09:42 +03:00
this . requestMode = options . requestMode || HTTP . defaultOptions . requestMode ;
2016-04-15 02:07:31 +03:00
/ * *
* The request timeout .
* @ type { Number }
* /
2016-07-13 22:09:42 +03:00
this . timeout = options . timeout || HTTP . defaultOptions . timeout ;
2016-04-15 02:07:31 +03:00
}
2017-05-09 19:27:11 +03:00
/ * *
* @ private
* /
timedFetch ( url , options ) {
let hasTimedout = false ;
return new Promise ( ( resolve , reject ) => {
// Detect if a request has timed out.
let _timeoutId ;
if ( this . timeout ) {
_timeoutId = setTimeout ( ( ) => {
hasTimedout = true ;
2018-02-14 20:48:09 +03:00
reject ( new _errors . NetworkTimeoutError ( url , options ) ) ;
2017-05-09 19:27:11 +03:00
} , this . timeout ) ;
}
function proceedWithHandler ( fn ) {
return arg => {
if ( ! hasTimedout ) {
if ( _timeoutId ) {
clearTimeout ( _timeoutId ) ;
}
fn ( arg ) ;
}
} ;
}
fetch ( url , options ) . then ( proceedWithHandler ( resolve ) ) . catch ( proceedWithHandler ( reject ) ) ;
} ) ;
}
/ * *
* @ private
* /
async processResponse ( response ) {
2018-02-14 20:48:09 +03:00
const { status , headers } = response ;
2017-05-09 19:27:11 +03:00
const text = await response . text ( ) ;
// Check if we have a body; if so parse it as JSON.
2018-02-14 20:48:09 +03:00
let json ;
if ( text . length !== 0 ) {
try {
json = JSON . parse ( text ) ;
} catch ( err ) {
throw new _errors . UnparseableResponseError ( response , text , err ) ;
2017-05-09 19:27:11 +03:00
}
2018-02-14 20:48:09 +03:00
}
if ( status >= 400 ) {
throw new _errors . ServerResponse ( response , json ) ;
2017-05-09 19:27:11 +03:00
}
return { status , json , headers } ;
}
/ * *
* @ private
* /
async retry ( url , retryAfter , request , options ) {
await ( 0 , _utils . delay ) ( retryAfter ) ;
2018-02-14 20:48:09 +03:00
return this . request ( url , request , { ... options , retry : options . retry - 1 } ) ;
2017-05-09 19:27:11 +03:00
}
2016-04-15 02:07:31 +03:00
/ * *
* Performs an HTTP request to the Kinto server .
*
* Resolves with an objet containing the following HTTP response properties :
* - ` {Number} status ` The HTTP status code .
* - ` {Object} json ` The JSON response body .
* - ` {Headers} headers ` The response headers object ; see the ES6 fetch ( ) spec .
*
2016-07-13 22:09:42 +03:00
* @ param { String } url The URL .
2017-05-09 19:27:11 +03:00
* @ param { Object } [ request = { } ] The request object , passed to
* fetch ( ) as its options object .
* @ param { Object } [ request . headers ] The request headers object ( default : { } )
* @ param { Object } [ options = { } ] Options for making the
* request
* @ param { Number } [ options . retry ] Number of retries ( default : 0 )
2016-04-15 02:07:31 +03:00
* @ return { Promise }
* /
2017-05-09 19:27:11 +03:00
async request ( url , request = { headers : { } } , options = { retry : 0 } ) {
2016-04-15 02:07:31 +03:00
// Ensure default request headers are always set
2018-02-14 20:48:09 +03:00
request . headers = { ... HTTP . DEFAULT _REQUEST _HEADERS , ... request . headers } ;
2017-01-18 16:53:52 +03:00
// If a multipart body is provided, remove any custom Content-Type header as
// the fetch() implementation will add the correct one for us.
2017-05-09 19:27:11 +03:00
if ( request . body && typeof request . body . append === "function" ) {
delete request . headers [ "Content-Type" ] ;
2017-01-18 16:53:52 +03:00
}
2017-05-09 19:27:11 +03:00
request . mode = this . requestMode ;
2017-01-18 16:53:52 +03:00
2017-05-09 19:27:11 +03:00
const response = await this . timedFetch ( url , request ) ;
const { status , headers } = response ;
this . _checkForDeprecationHeader ( headers ) ;
this . _checkForBackoffHeader ( status , headers ) ;
// Check if the server summons the client to retry after a while.
const retryAfter = this . _checkForRetryAfterHeader ( status , headers ) ;
// If number of allowed of retries is not exhausted, retry the same request.
if ( retryAfter && options . retry > 0 ) {
return this . retry ( url , retryAfter , request , options ) ;
} else {
return this . processResponse ( response ) ;
}
2016-04-15 02:07:31 +03:00
}
_checkForDeprecationHeader ( headers ) {
const alertHeader = headers . get ( "Alert" ) ;
if ( ! alertHeader ) {
return ;
}
let alert ;
try {
alert = JSON . parse ( alertHeader ) ;
} catch ( err ) {
console . warn ( "Unable to parse Alert header message" , alertHeader ) ;
return ;
}
console . warn ( alert . message , alert . url ) ;
this . events . emit ( "deprecated" , alert ) ;
}
_checkForBackoffHeader ( status , headers ) {
let backoffMs ;
const backoffSeconds = parseInt ( headers . get ( "Backoff" ) , 10 ) ;
if ( backoffSeconds > 0 ) {
backoffMs = new Date ( ) . getTime ( ) + backoffSeconds * 1000 ;
} else {
backoffMs = 0 ;
}
this . events . emit ( "backoff" , backoffMs ) ;
}
2016-07-13 22:09:42 +03:00
_checkForRetryAfterHeader ( status , headers ) {
let retryAfter = headers . get ( "Retry-After" ) ;
if ( ! retryAfter ) {
return ;
}
2017-01-18 16:53:52 +03:00
const delay = parseInt ( retryAfter , 10 ) * 1000 ;
retryAfter = new Date ( ) . getTime ( ) + delay ;
2016-07-13 22:09:42 +03:00
this . events . emit ( "retry-after" , retryAfter ) ;
2017-01-18 16:53:52 +03:00
return delay ;
2016-07-13 22:09:42 +03:00
}
2016-04-15 02:07:31 +03:00
} ;
exports . default = HTTP ;
2017-05-09 19:27:11 +03:00
} , { "./errors" : 12 , "./utils" : 15 } ] , 14 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
2016-07-13 22:09:42 +03:00
exports . createRequest = createRequest ;
exports . updateRequest = updateRequest ;
2017-05-09 19:27:11 +03:00
exports . jsonPatchPermissionsRequest = jsonPatchPermissionsRequest ;
2016-07-13 22:09:42 +03:00
exports . deleteRequest = deleteRequest ;
2017-01-18 16:53:52 +03:00
exports . addAttachmentRequest = addAttachmentRequest ;
2016-04-15 02:07:31 +03:00
2016-07-13 22:09:42 +03:00
var _utils = require ( "./utils" ) ;
2016-04-15 02:07:31 +03:00
const requestDefaults = {
safe : false ,
// check if we should set default content type here
headers : { } ,
2016-07-13 22:09:42 +03:00
permissions : undefined ,
data : undefined ,
2016-04-15 02:07:31 +03:00
patch : false
} ;
2016-07-13 22:09:42 +03:00
/ * *
* @ private
* /
2016-04-15 02:07:31 +03:00
function safeHeader ( safe , last _modified ) {
if ( ! safe ) {
return { } ;
}
if ( last _modified ) {
2017-03-03 01:44:18 +03:00
return { "If-Match" : ` " ${ last _modified } " ` } ;
2016-04-15 02:07:31 +03:00
}
return { "If-None-Match" : "*" } ;
}
/ * *
* @ private
* /
2016-07-13 22:09:42 +03:00
function createRequest ( path , { data , permissions } , options = { } ) {
2018-02-14 20:48:09 +03:00
const { headers , safe } = {
... requestDefaults ,
... options
} ;
2016-04-15 02:07:31 +03:00
return {
2016-07-13 22:09:42 +03:00
method : data && data . id ? "PUT" : "POST" ,
path ,
2018-02-14 20:48:09 +03:00
headers : { ... headers , ... safeHeader ( safe ) } ,
2017-05-09 19:27:11 +03:00
body : { data , permissions }
2016-04-15 02:07:31 +03:00
} ;
}
/ * *
* @ private
* /
2016-07-13 22:09:42 +03:00
function updateRequest ( path , { data , permissions } , options = { } ) {
2018-02-14 20:48:09 +03:00
const { headers , safe , patch } = { ... requestDefaults , ... options } ;
const { last _modified } = { ... data , ... options } ;
2016-04-15 02:07:31 +03:00
2016-07-13 22:09:42 +03:00
if ( Object . keys ( ( 0 , _utils . omit ) ( data , "id" , "last_modified" ) ) . length === 0 ) {
data = undefined ;
2016-04-15 02:07:31 +03:00
}
return {
method : patch ? "PATCH" : "PUT" ,
2016-07-13 22:09:42 +03:00
path ,
2018-02-14 20:48:09 +03:00
headers : { ... headers , ... safeHeader ( safe , last _modified ) } ,
2017-05-09 19:27:11 +03:00
body : { data , permissions }
} ;
}
/ * *
* @ private
* /
function jsonPatchPermissionsRequest ( path , permissions , opType , options = { } ) {
2018-02-14 20:48:09 +03:00
const { headers , safe , last _modified } = { ... requestDefaults , ... options } ;
2017-05-09 19:27:11 +03:00
const ops = [ ] ;
for ( const [ type , principals ] of Object . entries ( permissions ) ) {
for ( const principal of principals ) {
ops . push ( {
op : opType ,
path : ` /permissions/ ${ type } / ${ principal } `
} ) ;
2016-04-15 02:07:31 +03:00
}
2017-05-09 19:27:11 +03:00
}
return {
method : "PATCH" ,
path ,
2018-02-14 20:48:09 +03:00
headers : {
... headers ,
... safeHeader ( safe , last _modified ) ,
2017-05-09 19:27:11 +03:00
"Content-Type" : "application/json-patch+json"
2018-02-14 20:48:09 +03:00
} ,
2017-05-09 19:27:11 +03:00
body : ops
2016-04-15 02:07:31 +03:00
} ;
}
/ * *
* @ private
* /
2016-07-13 22:09:42 +03:00
function deleteRequest ( path , options = { } ) {
2018-02-14 20:48:09 +03:00
const { headers , safe , last _modified } = {
... requestDefaults ,
... options
} ;
2016-04-15 02:07:31 +03:00
if ( safe && ! last _modified ) {
throw new Error ( "Safe concurrency check requires a last_modified value." ) ;
}
return {
method : "DELETE" ,
2016-07-13 22:09:42 +03:00
path ,
2018-02-14 20:48:09 +03:00
headers : { ... headers , ... safeHeader ( safe , last _modified ) }
2016-04-15 02:07:31 +03:00
} ;
}
2017-01-18 16:53:52 +03:00
/ * *
* @ private
* /
function addAttachmentRequest ( path , dataURI , { data , permissions } = { } , options = { } ) {
2018-02-14 20:48:09 +03:00
const { headers , safe , gzipped } = { ... requestDefaults , ... options } ;
const { last _modified } = { ... data , ... options } ;
2017-01-18 16:53:52 +03:00
const body = { data , permissions } ;
const formData = ( 0 , _utils . createFormData ) ( dataURI , body , options ) ;
2017-05-09 19:27:11 +03:00
let customPath = gzipped != null ? customPath = path + "?gzipped=" + ( gzipped ? "true" : "false" ) : path ;
2017-01-18 16:53:52 +03:00
return {
method : "POST" ,
path : customPath ,
2018-02-14 20:48:09 +03:00
headers : { ... headers , ... safeHeader ( safe , last _modified ) } ,
2017-01-18 16:53:52 +03:00
body : formData
} ;
}
2017-03-03 01:44:18 +03:00
} , { "./utils" : 15 } ] , 15 : [ function ( require , module , exports ) {
2016-04-15 02:07:31 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . partition = partition ;
2017-05-09 19:27:11 +03:00
exports . delay = delay ;
2016-04-15 02:07:31 +03:00
exports . pMap = pMap ;
exports . omit = omit ;
exports . toDataBody = toDataBody ;
exports . qsify = qsify ;
exports . checkVersion = checkVersion ;
exports . support = support ;
2016-07-13 22:09:42 +03:00
exports . capable = capable ;
2016-04-15 02:07:31 +03:00
exports . nobatch = nobatch ;
2016-07-13 22:09:42 +03:00
exports . isObject = isObject ;
2017-01-18 16:53:52 +03:00
exports . parseDataURL = parseDataURL ;
exports . extractFileInfo = extractFileInfo ;
exports . createFormData = createFormData ;
2017-05-09 19:27:11 +03:00
exports . cleanUndefinedProperties = cleanUndefinedProperties ;
2016-04-15 02:07:31 +03:00
/ * *
* Chunks an array into n pieces .
*
* @ private
* @ param { Array } array
* @ param { Number } n
* @ return { Array }
* /
function partition ( array , n ) {
if ( n <= 0 ) {
return array ;
}
return array . reduce ( ( acc , x , i ) => {
if ( i === 0 || i % n === 0 ) {
acc . push ( [ x ] ) ;
} else {
acc [ acc . length - 1 ] . push ( x ) ;
}
return acc ;
} , [ ] ) ;
}
2017-05-09 19:27:11 +03:00
/ * *
* Returns a Promise always resolving after the specified amount in milliseconds .
*
* @ return Promise < void >
* /
function delay ( ms ) {
return new Promise ( resolve => setTimeout ( resolve , ms ) ) ;
}
2016-04-15 02:07:31 +03:00
/ * *
* Maps a list to promises using the provided mapping function , executes them
* sequentially then returns a Promise resolving with ordered results obtained .
* Think of this as a sequential Promise . all .
*
* @ private
* @ param { Array } list The list to map .
* @ param { Function } fn The mapping function .
* @ return { Promise }
* /
2017-05-09 19:27:11 +03:00
async function pMap ( list , fn ) {
2016-04-15 02:07:31 +03:00
let results = [ ] ;
2017-05-09 19:27:11 +03:00
await list . reduce ( async function ( promise , entry ) {
await promise ;
results = results . concat ( ( await fn ( entry ) ) ) ;
} , Promise . resolve ( ) ) ;
return results ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Takes an object and returns a copy of it with the provided keys omitted .
*
* @ private
* @ param { Object } obj The source object .
* @ param { ... String } keys The keys to omit .
* @ return { Object }
* /
function omit ( obj , ... keys ) {
return Object . keys ( obj ) . reduce ( ( acc , key ) => {
2018-02-01 22:45:22 +03:00
if ( ! keys . includes ( key ) ) {
2016-04-15 02:07:31 +03:00
acc [ key ] = obj [ key ] ;
}
return acc ;
} , { } ) ;
}
/ * *
* Always returns a resource data object from the provided argument .
*
* @ private
2016-07-13 22:09:42 +03:00
* @ param { Object | String } resource
2016-04-15 02:07:31 +03:00
* @ return { Object }
* /
2016-07-13 22:09:42 +03:00
function toDataBody ( resource ) {
if ( isObject ( resource ) ) {
return resource ;
2016-04-15 02:07:31 +03:00
}
2016-07-13 22:09:42 +03:00
if ( typeof resource === "string" ) {
return { id : resource } ;
2016-04-15 02:07:31 +03:00
}
2016-07-13 22:09:42 +03:00
throw new Error ( "Invalid argument." ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Transforms an object into an URL query string , stripping out any undefined
* values .
*
* @ param { Object } obj
* @ return { String }
* /
function qsify ( obj ) {
const encode = v => encodeURIComponent ( typeof v === "boolean" ? String ( v ) : v ) ;
const stripUndefined = o => JSON . parse ( JSON . stringify ( o ) ) ;
const stripped = stripUndefined ( obj ) ;
return Object . keys ( stripped ) . map ( k => {
const ks = encode ( k ) + "=" ;
if ( Array . isArray ( stripped [ k ] ) ) {
2017-01-18 16:53:52 +03:00
return ks + stripped [ k ] . map ( v => encode ( v ) ) . join ( "," ) ;
2016-04-15 02:07:31 +03:00
} else {
return ks + encode ( stripped [ k ] ) ;
}
2017-01-18 16:53:52 +03:00
} ) . join ( "&" ) ;
2016-04-15 02:07:31 +03:00
}
/ * *
* Checks if a version is within the provided range .
*
* @ param { String } version The version to check .
* @ param { String } minVersion The minimum supported version ( inclusive ) .
* @ param { String } maxVersion The minimum supported version ( exclusive ) .
* @ throws { Error } If the version is outside of the provided range .
* /
function checkVersion ( version , minVersion , maxVersion ) {
const extract = str => str . split ( "." ) . map ( x => parseInt ( x , 10 ) ) ;
const [ verMajor , verMinor ] = extract ( version ) ;
const [ minMajor , minMinor ] = extract ( minVersion ) ;
const [ maxMajor , maxMinor ] = extract ( maxVersion ) ;
const checks = [ verMajor < minMajor , verMajor === minMajor && verMinor < minMinor , verMajor > maxMajor , verMajor === maxMajor && verMinor >= maxMinor ] ;
if ( checks . some ( x => x ) ) {
2017-05-09 19:27:11 +03:00
throw new Error ( ` Version ${ version } doesn't satisfy ${ minVersion } <= x < ${ maxVersion } ` ) ;
2016-04-15 02:07:31 +03:00
}
}
/ * *
* Generates a decorator function ensuring a version check is performed against
* the provided requirements before executing it .
*
* @ param { String } min The required min version ( inclusive ) .
* @ param { String } max The required max version ( inclusive ) .
* @ return { Function }
* /
function support ( min , max ) {
return function ( target , key , descriptor ) {
const fn = descriptor . value ;
return {
configurable : true ,
get ( ) {
const wrappedMethod = ( ... args ) => {
// "this" is the current instance which its method is decorated.
const client = "client" in this ? this . client : this ;
2017-01-18 16:53:52 +03:00
return client . fetchHTTPApiVersion ( ) . then ( version => checkVersion ( version , min , max ) ) . then ( ( ) => fn . apply ( this , args ) ) ;
2016-04-15 02:07:31 +03:00
} ;
Object . defineProperty ( this , key , {
value : wrappedMethod ,
configurable : true ,
writable : true
} ) ;
return wrappedMethod ;
}
} ;
} ;
}
2016-07-13 22:09:42 +03:00
/ * *
* Generates a decorator function ensuring that the specified capabilities are
* available on the server before executing it .
*
* @ param { Array < String > } capabilities The required capabilities .
* @ return { Function }
* /
function capable ( capabilities ) {
return function ( target , key , descriptor ) {
const fn = descriptor . value ;
return {
configurable : true ,
get ( ) {
const wrappedMethod = ( ... args ) => {
// "this" is the current instance which its method is decorated.
const client = "client" in this ? this . client : this ;
return client . fetchServerCapabilities ( ) . then ( available => {
2017-05-09 19:27:11 +03:00
const missing = capabilities . filter ( c => ! ( c in available ) ) ;
2016-07-13 22:09:42 +03:00
if ( missing . length > 0 ) {
2017-05-09 19:27:11 +03:00
const missingStr = missing . join ( ", " ) ;
throw new Error ( ` Required capabilities ${ missingStr } not present on server ` ) ;
2016-07-13 22:09:42 +03:00
}
2017-01-18 16:53:52 +03:00
} ) . then ( ( ) => fn . apply ( this , args ) ) ;
2016-07-13 22:09:42 +03:00
} ;
Object . defineProperty ( this , key , {
value : wrappedMethod ,
configurable : true ,
writable : true
} ) ;
return wrappedMethod ;
}
} ;
} ;
}
2016-04-15 02:07:31 +03:00
/ * *
* Generates a decorator function ensuring an operation is not performed from
* within a batch request .
*
* @ param { String } message The error message to throw .
* @ return { Function }
* /
function nobatch ( message ) {
return function ( target , key , descriptor ) {
const fn = descriptor . value ;
return {
configurable : true ,
get ( ) {
const wrappedMethod = ( ... args ) => {
// "this" is the current instance which its method is decorated.
if ( this . _isBatch ) {
throw new Error ( message ) ;
}
return fn . apply ( this , args ) ;
} ;
Object . defineProperty ( this , key , {
value : wrappedMethod ,
configurable : true ,
writable : true
} ) ;
return wrappedMethod ;
}
} ;
} ;
}
2016-07-13 22:09:42 +03:00
/ * *
* Returns true if the specified value is an object ( i . e . not an array nor null ) .
* @ param { Object } thing The value to inspect .
* @ return { bool }
* /
function isObject ( thing ) {
return typeof thing === "object" && thing !== null && ! Array . isArray ( thing ) ;
}
2017-01-18 16:53:52 +03:00
/ * *
* Parses a data url .
* @ param { String } dataURL The data url .
* @ return { Object }
* /
function parseDataURL ( dataURL ) {
const regex = /^data:(.*);base64,(.*)/ ;
const match = dataURL . match ( regex ) ;
if ( ! match ) {
2017-03-03 01:44:18 +03:00
throw new Error ( ` Invalid data-url: ${ String ( dataURL ) . substr ( 0 , 32 ) } ... ` ) ;
2017-01-18 16:53:52 +03:00
}
const props = match [ 1 ] ;
const base64 = match [ 2 ] ;
const [ type , ... rawParams ] = props . split ( ";" ) ;
const params = rawParams . reduce ( ( acc , param ) => {
const [ key , value ] = param . split ( "=" ) ;
2018-02-14 20:48:09 +03:00
return { ... acc , [ key ] : value } ;
2017-01-18 16:53:52 +03:00
} , { } ) ;
2018-02-14 20:48:09 +03:00
return { ... params , type , base64 } ;
2017-01-18 16:53:52 +03:00
}
/ * *
* Extracts file information from a data url .
* @ param { String } dataURL The data url .
* @ return { Object }
* /
function extractFileInfo ( dataURL ) {
const { name , type , base64 } = parseDataURL ( dataURL ) ;
const binary = atob ( base64 ) ;
const array = [ ] ;
for ( let i = 0 ; i < binary . length ; i ++ ) {
array . push ( binary . charCodeAt ( i ) ) ;
}
const blob = new Blob ( [ new Uint8Array ( array ) ] , { type } ) ;
return { blob , name } ;
}
/ * *
* Creates a FormData instance from a data url and an existing JSON response
* body .
* @ param { String } dataURL The data url .
* @ param { Object } body The response body .
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . filename ] Force attachment file name .
* @ return { FormData }
* /
function createFormData ( dataURL , body , options = { } ) {
const { filename = "untitled" } = options ;
const { blob , name } = extractFileInfo ( dataURL ) ;
const formData = new FormData ( ) ;
formData . append ( "attachment" , blob , name || filename ) ;
for ( const property in body ) {
if ( typeof body [ property ] !== "undefined" ) {
formData . append ( property , JSON . stringify ( body [ property ] ) ) ;
}
}
return formData ;
}
2017-05-09 19:27:11 +03:00
/ * *
* Clones an object with all its undefined keys removed .
* @ private
* /
function cleanUndefinedProperties ( obj ) {
const result = { } ;
for ( const key in obj ) {
if ( typeof obj [ key ] !== "undefined" ) {
result [ key ] = obj [ key ] ;
}
}
return result ;
}
2016-04-15 02:07:31 +03:00
} , { } ] } , { } , [ 1 ] ) ( 1 )
2017-08-30 11:50:27 +03:00
} ) ;