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
2019-07-05 16:45:56 +03:00
var EXPORTED _SYMBOLS = [ "KintoHttpClient" ] ;
const { setTimeout , clearTimeout } = ChromeUtils . import ( "resource://gre/modules/Timer.jsm" ) ;
const { XPCOMUtils } = ChromeUtils . import ( "resource://gre/modules/XPCOMUtils.jsm" ) ;
XPCOMUtils . defineLazyGlobalGetters ( global , [ "fetch" ] ) ;
2016-04-15 02:07:31 +03:00
/ *
2019-07-30 16:32:45 +03:00
* Version 4.7 . 3 - 3796 f57
2016-04-15 02:07:31 +03:00
* /
2018-10-09 17:05:01 +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 r ( e , n , t ) { function o ( i , f ) { if ( ! n [ i ] ) { if ( ! e [ i ] ) { var c = "function" == typeof require && require ; if ( ! f && c ) return c ( i , ! 0 ) ; if ( u ) return u ( i , ! 0 ) ; var a = new Error ( "Cannot find module '" + i + "'" ) ; throw a . code = "MODULE_NOT_FOUND" , a } var p = n [ i ] = { exports : { } } ; e [ i ] [ 0 ] . call ( p . exports , function ( r ) { var n = e [ i ] [ 1 ] [ r ] ; return o ( n || r ) } , p , p . exports , r , e , n , t ) } return n [ i ] . exports } for ( var u = "function" == typeof require && require , i = 0 ; i < t . length ; i ++ ) o ( t [ i ] ) ; return o } return r } ) ( ) ( { 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
} ) ;
2018-10-09 17:05:01 +03:00
exports . default = void 0 ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
var _base = _interopRequireDefault ( require ( "../src/base" ) ) ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
var errors = _interopRequireWildcard ( require ( "../src/errors" ) ) ;
2018-02-14 20:48:09 +03:00
2018-10-09 17:05:01 +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 ) ) { var desc = Object . defineProperty && Object . getOwnPropertyDescriptor ? Object . getOwnPropertyDescriptor ( obj , key ) : { } ; if ( desc . get || desc . set ) { Object . defineProperty ( newObj , key , desc ) ; } else { newObj [ key ] = obj [ key ] ; } } } } newObj . default = obj ; return newObj ; } }
2018-02-14 20:48:09 +03:00
2016-04-15 02:07:31 +03:00
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
2018-10-09 17:05:01 +03:00
const {
EventEmitter
2019-01-17 21:18:31 +03:00
} = ChromeUtils . import ( "resource://gre/modules/EventEmitter.jsm" ) ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
class KintoHttpClient extends _base . default {
2016-04-15 02:07:31 +03:00
constructor ( remote , options = { } ) {
const events = { } ;
EventEmitter . decorate ( events ) ;
2018-10-09 17:05:01 +03:00
super ( remote , {
events ,
... options
} ) ;
2016-04-15 02:07:31 +03:00
}
2018-02-14 20:48:09 +03:00
2018-10-09 17:05:01 +03:00
}
2018-02-14 20:48:09 +03:00
2018-10-09 17:05:01 +03:00
exports . default = KintoHttpClient ;
KintoHttpClient . errors = errors ; // This fixes compatibility with CommonJS required by browserify.
2016-04-15 02:07:31 +03:00
// See http://stackoverflow.com/questions/33505992/babel-6-changes-how-it-exports-default/33683495#33683495
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
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 ;
2019-07-05 16:45:56 +03:00
// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
return ( [ 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 ++ ] ] ,
bth [ buf [ i ++ ] ] , bth [ buf [ i ++ ] ] ] ) . join ( '' ) ;
2017-03-03 01:44:18 +03:00
}
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
2019-07-05 16:45:56 +03:00
// getRandomValues needs to be invoked in a context where "this" is a Crypto
// implementation. Also, find the complete implementation of crypto on IE11.
var getRandomValues = ( typeof ( crypto ) != 'undefined' && crypto . getRandomValues && crypto . getRandomValues . bind ( crypto ) ) ||
( typeof ( msCrypto ) != 'undefined' && typeof window . msCrypto . getRandomValues == 'function' && msCrypto . getRandomValues . bind ( msCrypto ) ) ;
2018-02-14 20:48:09 +03:00
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
} ) ;
2018-10-09 17:05:01 +03:00
exports . default = exports . SUPPORTED _PROTOCOL _VERSION = void 0 ;
2016-04-15 02:07:31 +03:00
var _utils = require ( "./utils" ) ;
2018-10-09 17:05:01 +03:00
var _http = _interopRequireDefault ( require ( "./http" ) ) ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
var _endpoint = _interopRequireDefault ( require ( "./endpoint" ) ) ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
var requests = _interopRequireWildcard ( require ( "./requests" ) ) ;
2016-04-15 02:07:31 +03:00
var _batch = require ( "./batch" ) ;
2018-10-09 17:05:01 +03:00
var _bucket = _interopRequireDefault ( require ( "./bucket" ) ) ;
2016-04-15 02:07:31 +03:00
2019-07-05 16:45:56 +03:00
var _dec , _dec2 , _dec3 , _dec4 , _dec5 , _dec6 , _dec7 , _dec8 , _class ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +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 ) ) { var desc = Object . defineProperty && Object . getOwnPropertyDescriptor ? Object . getOwnPropertyDescriptor ( obj , key ) : { } ; if ( desc . get || desc . set ) { Object . defineProperty ( newObj , key , desc ) ; } else { 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 } ; }
2019-07-05 16:45:56 +03:00
function _applyDecoratedDescriptor ( target , property , decorators , descriptor , context ) { var desc = { } ; Object . keys ( 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 . defineProperty ( target , property , desc ) ; desc = null ; } return desc ; }
2016-04-15 02:07:31 +03:00
/ * *
* Currently supported protocol version .
* @ type { String }
* /
2018-10-09 17:05:01 +03:00
const SUPPORTED _PROTOCOL _VERSION = "v1" ;
2016-04-15 02:07:31 +03:00
/ * *
* 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-10-09 17:05:01 +03:00
* . then ( console . log . bind ( console ) )
* . catch ( console . error . bind ( console ) ) ;
2016-04-15 02:07:31 +03:00
* /
2018-10-09 17:05:01 +03:00
exports . SUPPORTED _PROTOCOL _VERSION = SUPPORTED _PROTOCOL _VERSION ;
2019-07-05 16:45:56 +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" ) , _dec8 = ( 0 , _utils . capable ) ( [ "accounts" ] ) , ( _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 ) ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
if ( remote [ remote . length - 1 ] === "/" ) {
remote = remote . slice ( 0 , - 1 ) ;
}
2018-10-09 17:05:01 +03:00
this . _backoffReleaseTime = null ;
2016-04-15 02:07:31 +03:00
this . _requests = [ ] ;
this . _isBatch = ! ! options . batch ;
2017-05-09 19:27:11 +03:00
this . _retry = options . retry || 0 ;
this . _safe = ! ! options . safe ;
2018-10-09 17:05:01 +03:00
this . _headers = options . headers || { } ; // public properties
2016-04-15 02:07:31 +03:00
/ * *
* The remote server base URL .
* @ type { String }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
this . remote = remote ;
/ * *
* Current server information .
* @ ignore
* @ type { Object | null }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
this . serverInfo = null ;
/ * *
* The event emitter instance . Should comply with the ` EventEmitter `
* interface .
* @ ignore
* @ type { Class }
* /
2018-10-09 17:05:01 +03:00
this . events = options . events ;
const {
requestMode ,
timeout
} = options ;
2016-04-15 02:07:31 +03:00
/ * *
* The HTTP instance .
* @ ignore
* @ type { HTTP }
* /
2018-10-09 17:05:01 +03:00
this . http = new _http . 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 }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
get remote ( ) {
return this . _remote ;
}
/ * *
* @ ignore
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
set remote ( url ) {
let version ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
try {
version = url . match ( /\/(v\d+)\/?$/ ) [ 1 ] ;
} catch ( err ) {
throw new Error ( "The remote URL must contain the version: " + url ) ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
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
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
this . _remote = url ;
this . _version = version ;
}
/ * *
* The current server protocol version , eg . ` v1 ` .
* @ type { String }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
get version ( ) {
return this . _version ;
}
/ * *
* Backoff remaining time , in milliseconds . Defaults to zero if no backoff is
* ongoing .
*
* @ type { Number }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
get backoff ( ) {
const currentTime = new Date ( ) . getTime ( ) ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
if ( this . _backoffReleaseTime && currentTime < this . _backoffReleaseTime ) {
return this . _backoffReleaseTime - currentTime ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
return 0 ;
}
/ * *
* Registers HTTP events .
* @ private
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
_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 }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
bucket ( name , options = { } ) {
2018-10-09 17:05:01 +03:00
return new _bucket . default ( this , name , {
2017-05-09 19:27:11 +03:00
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 .
* /
2018-10-09 17:05:01 +03:00
2018-02-14 20:48:09 +03:00
setHeaders ( headers ) {
2018-10-09 17:05:01 +03:00
this . _headers = { ... this . _headers ,
2018-02-14 20:48:09 +03:00
... 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 }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
_getHeaders ( options ) {
2018-10-09 17:05:01 +03:00
return { ... this . _headers ,
2018-02-14 20:48:09 +03:00
... 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 }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
_getSafe ( options ) {
2018-10-09 17:05:01 +03:00
return {
safe : this . _safe ,
... options
} . safe ;
2017-05-09 19:27:11 +03:00
}
/ * *
* As _getSafe , but for "retry" .
*
* @ private
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
_getRetry ( options ) {
2018-10-09 17:05:01 +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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async _getHello ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = this . remote + ( 0 , _endpoint . default ) ( "root" ) ;
const {
json
} = await this . http . request ( path , {
headers : this . _getHeaders ( options )
} , {
retry : this . _getRetry ( options )
} ) ;
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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
}
2018-10-09 17:05:01 +03:00
this . serverInfo = await this . _getHello ( {
retry : this . _getRetry ( options )
} ) ;
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async fetchServerSettings ( options ) {
2018-10-09 17:05:01 +03:00
const {
settings
} = await this . fetchServerInfo ( options ) ;
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async fetchServerCapabilities ( options = { } ) {
2018-10-09 17:05:01 +03:00
const {
capabilities
} = await this . fetchServerInfo ( options ) ;
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async fetchUser ( options = { } ) {
2018-10-09 17:05:01 +03:00
const {
user
} = await this . _getHello ( options ) ;
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async fetchHTTPApiVersion ( options = { } ) {
2018-10-09 17:05:01 +03:00
const {
http _api _version
} = await this . fetchServerInfo ( options ) ;
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async _batchRequests ( requests , options = { } ) {
const headers = this . _getHeaders ( options ) ;
2018-10-09 17:05:01 +03:00
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
}
2018-10-09 17:05:01 +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" ] ;
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
if ( maxRequests && requests . length > maxRequests ) {
const chunks = ( 0 , _utils . partition ) ( requests , maxRequests ) ;
return ( 0 , _utils . pMap ) ( chunks , chunk => this . _batchRequests ( chunk , options ) ) ;
}
2018-10-09 17:05:01 +03:00
const {
responses
} = await this . execute ( {
2017-05-09 19:27:11 +03:00
// FIXME: is this really necessary, since it's also present in
// the "defaults"?
headers ,
2018-10-09 17:05:01 +03:00
path : ( 0 , _endpoint . default ) ( "batch" ) ,
2017-05-09 19:27:11 +03:00
method : "POST" ,
body : {
2018-10-09 17:05:01 +03:00
defaults : {
headers
} ,
2017-05-09 19:27:11 +03:00
requests
}
2018-10-09 17:05:01 +03:00
} , {
retry : this . _getRetry ( options )
} ) ;
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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 ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
if ( options . bucket ) {
bucketBatch = rootBatch . bucket ( options . bucket ) ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
if ( options . collection ) {
collBatch = bucketBatch . collection ( options . collection ) ;
}
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
const batchClient = collBatch || bucketBatch || rootBatch ;
2017-05-09 19:27:11 +03:00
fn ( batchClient ) ;
const responses = await this . _batchRequests ( rootBatch . _requests , options ) ;
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async execute ( request , options = { } ) {
2018-10-09 17:05:01 +03:00
const {
raw = false ,
stringify = true
} = options ; // If we're within a batch, add the request to the stack to send at once.
2016-04-15 02:07:31 +03:00
if ( this . _isBatch ) {
2018-10-09 17:05:01 +03:00
this . _requests . push ( request ) ; // Resolve with a message in case people attempt at consuming the result
2016-04-15 02:07:31 +03:00
// from within a batch operation.
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
const msg = "This result is generated from within a batch " + "operation and should not be consumed." ;
2018-10-09 17:05:01 +03:00
return raw ? {
json : msg ,
headers : {
get ( ) { }
}
} : msg ;
2016-04-15 02:07:31 +03:00
}
2018-10-09 17:05:01 +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
2018-10-09 17:05:01 +03:00
} ) , {
retry : this . _getRetry ( options )
} ) ;
2017-05-09 19:27:11 +03:00
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 .
2019-07-05 16:45:56 +03:00
* @ param { Array } [ params . fields ]
* Limit response to just some fields .
2017-05-09 19:27:11 +03:00
* @ 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 .
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
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-10-09 17:05:01 +03:00
const {
sort ,
filters ,
limit ,
pages ,
2019-07-05 16:45:56 +03:00
since ,
fields
2018-10-09 17:05:01 +03:00
} = {
2018-02-14 20:48:09 +03:00
sort : "-last_modified" ,
... params
2018-10-09 17:05:01 +03:00
} ; // Safety/Consistency check on ETag value.
2017-01-18 16:53:52 +03:00
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
}
2019-07-05 16:45:56 +03:00
const query = { ... filters ,
2017-01-18 16:53:52 +03:00
_sort : sort ,
_limit : limit ,
_since : since
2019-07-05 16:45:56 +03:00
} ;
if ( fields ) {
query . _fields = fields ;
}
const querystring = ( 0 , _utils . qsify ) ( query ) ;
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." ) ;
}
2018-10-09 17:05:01 +03:00
2017-01-18 16:53:52 +03:00
return processNextPage ( nextPage ) ;
} ;
2017-06-22 13:51:42 +03:00
const processNextPage = async nextPage => {
2018-10-09 17:05:01 +03:00
const {
headers
} = options ;
return handleResponse ( ( await this . http . request ( nextPage , {
headers
} ) ) ) ;
2017-06-22 13:51:42 +03:00
} ;
2017-01-18 16:53:52 +03:00
2019-07-05 16:45:56 +03:00
const pageResults = ( results , nextPage , etag ) => {
2017-01-18 16:53:52 +03:00
// 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 ) ,
2019-07-05 16:45:56 +03:00
hasNextPage : ! ! nextPage
2017-01-18 16:53:52 +03:00
} ;
} ;
2018-10-09 17:05:01 +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" ) ;
if ( ! pages ) {
2019-07-05 16:45:56 +03:00
return pageResults ( json . data , nextPage , etag ) ;
2018-10-09 17:05:01 +03:00
} // Aggregate new results with previous ones
2017-01-18 16:53:52 +03:00
results = results . concat ( json . data ) ;
current += 1 ;
2018-10-09 17:05:01 +03:00
2017-01-18 16:53:52 +03:00
if ( current >= pages || ! nextPage ) {
// Pagination exhausted
2019-07-05 16:45:56 +03:00
return pageResults ( results , nextPage , etag ) ;
2018-10-09 17:05:01 +03:00
} // Follow next page
2017-01-18 16:53:52 +03:00
return processNextPage ( nextPage ) ;
} ;
2017-05-09 19:27:11 +03:00
2018-10-09 17:05:01 +03:00
return handleResponse ( ( await this . execute ( // N.B.: This doesn't use _getHeaders, because all calls to
2017-05-09 19:27:11 +03:00
// `paginatedList` are assumed to come from calls that already
// have headers merged at e.g. the bucket or collection level.
2018-10-09 17:05:01 +03:00
{
headers : options . headers ,
path : path + "?" + querystring
} , // N.B. This doesn't use _getRetry, because all calls to
2017-05-09 19:27:11 +03:00
// `paginatedList` are assumed to come from calls that already
// used `_getRetry` at e.g. the bucket or collection level.
2018-10-09 17:05:01 +03:00
{
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async listPermissions ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "permissions" ) ; // Ensure the default sort parameter is something that exists in permissions
2017-05-09 19:27:11 +03:00
// entries, as `last_modified` doesn't; here, we pick "id".
2018-10-09 17:05:01 +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 .
2019-07-05 16:45:56 +03:00
* @ param { Object } [ options . filters = { } ] The filters object .
* @ param { Array } [ options . fields ] Limit response to
* just some fields .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object [ ] , Error > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async listBuckets ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . 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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async createBucket ( id , options = { } ) {
2018-10-09 17:05:01 +03:00
const {
data = { } ,
permissions
} = options ;
2017-05-09 19:27:11 +03:00
if ( id != null ) {
data . id = id ;
2016-07-13 22:09:42 +03:00
}
2018-10-09 17:05:01 +03:00
const path = data . id ? ( 0 , _endpoint . default ) ( "bucket" , data . id ) : ( 0 , _endpoint . default ) ( "bucket" ) ;
return this . execute ( requests . createRequest ( path , {
data ,
permissions
} , {
2017-05-09 19:27:11 +03:00
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
2018-10-09 17:05:01 +03:00
} ) , {
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 > }
* /
2018-10-09 17:05:01 +03:00
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 ) ;
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
if ( ! bucketObj . id ) {
throw new Error ( "A bucket id is required." ) ;
}
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "bucket" , bucketObj . id ) ;
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 )
2018-10-09 17:05:01 +03:00
} ) , {
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async deleteBuckets ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . 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 )
2018-10-09 17:05:01 +03:00
} ) , {
retry : this . _getRetry ( options )
} ) ;
2016-04-15 02:07:31 +03:00
}
2018-10-09 17:05:01 +03:00
2019-07-05 16:45:56 +03:00
async createAccount ( username , password ) {
return this . execute ( requests . createRequest ( ` /accounts/ ${ username } ` , {
data : {
password
}
} , {
method : "PUT"
} ) ) ;
}
} , ( _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 ) , _applyDecoratedDescriptor ( _class . prototype , "createAccount" , [ _dec8 ] , Object . getOwnPropertyDescriptor ( _class . prototype , "createAccount" ) , _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 ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
/ * *
* 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." ) ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
const results = {
errors : [ ] ,
published : [ ] ,
conflicts : [ ] ,
skipped : [ ]
} ;
return responses . reduce ( ( acc , response , index ) => {
2018-10-09 17:05:01 +03:00
const {
status
} = response ;
2017-01-18 16:53:52 +03:00
const request = requests [ index ] ;
2018-10-09 17:05:01 +03:00
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
} ) ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
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
} ) ;
2018-10-09 17:05:01 +03:00
exports . default = void 0 ;
2017-01-18 16:53:52 +03:00
2016-04-15 02:07:31 +03:00
var _utils = require ( "./utils" ) ;
2018-10-09 17:05:01 +03:00
var _collection = _interopRequireDefault ( require ( "./collection" ) ) ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
var requests = _interopRequireWildcard ( require ( "./requests" ) ) ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
var _endpoint = _interopRequireDefault ( require ( "./endpoint" ) ) ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
var _dec , _class ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +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 ) ) { var desc = Object . defineProperty && Object . getOwnPropertyDescriptor ? Object . getOwnPropertyDescriptor ( obj , key ) : { } ; if ( desc . get || desc . set ) { Object . defineProperty ( newObj , key , desc ) ; } else { 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 } ; }
2019-07-05 16:45:56 +03:00
function _applyDecoratedDescriptor ( target , property , decorators , descriptor , context ) { var desc = { } ; Object . keys ( 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 . defineProperty ( target , property , desc ) ; desc = null ; } return desc ; }
2017-01-18 16:53:52 +03:00
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 }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
this . name = name ;
/ * *
* @ ignore
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
this . _isBatch = ! ! options . batch ;
2016-04-15 02:07:31 +03:00
/ * *
* @ ignore
* /
2018-10-09 17:05:01 +03:00
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
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
_getHeaders ( options ) {
2018-10-09 17:05:01 +03:00
return { ... this . _headers ,
2018-02-14 20:48:09 +03:00
... 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 }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
_getSafe ( options ) {
2018-10-09 17:05:01 +03:00
return {
safe : this . _safe ,
... options
} . safe ;
2017-05-09 19:27:11 +03:00
}
/ * *
* As _getSafe , but for "retry" .
*
* @ private
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
_getRetry ( options ) {
2018-10-09 17:05:01 +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 }
* /
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
collection ( name , options = { } ) {
2018-10-09 17:05:01 +03:00
return new _collection . default ( this . client , this , name , {
2017-05-09 19:27:11 +03:00
batch : this . _isBatch ,
headers : this . _getHeaders ( options ) ,
retry : this . _getRetry ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2016-04-15 02:07:31 +03:00
}
2019-07-05 16:45:56 +03:00
/ * *
* Retrieves the ETag of the collection list , for use with the ` since ` filtering option .
*
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
* @ return { Promise < String , Error > }
* /
async getCollectionsTimestamp ( options = { } ) {
const path = ( 0 , _endpoint . default ) ( "collection" , this . name ) ;
const request = {
headers : this . _getHeaders ( options ) ,
path ,
method : "HEAD"
} ;
const {
headers
} = await this . client . execute ( request , {
raw : true ,
retry : this . _getRetry ( options )
} ) ;
return headers . get ( "ETag" ) ;
}
/ * *
* Retrieves the ETag of the group list , for use with the ` since ` filtering option .
*
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
* @ return { Promise < String , Error > }
* /
async getGroupsTimestamp ( options = { } ) {
const path = ( 0 , _endpoint . default ) ( "group" , this . name ) ;
const request = {
headers : this . _getHeaders ( options ) ,
path ,
method : "HEAD"
} ;
const {
headers
} = await this . client . execute ( request , {
raw : true ,
retry : this . _getRetry ( options )
} ) ;
return headers . get ( "ETag" ) ;
}
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 .
2019-07-05 16:45:56 +03:00
* @ param { Object } [ options . query ] Query parameters to pass in
* the request . This might be useful for features that aren ' t
* yet supported by this library .
* @ param { Array } [ options . fields ] Limit response to
* just some fields .
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async getData ( options = { } ) {
2019-07-05 16:45:56 +03:00
let path = ( 0 , _endpoint . default ) ( "bucket" , this . name ) ;
path = ( 0 , _utils . addEndpointOptions ) ( path , options ) ;
2017-05-09 19:27:11 +03:00
const request = {
headers : this . _getHeaders ( options ) ,
2019-07-05 16:45:56 +03:00
path
2017-05-09 19:27:11 +03:00
} ;
2018-10-09 17:05:01 +03:00
const {
data
} = await this . client . execute ( request , {
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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-10-09 17:05:01 +03:00
const bucket = { ... data ,
id : this . name
} ; // For default bucket, we need to drop the id from the data object.
2016-07-13 22:09:42 +03:00
// Bug in Kinto < 3.1.1
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
const bucketId = bucket . id ;
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
if ( bucket . id === "default" ) {
delete bucket . id ;
}
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "bucket" , bucketId ) ;
const {
patch ,
permissions
} = options ;
const {
last _modified
} = { ... data ,
... options
} ;
const request = requests . updateRequest ( path , {
data : bucket ,
permissions
} , {
2017-05-09 19:27:11 +03:00
last _modified ,
patch ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async listHistory ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . 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 .
2019-07-05 16:45:56 +03:00
* @ param { Object } [ options . filters = { } ] The filters object .
2016-07-13 22:09:42 +03:00
* @ 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 .
2019-07-05 16:45:56 +03:00
* @ param { Array } [ options . fields ] Limit response to
* just some fields .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Array < Object > , Error > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async listCollections ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . 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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async createCollection ( id , options = { } ) {
2018-10-09 17:05:01 +03:00
const {
permissions ,
data = { }
} = options ;
2016-07-13 22:09:42 +03:00
data . id = id ;
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "collection" , this . name , id ) ;
const request = requests . createRequest ( path , {
data ,
permissions
} , {
2017-05-09 19:27:11 +03:00
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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 ) ;
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
if ( ! collectionObj . id ) {
throw new Error ( "A collection id is required." ) ;
}
2018-10-09 17:05:01 +03:00
const {
id
} = collectionObj ;
const {
last _modified
} = { ... collectionObj ,
... options
} ;
const path = ( 0 , _endpoint . 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 )
} ) ;
2018-10-09 17:05:01 +03:00
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 .
2019-07-05 16:45:56 +03:00
* @ param { Object } [ options . filters = { } ] The filters object .
2016-07-13 22:09:42 +03:00
* @ 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 .
2019-07-05 16:45:56 +03:00
* @ param { Array } [ options . fields ] Limit response to
* just some fields .
2016-07-13 22:09:42 +03:00
* @ return { Promise < Array < Object > , Error > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async listGroups ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . 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
}
/ * *
2019-07-05 16:45:56 +03:00
* Fetches a group in current bucket .
2016-07-13 22:09:42 +03:00
*
* @ 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 .
2019-07-05 16:45:56 +03:00
* @ param { Object } [ options . query ] Query parameters to pass in
* the request . This might be useful for features that aren ' t
* yet supported by this library .
* @ param { Array } [ options . fields ] Limit response to
* just some fields .
2016-07-13 22:09:42 +03:00
* @ return { Promise < Object , Error > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async getGroup ( id , options = { } ) {
2019-07-05 16:45:56 +03:00
let path = ( 0 , _endpoint . default ) ( "group" , this . name , id ) ;
path = ( 0 , _utils . addEndpointOptions ) ( path , options ) ;
2017-05-09 19:27:11 +03:00
const request = {
headers : this . _getHeaders ( options ) ,
2019-07-05 16:45:56 +03:00
path
2017-05-09 19:27:11 +03:00
} ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async createGroup ( id , members = [ ] , options = { } ) {
2018-10-09 17:05:01 +03:00
const data = { ... options . data ,
2016-07-13 22:09:42 +03:00
id ,
members
2018-02-14 20:48:09 +03:00
} ;
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "group" , this . name , id ) ;
const {
permissions
} = options ;
const request = requests . createRequest ( path , {
data ,
permissions
} , {
2017-05-09 19:27:11 +03:00
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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." ) ;
}
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
if ( ! group . id ) {
throw new Error ( "A group id is required." ) ;
}
2018-10-09 17:05:01 +03:00
const data = { ... options . data ,
2018-02-14 20:48:09 +03:00
... group
} ;
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "group" , this . name , group . id ) ;
const {
patch ,
permissions
} = options ;
const {
last _modified
} = { ... data ,
... options
} ;
const request = requests . updateRequest ( path , {
data ,
permissions
} , {
2017-05-09 19:27:11 +03:00
last _modified ,
patch ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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 ) ;
2018-10-09 17:05:01 +03:00
const {
id
} = groupObj ;
const {
last _modified
} = { ... groupObj ,
... options
} ;
const path = ( 0 , _endpoint . 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 )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async getPermissions ( options = { } ) {
const request = {
headers : this . _getHeaders ( options ) ,
2018-10-09 17:05:01 +03:00
path : ( 0 , _endpoint . default ) ( "bucket" , this . name )
2017-05-09 19:27:11 +03:00
} ;
2018-10-09 17:05:01 +03:00
const {
permissions
} = await this . client . execute ( request , {
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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." ) ;
}
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "bucket" , this . name ) ;
const {
last _modified
} = options ;
const data = {
last _modified
} ;
const request = requests . updateRequest ( path , {
data ,
permissions
} , {
2017-05-09 19:27:11 +03:00
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
return this . client . execute ( request , {
retry : this . _getRetry ( options )
} ) ;
2017-05-09 19:27:11 +03:00
}
/ * *
* 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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async addPermissions ( permissions , options = { } ) {
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "bucket" , this . name ) ;
const {
last _modified
} = options ;
2017-05-09 19:27:11 +03:00
const request = requests . jsonPatchPermissionsRequest ( path , permissions , "add" , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
return this . client . execute ( request , {
retry : this . _getRetry ( options )
} ) ;
2017-05-09 19:27:11 +03:00
}
/ * *
* 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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async removePermissions ( permissions , options = { } ) {
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "bucket" , this . name ) ;
const {
last _modified
} = options ;
2017-05-09 19:27:11 +03:00
const request = requests . jsonPatchPermissionsRequest ( path , permissions , "remove" , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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
}
2018-10-09 17:05:01 +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
} ) ;
2018-10-09 17:05:01 +03:00
exports . default = void 0 ;
2017-01-18 16:53:52 +03:00
var _uuid = require ( "uuid" ) ;
2016-04-15 02:07:31 +03:00
var _utils = require ( "./utils" ) ;
2018-10-09 17:05:01 +03:00
var requests = _interopRequireWildcard ( require ( "./requests" ) ) ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
var _endpoint = _interopRequireDefault ( require ( "./endpoint" ) ) ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
var _dec , _dec2 , _dec3 , _class ;
2016-04-15 02:07:31 +03:00
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
2018-10-09 17:05:01 +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 ) ) { var desc = Object . defineProperty && Object . getOwnPropertyDescriptor ? Object . getOwnPropertyDescriptor ( obj , key ) : { } ; if ( desc . get || desc . set ) { Object . defineProperty ( newObj , key , desc ) ; } else { newObj [ key ] = obj [ key ] ; } } } } newObj . default = obj ; return newObj ; } }
2017-01-18 16:53:52 +03:00
2019-07-05 16:45:56 +03:00
function _applyDecoratedDescriptor ( target , property , decorators , descriptor , context ) { var desc = { } ; Object . keys ( 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 . defineProperty ( target , property , desc ) ; desc = null ; } return desc ; }
2017-01-18 16:53:52 +03:00
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
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
this . bucket = bucket ;
/ * *
* The collection name .
* @ type { String }
* /
2018-10-09 17:05:01 +03:00
this . name = name ;
2016-04-15 02:07:31 +03:00
/ * *
* @ ignore
* /
2017-05-09 19:27:11 +03:00
2018-10-09 17:05:01 +03:00
this . _isBatch = ! ! options . batch ;
2016-04-15 02:07:31 +03:00
/ * *
* @ ignore
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
this . _retry = options . retry || 0 ;
2018-10-09 17:05:01 +03:00
this . _safe = ! ! options . safe ; // FIXME: This is kind of ugly; shouldn't the bucket be responsible
2017-05-09 19:27:11 +03:00
// for doing the merge?
2018-10-09 17:05:01 +03:00
this . _headers = { ... this . bucket . _headers ,
2018-02-14 20:48:09 +03:00
... 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
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
_getHeaders ( options ) {
2018-10-09 17:05:01 +03:00
return { ... this . _headers ,
2018-02-14 20:48:09 +03:00
... 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 }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
_getSafe ( options ) {
2018-10-09 17:05:01 +03:00
return {
safe : this . _safe ,
... options
} . safe ;
2017-05-09 19:27:11 +03:00
}
/ * *
* As _getSafe , but for "retry" .
*
* @ private
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
_getRetry ( options ) {
2018-10-09 17:05:01 +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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async getTotalRecords ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "record" , this . bucket . name , this . name ) ;
2017-05-09 19:27:11 +03:00
const request = {
headers : this . _getHeaders ( options ) ,
path ,
method : "HEAD"
} ;
2018-10-09 17:05:01 +03:00
const {
headers
} = await this . client . execute ( request , {
2017-05-09 19:27:11 +03:00
raw : true ,
retry : this . _getRetry ( options )
} ) ;
return parseInt ( headers . get ( "Total-Records" ) , 10 ) ;
2017-01-18 16:53:52 +03:00
}
2019-07-05 16:45:56 +03:00
/ * *
* Retrieves the ETag of the records list , for use with the ` since ` filtering option .
*
* @ param { Object } [ options = { } ] The options object .
* @ param { Object } [ options . headers ] The headers object option .
* @ param { Number } [ options . retry = 0 ] Number of retries to make
* when faced with transient errors .
* @ return { Promise < String , Error > }
* /
async getRecordsTimestamp ( options = { } ) {
const path = ( 0 , _endpoint . default ) ( "record" , this . bucket . name , this . name ) ;
const request = {
headers : this . _getHeaders ( options ) ,
path ,
method : "HEAD"
} ;
const {
headers
} = await this . client . execute ( request , {
raw : true ,
retry : this . _getRetry ( options )
} ) ;
return headers . get ( "ETag" ) ;
}
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 .
2018-10-09 17:05:01 +03:00
* @ param { Object } [ options . query ] Query parameters to pass in
* the request . This might be useful for features that aren ' t
* yet supported by this library .
2019-07-05 16:45:56 +03:00
* @ param { Array } [ options . fields ] Limit response to
* just some fields .
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async getData ( options = { } ) {
2018-10-09 17:05:01 +03:00
let path = ( 0 , _endpoint . default ) ( "collection" , this . bucket . name , this . name ) ;
2019-07-05 16:45:56 +03:00
path = ( 0 , _utils . addEndpointOptions ) ( path , options ) ;
2018-10-09 17:05:01 +03:00
const request = {
headers : this . _getHeaders ( options ) ,
path
} ;
const {
data
} = await this . client . execute ( request , {
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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." ) ;
}
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
const {
patch ,
permissions
} = options ;
const {
last _modified
} = { ... data ,
... options
} ;
const path = ( 0 , _endpoint . default ) ( "collection" , this . bucket . name , this . name ) ;
const request = requests . updateRequest ( path , {
data ,
permissions
} , {
2017-05-09 19:27:11 +03:00
last _modified ,
patch ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async getPermissions ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "collection" , this . bucket . name , this . name ) ;
const request = {
headers : this . _getHeaders ( options ) ,
path
} ;
const {
permissions
} = await this . client . execute ( request , {
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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." ) ;
}
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "collection" , this . bucket . name , this . name ) ;
const data = {
last _modified : options . last _modified
} ;
const request = requests . updateRequest ( path , {
data ,
permissions
} , {
2017-05-09 19:27:11 +03:00
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
return this . client . execute ( request , {
retry : this . _getRetry ( options )
} ) ;
2017-05-09 19:27:11 +03:00
}
/ * *
* 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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async addPermissions ( permissions , options = { } ) {
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "collection" , this . bucket . name , this . name ) ;
const {
last _modified
} = options ;
2017-05-09 19:27:11 +03:00
const request = requests . jsonPatchPermissionsRequest ( path , permissions , "add" , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
return this . client . execute ( request , {
retry : this . _getRetry ( options )
} ) ;
2017-05-09 19:27:11 +03:00
}
/ * *
* 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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async removePermissions ( permissions , options = { } ) {
if ( ! ( 0 , _utils . isObject ) ( permissions ) ) {
throw new Error ( "A permissions object is required." ) ;
}
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "collection" , this . bucket . name , this . name ) ;
const {
last _modified
} = options ;
2017-05-09 19:27:11 +03:00
const request = requests . jsonPatchPermissionsRequest ( path , permissions , "remove" , {
last _modified ,
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async createRecord ( record , options = { } ) {
2018-10-09 17:05:01 +03:00
const {
permissions
} = options ;
const path = ( 0 , _endpoint . default ) ( "record" , this . bucket . name , this . name , record . id ) ;
const request = requests . createRequest ( path , {
data : record ,
permissions
} , {
2017-05-09 19:27:11 +03:00
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async addAttachment ( dataURI , record = { } , options = { } ) {
2018-10-09 17:05:01 +03:00
const {
permissions
} = options ;
2017-01-18 16:53:52 +03:00
const id = record . id || _uuid . v4 . v4 ( ) ;
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "attachment" , this . bucket . name , this . name , id ) ;
const {
last _modified
} = { ... record ,
... options
} ;
const addAttachmentRequest = requests . addAttachmentRequest ( path , dataURI , {
data : record ,
permissions
} , {
2017-05-09 19:27:11 +03:00
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 .
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async removeAttachment ( recordId , options = { } ) {
2018-10-09 17:05:01 +03:00
const {
last _modified
} = options ;
const path = ( 0 , _endpoint . 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 )
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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." ) ;
}
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
if ( ! record . id ) {
throw new Error ( "A record id is required." ) ;
}
2018-10-09 17:05:01 +03:00
const {
permissions
} = options ;
const {
last _modified
} = { ... record ,
... options
} ;
const path = ( 0 , _endpoint . default ) ( "record" , this . bucket . name , this . name , record . id ) ;
const request = requests . updateRequest ( path , {
data : record ,
permissions
} , {
2017-05-09 19:27:11 +03:00
headers : this . _getHeaders ( options ) ,
safe : this . _getSafe ( options ) ,
last _modified ,
patch : ! ! options . patch
} ) ;
2018-10-09 17:05:01 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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 ) ;
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
if ( ! recordObj . id ) {
throw new Error ( "A record id is required." ) ;
}
2018-10-09 17:05:01 +03:00
const {
id
} = recordObj ;
const {
last _modified
} = { ... recordObj ,
... options
} ;
const path = ( 0 , _endpoint . 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 )
} ) ;
2018-10-09 17:05:01 +03:00
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 .
2019-07-05 16:45:56 +03:00
* @ param { Object } [ options . query ] Query parameters to pass in
* the request . This might be useful for features that aren ' t
* yet supported by this library .
* @ param { Array } [ options . fields ] Limit response to
* just some fields .
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 > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async getRecord ( id , options = { } ) {
2019-07-05 16:45:56 +03:00
let path = ( 0 , _endpoint . default ) ( "record" , this . bucket . name , this . name , id ) ;
path = ( 0 , _utils . addEndpointOptions ) ( path , options ) ;
2018-10-09 17:05:01 +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 .
2019-07-05 16:45:56 +03:00
* @ param { Object } [ options . filters = { } ] The filters object .
2016-07-13 22:09:42 +03:00
* @ 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 .
2019-07-05 16:45:56 +03:00
* @ param { Array } [ options . fields ] Limit response to just some fields .
2016-04-15 02:07:31 +03:00
* @ return { Promise < Object , Error > }
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async listRecords ( options = { } ) {
2018-10-09 17:05:01 +03:00
const path = ( 0 , _endpoint . default ) ( "record" , this . bucket . name , this . name ) ;
2019-07-05 16:45:56 +03:00
if ( Object . prototype . hasOwnProperty . call ( options , "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
* /
2018-10-09 17:05:01 +03:00
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.
2018-10-09 17:05:01 +03:00
const {
data : [ oldestHistoryEntry ]
} = await this . bucket . listHistory ( {
2017-05-09 19:27:11 +03:00
limit : 1 ,
filters : {
action : "create" ,
resource _name : "collection" ,
collection _id : this . name
}
} ) ;
return ! ! oldestHistoryEntry ;
}
/ * *
* @ private
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
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
}
2018-10-09 17:05:01 +03:00
const {
data : changes
} = await this . bucket . listHistory ( {
pages : Infinity ,
// all pages up to target timestamp are required
2017-03-03 01:44:18 +03:00
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 <=
2018-10-09 17:05:01 +03:00
2018-02-14 20:48:09 +03:00
}
2017-03-03 01:44:18 +03:00
} ) ;
2017-05-09 19:27:11 +03:00
return changes ;
}
/ * *
* @ private
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async getSnapshot ( at ) {
if ( ! Number . isInteger ( at ) || at <= 0 ) {
throw new Error ( "Invalid argument, expected a positive integer." ) ;
2018-10-09 17:05:01 +03:00
} // Retrieve history and check it covers the required time range.
const changes = await this . listChangesBackTo ( at ) ; // Replay changes to compute the requested snapshot.
2017-05-09 19:27:11 +03:00
const seenIds = new Set ( ) ;
let snapshot = [ ] ;
2018-10-09 17:05:01 +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
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
snapshot = snapshot . filter ( r => r . id !== record . id ) ;
} else if ( ! seenIds . has ( record . id ) ) {
seenIds . add ( record . id ) ;
snapshot . push ( record ) ;
}
}
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
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 > }
* /
2018-10-09 17:05:01 +03:00
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
}
2018-10-09 17:05:01 +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 ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
/ * *
* 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 }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
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
} ) ;
2018-10-09 17:05:01 +03:00
exports . UnparseableResponseError = exports . ServerResponse = exports . NetworkTimeoutError = exports . default = void 0 ;
2016-04-15 02:07:31 +03:00
/ * *
* 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-10-09 17:05:01 +03:00
var _default = ERROR _CODES ;
exports . default = _default ;
2016-04-15 02:07:31 +03:00
2018-10-09 17:05:01 +03:00
class NetworkTimeoutError extends Error {
2018-02-14 20:48:09 +03:00
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 ;
}
2018-10-09 17:05:01 +03:00
}
exports . NetworkTimeoutError = NetworkTimeoutError ;
class UnparseableResponseError extends Error {
constructor ( response , body , error ) {
const {
status
} = response ;
2018-02-14 20:48:09 +03:00
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 ;
}
2018-10-09 17:05:01 +03:00
}
2018-02-14 20:48:09 +03:00
/ * *
* "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 ) .
* /
2018-10-09 17:05:01 +03:00
exports . UnparseableResponseError = UnparseableResponseError ;
class ServerResponse extends Error {
2018-02-14 20:48:09 +03:00
constructor ( response , json ) {
2018-10-09 17:05:01 +03:00
const {
status
} = response ;
let {
statusText
} = response ;
2018-02-14 20:48:09 +03:00
let errnoMsg ;
if ( json ) {
// Try to fill in information from the JSON error.
2018-10-09 17:05:01 +03:00
statusText = json . error || statusText ; // Take errnoMsg from either ERROR_CODES or json.message.
2018-02-14 20:48:09 +03:00
if ( json . errno && json . errno in ERROR _CODES ) {
errnoMsg = ERROR _CODES [ json . errno ] ;
} else if ( json . message ) {
errnoMsg = json . message ;
2018-10-09 17:05:01 +03:00
} // If we had both ERROR_CODES and json.message, and they differ,
2018-02-14 20:48:09 +03:00
// combine them.
2018-10-09 17:05:01 +03:00
2018-02-14 20:48:09 +03:00
if ( errnoMsg && json . message && json . message !== errnoMsg ) {
errnoMsg += ` ( ${ json . message } ) ` ;
}
}
let message = ` HTTP ${ status } ${ statusText } ` ;
2018-10-09 17:05:01 +03:00
2018-02-14 20:48:09 +03:00
if ( errnoMsg ) {
message += ` : ${ errnoMsg } ` ;
}
super ( message . trim ( ) ) ;
2018-10-09 17:05:01 +03:00
2018-02-14 20:48:09 +03:00
if ( Error . captureStackTrace ) {
Error . captureStackTrace ( this , ServerResponse ) ;
}
this . response = response ;
this . data = json ;
}
2018-10-09 17:05:01 +03:00
}
2018-02-14 20:48:09 +03:00
exports . ServerResponse = ServerResponse ;
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
} ) ;
2018-10-09 17:05:01 +03:00
exports . default = void 0 ;
2016-04-15 02:07:31 +03:00
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
* /
2018-10-09 17:05:01 +03:00
class HTTP {
2016-04-15 02:07:31 +03:00
/ * *
* 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 }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
static get defaultOptions ( ) {
2018-10-09 17:05:01 +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
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
constructor ( events , options = { } ) {
// public properties
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
/ * *
* The event emitter instance .
* @ type { EventEmitter }
* /
if ( ! events ) {
throw new Error ( "No events handler provided" ) ;
}
2018-10-09 17:05:01 +03:00
this . events = events ;
2016-04-15 02:07:31 +03:00
/ * *
* The request mode .
* @ see https : //fetch.spec.whatwg.org/#requestmode
* @ type { String }
* /
2018-10-09 17:05:01 +03:00
this . requestMode = options . requestMode || HTTP . defaultOptions . requestMode ;
2016-04-15 02:07:31 +03:00
/ * *
* The request timeout .
* @ type { Number }
* /
2018-10-09 17:05:01 +03:00
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
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
timedFetch ( url , options ) {
let hasTimedout = false ;
return new Promise ( ( resolve , reject ) => {
// Detect if a request has timed out.
let _timeoutId ;
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
if ( this . timeout ) {
_timeoutId = setTimeout ( ( ) => {
hasTimedout = true ;
2019-07-30 16:32:45 +03:00
if ( options && options . headers ) {
options = { ... options ,
headers : ( 0 , _utils . replaceKey ) ( options . headers , "authorization" , "**** (suppressed)" )
} ;
}
2018-02-14 20:48:09 +03:00
reject ( new _errors . NetworkTimeoutError ( url , options ) ) ;
2017-05-09 19:27:11 +03:00
} , this . timeout ) ;
}
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
function proceedWithHandler ( fn ) {
return arg => {
if ( ! hasTimedout ) {
if ( _timeoutId ) {
clearTimeout ( _timeoutId ) ;
}
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
fn ( arg ) ;
}
} ;
}
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
fetch ( url , options ) . then ( proceedWithHandler ( resolve ) ) . catch ( proceedWithHandler ( reject ) ) ;
} ) ;
}
/ * *
* @ private
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async processResponse ( response ) {
2018-10-09 17:05:01 +03:00
const {
status ,
headers
} = response ;
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 ;
2018-10-09 17:05:01 +03:00
2018-02-14 20:48:09 +03:00
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
}
2018-10-09 17:05:01 +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
}
2018-10-09 17:05:01 +03:00
return {
status ,
json ,
headers
} ;
}
2017-05-09 19:27:11 +03:00
/ * *
* @ private
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
async retry ( url , retryAfter , request , options ) {
await ( 0 , _utils . delay ) ( retryAfter ) ;
2018-10-09 17:05:01 +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 }
* /
2018-10-09 17:05:01 +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-10-09 17:05:01 +03:00
request . headers = { ... HTTP . DEFAULT _REQUEST _HEADERS ,
... request . headers
} ; // If a multipart body is provided, remove any custom Content-Type header as
2017-01-18 16:53:52 +03:00
// the fetch() implementation will add the correct one for us.
2018-10-09 17:05:01 +03:00
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
}
2018-10-09 17:05:01 +03:00
request . mode = this . requestMode ;
2017-05-09 19:27:11 +03:00
const response = await this . timedFetch ( url , request ) ;
2018-10-09 17:05:01 +03:00
const {
status ,
headers
} = response ;
2017-05-09 19:27:11 +03:00
this . _checkForDeprecationHeader ( headers ) ;
2018-10-09 17:05:01 +03:00
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.
2017-05-09 19:27:11 +03:00
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" ) ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
if ( ! alertHeader ) {
return ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
let alert ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
try {
alert = JSON . parse ( alertHeader ) ;
} catch ( err ) {
console . warn ( "Unable to parse Alert header message" , alertHeader ) ;
return ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
console . warn ( alert . message , alert . url ) ;
this . events . emit ( "deprecated" , alert ) ;
}
_checkForBackoffHeader ( status , headers ) {
let backoffMs ;
const backoffSeconds = parseInt ( headers . get ( "Backoff" ) , 10 ) ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
if ( backoffSeconds > 0 ) {
backoffMs = new Date ( ) . getTime ( ) + backoffSeconds * 1000 ;
} else {
backoffMs = 0 ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
this . events . emit ( "backoff" , backoffMs ) ;
}
2016-07-13 22:09:42 +03:00
_checkForRetryAfterHeader ( status , headers ) {
let retryAfter = headers . get ( "Retry-After" ) ;
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
if ( ! retryAfter ) {
return ;
}
2018-10-09 17:05:01 +03:00
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
}
2018-10-09 17:05:01 +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
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
function safeHeader ( safe , last _modified ) {
if ( ! safe ) {
return { } ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
if ( last _modified ) {
2018-10-09 17:05:01 +03:00
return {
"If-Match" : ` " ${ last _modified } " `
} ;
2016-04-15 02:07:31 +03:00
}
2018-10-09 17:05:01 +03:00
return {
"If-None-Match" : "*"
} ;
}
2016-04-15 02:07:31 +03:00
/ * *
* @ private
* /
2018-10-09 17:05:01 +03:00
function createRequest ( path , {
data ,
permissions
} , options = { } ) {
const {
headers ,
safe
} = { ... requestDefaults ,
2018-02-14 20:48:09 +03:00
... options
} ;
2019-07-05 16:45:56 +03:00
const method = options . method || data && data . id ? "PUT" : "POST" ;
2016-04-15 02:07:31 +03:00
return {
2019-07-05 16:45:56 +03:00
method ,
2016-07-13 22:09:42 +03:00
path ,
2018-10-09 17:05:01 +03:00
headers : { ... headers ,
... safeHeader ( safe )
} ,
body : {
data ,
permissions
}
2016-04-15 02:07:31 +03:00
} ;
}
/ * *
* @ private
* /
2018-10-09 17:05:01 +03:00
function updateRequest ( path , {
data ,
permissions
} , options = { } ) {
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-10-09 17:05:01 +03:00
headers : { ... headers ,
... safeHeader ( safe , last _modified )
} ,
body : {
data ,
permissions
}
2017-05-09 19:27:11 +03:00
} ;
}
/ * *
* @ private
* /
2018-10-09 17:05:01 +03:00
function jsonPatchPermissionsRequest ( path , permissions , opType , options = { } ) {
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-10-09 17:05:01 +03:00
headers : { ... headers ,
2018-02-14 20:48:09 +03:00
... 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
* /
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
function deleteRequest ( path , options = { } ) {
2018-10-09 17:05:01 +03:00
const {
headers ,
safe ,
last _modified
} = { ... requestDefaults ,
2018-02-14 20:48:09 +03:00
... options
} ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
if ( safe && ! last _modified ) {
throw new Error ( "Safe concurrency check requires a last_modified value." ) ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
return {
method : "DELETE" ,
2016-07-13 22:09:42 +03:00
path ,
2018-10-09 17:05:01 +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
* /
2018-10-09 17:05:01 +03:00
function addAttachmentRequest ( path , dataURI , {
data ,
permissions
} = { } , options = { } ) {
const {
headers ,
safe ,
gzipped
} = { ... requestDefaults ,
... options
} ;
const {
last _modified
} = { ... data ,
... options
} ;
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-10-09 17:05:01 +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 ;
2019-07-30 16:32:45 +03:00
exports . replaceKey = replaceKey ;
2016-04-15 02:07:31 +03:00
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 ;
2019-07-05 16:45:56 +03:00
exports . addEndpointOptions = addEndpointOptions ;
2018-10-09 17:05:01 +03:00
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 ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
return array . reduce ( ( acc , x , i ) => {
if ( i === 0 || i % n === 0 ) {
acc . push ( [ x ] ) ;
} else {
acc [ acc . length - 1 ] . push ( x ) ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
return acc ;
} , [ ] ) ;
}
2017-05-09 19:27:11 +03:00
/ * *
* Returns a Promise always resolving after the specified amount in milliseconds .
*
* @ return Promise < void >
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
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 }
* /
2018-10-09 17:05:01 +03:00
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 ;
2019-07-05 16:45:56 +03:00
const out = await fn ( entry ) ;
results = results . concat ( out ) ;
2017-05-09 19:27:11 +03:00
} , 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 }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
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 ] ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
return acc ;
} , { } ) ;
}
2019-07-30 16:32:45 +03:00
/ * *
* Replace an object key ( case insensitive ) value with the specified one .
*
* @ private
* @ param { Object } obj
* @ param { String } key
* @ param { Object } value
* @ return { Object }
* /
function replaceKey ( obj , key , value ) {
return Object . keys ( obj ) . reduce ( ( acc , k ) => {
acc [ k ] = k . toLowerCase ( ) == key . toLowerCase ( ) ? value : obj [ k ] ;
return acc ;
} , { } ) ;
}
2016-04-15 02:07:31 +03:00
/ * *
* 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 }
* /
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
function toDataBody ( resource ) {
if ( isObject ( resource ) ) {
return resource ;
2016-04-15 02:07:31 +03:00
}
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
if ( typeof resource === "string" ) {
2018-10-09 17:05:01 +03:00
return {
id : resource
} ;
2016-04-15 02:07:31 +03:00
}
2018-10-09 17:05:01 +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 }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
function qsify ( obj ) {
const encode = v => encodeURIComponent ( typeof v === "boolean" ? String ( v ) : v ) ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
const stripUndefined = o => JSON . parse ( JSON . stringify ( o ) ) ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
const stripped = stripUndefined ( obj ) ;
return Object . keys ( stripped ) . map ( k => {
const ks = encode ( k ) + "=" ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
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 .
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
function checkVersion ( version , minVersion , maxVersion ) {
const extract = str => str . split ( "." ) . map ( x => parseInt ( x , 10 ) ) ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
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 ] ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
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 }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
function support ( min , max ) {
return function ( target , key , descriptor ) {
const fn = descriptor . value ;
return {
configurable : true ,
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
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
} ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
Object . defineProperty ( this , key , {
value : wrappedMethod ,
configurable : true ,
writable : true
} ) ;
return wrappedMethod ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
} ;
} ;
}
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 }
* /
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
function capable ( capabilities ) {
return function ( target , key , descriptor ) {
const fn = descriptor . value ;
return {
configurable : true ,
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
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 ) ) ;
2018-10-09 17:05:01 +03:00
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
} ;
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
Object . defineProperty ( this , key , {
value : wrappedMethod ,
configurable : true ,
writable : true
} ) ;
return wrappedMethod ;
}
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
} ;
} ;
}
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 }
* /
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
function nobatch ( message ) {
return function ( target , key , descriptor ) {
const fn = descriptor . value ;
return {
configurable : true ,
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
get ( ) {
const wrappedMethod = ( ... args ) => {
// "this" is the current instance which its method is decorated.
if ( this . _isBatch ) {
throw new Error ( message ) ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
return fn . apply ( this , args ) ;
} ;
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
Object . defineProperty ( this , key , {
value : wrappedMethod ,
configurable : true ,
writable : true
} ) ;
return wrappedMethod ;
}
2018-10-09 17:05:01 +03:00
2016-04-15 02:07:31 +03:00
} ;
} ;
}
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 }
* /
2018-10-09 17:05:01 +03:00
2016-07-13 22:09:42 +03:00
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 }
* /
2018-10-09 17:05:01 +03:00
2017-01-18 16:53:52 +03:00
function parseDataURL ( dataURL ) {
const regex = /^data:(.*);base64,(.*)/ ;
const match = dataURL . match ( regex ) ;
2018-10-09 17:05:01 +03:00
2017-01-18 16:53:52 +03:00
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
}
2018-10-09 17:05:01 +03:00
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-10-09 17:05:01 +03:00
return { ... acc ,
[ key ] : value
} ;
2017-01-18 16:53:52 +03:00
} , { } ) ;
2018-10-09 17:05:01 +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 }
* /
2018-10-09 17:05:01 +03:00
2017-01-18 16:53:52 +03:00
function extractFileInfo ( dataURL ) {
2018-10-09 17:05:01 +03:00
const {
name ,
type ,
base64
} = parseDataURL ( dataURL ) ;
2017-01-18 16:53:52 +03:00
const binary = atob ( base64 ) ;
const array = [ ] ;
2018-10-09 17:05:01 +03:00
2017-01-18 16:53:52 +03:00
for ( let i = 0 ; i < binary . length ; i ++ ) {
array . push ( binary . charCodeAt ( i ) ) ;
}
2019-07-30 16:32:45 +03:00
let blob ;
if ( typeof Blob !== "undefined" ) {
// Running in a browser environment.
blob = new Blob ( [ new Uint8Array ( array ) ] , {
type
} ) ;
} else {
// In NodeJS. Blob is not available.
blob = Buffer . from ( array ) ;
}
2018-10-09 17:05:01 +03:00
return {
blob ,
name
} ;
}
2017-01-18 16:53:52 +03:00
/ * *
* 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 }
* /
2018-10-09 17:05:01 +03:00
2017-01-18 16:53:52 +03:00
function createFormData ( dataURL , body , options = { } ) {
2018-10-09 17:05:01 +03:00
const {
filename = "untitled"
} = options ;
const {
blob ,
name
} = extractFileInfo ( dataURL ) ;
2017-01-18 16:53:52 +03:00
const formData = new FormData ( ) ;
formData . append ( "attachment" , blob , name || filename ) ;
2018-10-09 17:05:01 +03:00
2017-01-18 16:53:52 +03:00
for ( const property in body ) {
if ( typeof body [ property ] !== "undefined" ) {
formData . append ( property , JSON . stringify ( body [ property ] ) ) ;
}
}
2018-10-09 17:05:01 +03:00
2017-01-18 16:53:52 +03:00
return formData ;
}
2017-05-09 19:27:11 +03:00
/ * *
* Clones an object with all its undefined keys removed .
* @ private
* /
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
function cleanUndefinedProperties ( obj ) {
const result = { } ;
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
for ( const key in obj ) {
if ( typeof obj [ key ] !== "undefined" ) {
result [ key ] = obj [ key ] ;
}
}
2018-10-09 17:05:01 +03:00
2017-05-09 19:27:11 +03:00
return result ;
}
2019-07-05 16:45:56 +03:00
/ * *
* Handle common query parameters for Kinto requests .
*
* @ param { String } [ path ] The endpoint base path .
* @ param { Array } [ options . fields ] Fields to limit the
* request to .
* @ param { Object } [ options . query = { } ] Additional query arguments .
* /
function addEndpointOptions ( path , options = { } ) {
const query = { ... options . query
} ;
if ( options . fields ) {
query . _fields = options . fields ;
}
const queryString = qsify ( query ) ;
if ( queryString ) {
return path + "?" + queryString ;
}
return path ;
}
2017-05-09 19:27:11 +03:00
2016-04-15 02:07:31 +03:00
} , { } ] } , { } , [ 1 ] ) ( 1 )
2017-08-30 11:50:27 +03:00
} ) ;
2018-10-09 17:05:01 +03:00