@thirstie/thirstieservices 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2848 @@
1
+ async function apiRequest (url, requestConfig) {
2
+ const apiResponse = {
3
+ ok: null,
4
+ status: null,
5
+ statusText: null,
6
+ data: {}
7
+ };
8
+ try {
9
+ const response = await fetch(url, requestConfig);
10
+
11
+ let responseBody = {};
12
+ const headers = response.headers;
13
+ const hasBody = headers && headers.get('content-type')?.indexOf('application/json') > -1 && parseInt(headers.get('content-length')) > 0;
14
+ if (hasBody) {
15
+ responseBody = await response.json();
16
+ }
17
+ return Object.assign(apiResponse, {
18
+ ok: response.ok,
19
+ status: response.status,
20
+ statusText: response.statusText,
21
+ data: responseBody,
22
+ url
23
+ });
24
+ } catch (error) {
25
+ console.error('apiRequest error: ', error);
26
+ return Object.assign(apiResponse, {
27
+ ok: false,
28
+ status: 500,
29
+ statusText: 'ERROR',
30
+ data: { message: 'Network error', error },
31
+ url
32
+ });
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Access Thirstie API and manage session information.
38
+ */
39
+ class ThirstieAPI {
40
+ // private fields
41
+ #apiKey;
42
+ #thirstieApiBaseUrl;
43
+ #_apiState;
44
+ #emptyState;
45
+ #environment;
46
+
47
+ /**
48
+ * Initialize Thirstie API with public api key
49
+ * @param {string} apiKey - The public basic auth key, defines application access
50
+ * @param {Object=} config - Optional config settings
51
+ * @param {Object} config.env - Set to 'prod' to use production environment
52
+ * @param {Object} config.initState - Values to initialize session state
53
+ */
54
+ constructor (apiKey, config = {}) {
55
+ const { env, initState } = config;
56
+ this.#environment = env;
57
+ this.#emptyState = {
58
+ sessionToken: null,
59
+ application: null,
60
+ applicationRef: null,
61
+ sessionRef: null,
62
+ userRef: null,
63
+ user: {},
64
+ message: null
65
+ };
66
+ this.#apiKey = apiKey;
67
+ this.#thirstieApiBaseUrl =
68
+ env === 'prod'
69
+ ? 'https://api.thirstie.com'
70
+ : 'https://api.next.thirstie.com';
71
+
72
+ this.#_apiState = Object.seal(this.#emptyState);
73
+ const { sessionToken, application, applicationRef, sessionRef, userRef } = initState || {};
74
+ if (sessionToken || application || applicationRef || sessionRef || userRef) {
75
+ const apiInitState = { sessionToken, application, applicationRef, sessionRef, userRef };
76
+ this.apiState = apiInitState;
77
+ }
78
+ }
79
+
80
+ get sessionToken () {
81
+ return this.#_apiState.sessionToken;
82
+ }
83
+
84
+ get sessionRef () {
85
+ return this.#_apiState.sessionRef;
86
+ }
87
+
88
+ get userRef () {
89
+ return this.#_apiState.userRef;
90
+ }
91
+
92
+ get applicationRef () {
93
+ return this.#_apiState.applicationRef;
94
+ }
95
+
96
+ get application () {
97
+ return this.#_apiState.application;
98
+ }
99
+
100
+ /**
101
+ * Getter for session state
102
+ * This is safe to use for persisting state in localstorage
103
+ * because it does not contain user information.
104
+ */
105
+ get sessionState () {
106
+ const {
107
+ sessionToken, application, applicationRef, sessionRef, userRef
108
+ } = this.#_apiState;
109
+ return { sessionToken, application, applicationRef, sessionRef, userRef };
110
+ }
111
+
112
+ /**
113
+ * Getter for general api state, contains user information
114
+ * Only use for internal comparison.
115
+ */
116
+ get apiState () {
117
+ return this.#_apiState;
118
+ }
119
+
120
+ set apiState (props) {
121
+ try {
122
+ return Object.assign(this.#_apiState, props);
123
+ } catch (error) {
124
+ console.error('set apiState', error);
125
+ return this.#_apiState;
126
+ }
127
+ }
128
+
129
+ #handleSession (data) {
130
+ const sessionData = {
131
+ application: data.application_name,
132
+ applicationRef: data.uuid,
133
+ sessionToken: data.token,
134
+ sessionRef: data.session_uuid
135
+ };
136
+ if (data.user) {
137
+ sessionData.userRef = data.user.id;
138
+ const {
139
+ birthday, email, prefix, guest,
140
+ first_name: firstName, last_name: lastName, phone_number: phoneNumber,
141
+ last_login: lastLogin
142
+ } = data.user;
143
+ sessionData.user = {
144
+ email, birthday, prefix, firstName, lastName, phoneNumber, guest, lastLogin
145
+ };
146
+ }
147
+ this.apiState = sessionData;
148
+ }
149
+
150
+ #handleSessionError (err) {
151
+ this.apiState = this.#emptyState;
152
+ console.log('session error', err);
153
+ }
154
+
155
+ /**
156
+ * Create a new session and retrieve a bearer token.
157
+ *
158
+ * Defaults to creating an anonymous session. If userCredentials are
159
+ * provided, then a user session will be returned.
160
+ *
161
+ * @param {Object=} userCredentials - user email & password
162
+ * @param {string} userCredentials.email
163
+ * @param {string} userCredentials.password
164
+ * @param {boolean} [basicAuth=true] - force use of application basic auth
165
+ * @returns {response}
166
+ */
167
+ async getNewSession (userCredentials = {}, basicAuth = true) {
168
+ const { email, password } = userCredentials;
169
+ const options = { basicAuth };
170
+ if (email && password) {
171
+ options.data = { email, password };
172
+ }
173
+ const url = '/a/v2/sessions';
174
+ const response = await this.apiCaller('POST', url, options);
175
+ if (response && response.ok && response.data) {
176
+ return response.data;
177
+ } else {
178
+ return { code: response.status, message: response.message || 'unknown error', response };
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Validate an existing session
184
+ * @param {string} sessionToken - Session JWT to validate
185
+ * @returns {object} session response
186
+ */
187
+ async validateSession (sessionToken) {
188
+ if (sessionToken) {
189
+ this.apiState = { sessionToken };
190
+ }
191
+ if (!this.sessionToken) {
192
+ return {};
193
+ }
194
+
195
+ const url = '/a/v2/sessions';
196
+ const response = await this.apiCaller('GET', url);
197
+ if (response && response.ok && response.data) {
198
+ return response.data;
199
+ } else {
200
+ return await this.getNewSession();
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Create new session, or validates existing session and set apiState
206
+ * @param {string} [existingToken] If provided, session JWT to be validated
207
+ * @returns {object} API State
208
+ */
209
+ async fetchSession (existingToken = null) {
210
+ let sessionData = {};
211
+ if (!this.sessionToken && !existingToken) {
212
+ sessionData = await this.getNewSession();
213
+ } else {
214
+ sessionData = await this.validateSession(existingToken);
215
+ }
216
+
217
+ if (sessionData.token) {
218
+ this.#handleSession(sessionData);
219
+ } else {
220
+ this.#handleSessionError(sessionData);
221
+ }
222
+ return this.apiState;
223
+ }
224
+
225
+ /**
226
+ * Convert an anonymous session to a user session
227
+ * @param {object} userCredentials - { email, password }
228
+ * @returns {object} - api state
229
+ */
230
+ async loginUser (userCredentials) {
231
+ const { email, password } = userCredentials;
232
+
233
+ // force use of existing anonymous session token if a token exists
234
+ const basicAuth = !this.sessionToken;
235
+ if (email && password) ; else {
236
+ throw new Error('Invalid credential payload');
237
+ }
238
+
239
+ const responseData = await this.getNewSession(userCredentials, basicAuth);
240
+ if (responseData.token) {
241
+ this.#handleSession(responseData);
242
+ } else {
243
+ this.#handleSessionError(responseData);
244
+ const { response } = responseData;
245
+ const { data } = response;
246
+ if (data?.message) {
247
+ this.apiState.message = data?.message;
248
+ }
249
+ }
250
+ return this.apiState;
251
+ }
252
+
253
+ /**
254
+ * Create a new user
255
+ * @param {object} userData - { email, password, birthday, prefix, firstName, lastName, phoneNumber, guestCheck }
256
+ * @param {Function} [errorHandler] - optional error callback
257
+ * @returns {object} - api state
258
+ */
259
+ async createUser (userData, errorHandler = null) {
260
+ const options = {};
261
+ const { email, password } = userData;
262
+ const { birthday, prefix, firstName, lastName, phoneNumber, guestCheck, emailOptIn } = userData;
263
+ const requestPayload = {
264
+ email,
265
+ birthday,
266
+ prefix,
267
+ first_name: firstName,
268
+ last_name: lastName,
269
+ phone_number: phoneNumber,
270
+ guest_check: !!guestCheck // "allow guest checkout for existing user" if set to True
271
+ };
272
+
273
+ if (emailOptIn) {
274
+ requestPayload.aux_data = {
275
+ thirstieaccess_email_opt_in: emailOptIn
276
+ };
277
+ }
278
+
279
+ // force use of existing anonymous session token if a token exists
280
+ const basicAuth = !this.sessionToken;
281
+ if (email && password) {
282
+ requestPayload.password = password;
283
+ } else {
284
+ requestPayload.guest = true;
285
+ }
286
+ options.data = requestPayload;
287
+ options.basicAuth = basicAuth;
288
+
289
+ const responseData = await this.apiCaller('POST', '/a/v2/users', options, errorHandler);
290
+ if (responseData.data.token) {
291
+ this.#handleSession(responseData.data);
292
+ } else {
293
+ this.#handleSessionError(responseData);
294
+ }
295
+ return this.apiState;
296
+ }
297
+
298
+ /**
299
+ * Invoke Thirstie API Endpoint
300
+ * @param {string} method - 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'
301
+ * @param {string} url - api endpoint url
302
+ * @param {object} [options] - { data, params, basicAuth }
303
+ * @param {callback} [errorHandler] - error callback
304
+ * @returns {object} - api response
305
+ */
306
+ async apiCaller (method, url, options = {}, errorHandler = null) {
307
+ const { data, params, basicAuth } = options;
308
+ const { sessionRef, application, applicationRef, userRef } = this.apiState;
309
+
310
+ if (!this.sessionToken && !basicAuth) {
311
+ throw new Error('Invalid Authorization');
312
+ }
313
+
314
+ const authHeader = (this.sessionToken && !basicAuth)
315
+ ? `Bearer ${this.sessionToken}`
316
+ : `Basic ${btoa(this.#apiKey)}`;
317
+
318
+ const requestConfig = {
319
+ method,
320
+ headers: {
321
+ Authorization: authHeader,
322
+ Accept: 'application/json',
323
+ 'Content-Type': 'application/json'
324
+ }
325
+ };
326
+ if ([ 'POST', 'PUT', 'PATCH' ].includes(method) && !!data) {
327
+ requestConfig.body = JSON.stringify(data);
328
+ }
329
+ let queryString = '';
330
+ if (params) {
331
+ const searchParams = new URLSearchParams(params);
332
+ queryString = searchParams.toString();
333
+ }
334
+
335
+ const telemetryContext = {
336
+ environment: this.#environment,
337
+ sessionRef,
338
+ application,
339
+ applicationRef,
340
+ userRef,
341
+ data,
342
+ queryString,
343
+ url
344
+ };
345
+ const requestUrl = `${this.#thirstieApiBaseUrl}${url}${queryString}`;
346
+ try {
347
+ const response = await apiRequest(requestUrl, requestConfig);
348
+ if (response) {
349
+ if (!response.ok && errorHandler) {
350
+ errorHandler({ code: response.status, message: response.statusText || 'unknown error', response, telemetryContext });
351
+ }
352
+ return response;
353
+ }
354
+ } catch (error) {
355
+ if (errorHandler) {
356
+ errorHandler({ code: 500, message: 'unknown error', error, telemetryContext });
357
+ }
358
+ return error;
359
+ }
360
+ }
361
+ }
362
+
363
+ function _isPlaceholder(a) {
364
+ return a != null && typeof a === 'object' && a['@@functional/placeholder'] === true;
365
+ }
366
+
367
+ /**
368
+ * Optimized internal one-arity curry function.
369
+ *
370
+ * @private
371
+ * @category Function
372
+ * @param {Function} fn The function to curry.
373
+ * @return {Function} The curried function.
374
+ */
375
+
376
+ function _curry1(fn) {
377
+ return function f1(a) {
378
+ if (arguments.length === 0 || _isPlaceholder(a)) {
379
+ return f1;
380
+ } else {
381
+ return fn.apply(this, arguments);
382
+ }
383
+ };
384
+ }
385
+
386
+ /**
387
+ * Optimized internal two-arity curry function.
388
+ *
389
+ * @private
390
+ * @category Function
391
+ * @param {Function} fn The function to curry.
392
+ * @return {Function} The curried function.
393
+ */
394
+
395
+ function _curry2(fn) {
396
+ return function f2(a, b) {
397
+ switch (arguments.length) {
398
+ case 0:
399
+ return f2;
400
+
401
+ case 1:
402
+ return _isPlaceholder(a) ? f2 : _curry1(function (_b) {
403
+ return fn(a, _b);
404
+ });
405
+
406
+ default:
407
+ return _isPlaceholder(a) && _isPlaceholder(b) ? f2 : _isPlaceholder(a) ? _curry1(function (_a) {
408
+ return fn(_a, b);
409
+ }) : _isPlaceholder(b) ? _curry1(function (_b) {
410
+ return fn(a, _b);
411
+ }) : fn(a, b);
412
+ }
413
+ };
414
+ }
415
+
416
+ function _arity(n, fn) {
417
+ /* eslint-disable no-unused-vars */
418
+ switch (n) {
419
+ case 0:
420
+ return function () {
421
+ return fn.apply(this, arguments);
422
+ };
423
+
424
+ case 1:
425
+ return function (a0) {
426
+ return fn.apply(this, arguments);
427
+ };
428
+
429
+ case 2:
430
+ return function (a0, a1) {
431
+ return fn.apply(this, arguments);
432
+ };
433
+
434
+ case 3:
435
+ return function (a0, a1, a2) {
436
+ return fn.apply(this, arguments);
437
+ };
438
+
439
+ case 4:
440
+ return function (a0, a1, a2, a3) {
441
+ return fn.apply(this, arguments);
442
+ };
443
+
444
+ case 5:
445
+ return function (a0, a1, a2, a3, a4) {
446
+ return fn.apply(this, arguments);
447
+ };
448
+
449
+ case 6:
450
+ return function (a0, a1, a2, a3, a4, a5) {
451
+ return fn.apply(this, arguments);
452
+ };
453
+
454
+ case 7:
455
+ return function (a0, a1, a2, a3, a4, a5, a6) {
456
+ return fn.apply(this, arguments);
457
+ };
458
+
459
+ case 8:
460
+ return function (a0, a1, a2, a3, a4, a5, a6, a7) {
461
+ return fn.apply(this, arguments);
462
+ };
463
+
464
+ case 9:
465
+ return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) {
466
+ return fn.apply(this, arguments);
467
+ };
468
+
469
+ case 10:
470
+ return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
471
+ return fn.apply(this, arguments);
472
+ };
473
+
474
+ default:
475
+ throw new Error('First argument to _arity must be a non-negative integer no greater than ten');
476
+ }
477
+ }
478
+
479
+ /**
480
+ * Internal curryN function.
481
+ *
482
+ * @private
483
+ * @category Function
484
+ * @param {Number} length The arity of the curried function.
485
+ * @param {Array} received An array of arguments received thus far.
486
+ * @param {Function} fn The function to curry.
487
+ * @return {Function} The curried function.
488
+ */
489
+
490
+ function _curryN(length, received, fn) {
491
+ return function () {
492
+ var combined = [];
493
+ var argsIdx = 0;
494
+ var left = length;
495
+ var combinedIdx = 0;
496
+ var hasPlaceholder = false;
497
+
498
+ while (combinedIdx < received.length || argsIdx < arguments.length) {
499
+ var result;
500
+
501
+ if (combinedIdx < received.length && (!_isPlaceholder(received[combinedIdx]) || argsIdx >= arguments.length)) {
502
+ result = received[combinedIdx];
503
+ } else {
504
+ result = arguments[argsIdx];
505
+ argsIdx += 1;
506
+ }
507
+
508
+ combined[combinedIdx] = result;
509
+
510
+ if (!_isPlaceholder(result)) {
511
+ left -= 1;
512
+ } else {
513
+ hasPlaceholder = true;
514
+ }
515
+
516
+ combinedIdx += 1;
517
+ }
518
+
519
+ return !hasPlaceholder && left <= 0 ? fn.apply(this, combined) : _arity(Math.max(0, left), _curryN(length, combined, fn));
520
+ };
521
+ }
522
+
523
+ /**
524
+ * Returns a curried equivalent of the provided function, with the specified
525
+ * arity. The curried function has two unusual capabilities. First, its
526
+ * arguments needn't be provided one at a time. If `g` is `R.curryN(3, f)`, the
527
+ * following are equivalent:
528
+ *
529
+ * - `g(1)(2)(3)`
530
+ * - `g(1)(2, 3)`
531
+ * - `g(1, 2)(3)`
532
+ * - `g(1, 2, 3)`
533
+ *
534
+ * Secondly, the special placeholder value [`R.__`](#__) may be used to specify
535
+ * "gaps", allowing partial application of any combination of arguments,
536
+ * regardless of their positions. If `g` is as above and `_` is [`R.__`](#__),
537
+ * the following are equivalent:
538
+ *
539
+ * - `g(1, 2, 3)`
540
+ * - `g(_, 2, 3)(1)`
541
+ * - `g(_, _, 3)(1)(2)`
542
+ * - `g(_, _, 3)(1, 2)`
543
+ * - `g(_, 2)(1)(3)`
544
+ * - `g(_, 2)(1, 3)`
545
+ * - `g(_, 2)(_, 3)(1)`
546
+ *
547
+ * @func
548
+ * @memberOf R
549
+ * @since v0.5.0
550
+ * @category Function
551
+ * @sig Number -> (* -> a) -> (* -> a)
552
+ * @param {Number} length The arity for the returned function.
553
+ * @param {Function} fn The function to curry.
554
+ * @return {Function} A new, curried function.
555
+ * @see R.curry
556
+ * @example
557
+ *
558
+ * const sumArgs = (...args) => R.sum(args);
559
+ *
560
+ * const curriedAddFourNumbers = R.curryN(4, sumArgs);
561
+ * const f = curriedAddFourNumbers(1, 2);
562
+ * const g = f(3);
563
+ * g(4); //=> 10
564
+ */
565
+
566
+ var curryN =
567
+ /*#__PURE__*/
568
+ _curry2(function curryN(length, fn) {
569
+ if (length === 1) {
570
+ return _curry1(fn);
571
+ }
572
+
573
+ return _arity(length, _curryN(length, [], fn));
574
+ });
575
+
576
+ /**
577
+ * Optimized internal three-arity curry function.
578
+ *
579
+ * @private
580
+ * @category Function
581
+ * @param {Function} fn The function to curry.
582
+ * @return {Function} The curried function.
583
+ */
584
+
585
+ function _curry3(fn) {
586
+ return function f3(a, b, c) {
587
+ switch (arguments.length) {
588
+ case 0:
589
+ return f3;
590
+
591
+ case 1:
592
+ return _isPlaceholder(a) ? f3 : _curry2(function (_b, _c) {
593
+ return fn(a, _b, _c);
594
+ });
595
+
596
+ case 2:
597
+ return _isPlaceholder(a) && _isPlaceholder(b) ? f3 : _isPlaceholder(a) ? _curry2(function (_a, _c) {
598
+ return fn(_a, b, _c);
599
+ }) : _isPlaceholder(b) ? _curry2(function (_b, _c) {
600
+ return fn(a, _b, _c);
601
+ }) : _curry1(function (_c) {
602
+ return fn(a, b, _c);
603
+ });
604
+
605
+ default:
606
+ return _isPlaceholder(a) && _isPlaceholder(b) && _isPlaceholder(c) ? f3 : _isPlaceholder(a) && _isPlaceholder(b) ? _curry2(function (_a, _b) {
607
+ return fn(_a, _b, c);
608
+ }) : _isPlaceholder(a) && _isPlaceholder(c) ? _curry2(function (_a, _c) {
609
+ return fn(_a, b, _c);
610
+ }) : _isPlaceholder(b) && _isPlaceholder(c) ? _curry2(function (_b, _c) {
611
+ return fn(a, _b, _c);
612
+ }) : _isPlaceholder(a) ? _curry1(function (_a) {
613
+ return fn(_a, b, c);
614
+ }) : _isPlaceholder(b) ? _curry1(function (_b) {
615
+ return fn(a, _b, c);
616
+ }) : _isPlaceholder(c) ? _curry1(function (_c) {
617
+ return fn(a, b, _c);
618
+ }) : fn(a, b, c);
619
+ }
620
+ };
621
+ }
622
+
623
+ /**
624
+ * Tests whether or not an object is an array.
625
+ *
626
+ * @private
627
+ * @param {*} val The object to test.
628
+ * @return {Boolean} `true` if `val` is an array, `false` otherwise.
629
+ * @example
630
+ *
631
+ * _isArray([]); //=> true
632
+ * _isArray(null); //=> false
633
+ * _isArray({}); //=> false
634
+ */
635
+ var _isArray = Array.isArray || function _isArray(val) {
636
+ return val != null && val.length >= 0 && Object.prototype.toString.call(val) === '[object Array]';
637
+ };
638
+
639
+ function _isTransformer(obj) {
640
+ return obj != null && typeof obj['@@transducer/step'] === 'function';
641
+ }
642
+
643
+ /**
644
+ * Returns a function that dispatches with different strategies based on the
645
+ * object in list position (last argument). If it is an array, executes [fn].
646
+ * Otherwise, if it has a function with one of the given method names, it will
647
+ * execute that function (functor case). Otherwise, if it is a transformer,
648
+ * uses transducer created by [transducerCreator] to return a new transformer
649
+ * (transducer case).
650
+ * Otherwise, it will default to executing [fn].
651
+ *
652
+ * @private
653
+ * @param {Array} methodNames properties to check for a custom implementation
654
+ * @param {Function} transducerCreator transducer factory if object is transformer
655
+ * @param {Function} fn default ramda implementation
656
+ * @return {Function} A function that dispatches on object in list position
657
+ */
658
+
659
+ function _dispatchable(methodNames, transducerCreator, fn) {
660
+ return function () {
661
+ if (arguments.length === 0) {
662
+ return fn();
663
+ }
664
+
665
+ var obj = arguments[arguments.length - 1];
666
+
667
+ if (!_isArray(obj)) {
668
+ var idx = 0;
669
+
670
+ while (idx < methodNames.length) {
671
+ if (typeof obj[methodNames[idx]] === 'function') {
672
+ return obj[methodNames[idx]].apply(obj, Array.prototype.slice.call(arguments, 0, -1));
673
+ }
674
+
675
+ idx += 1;
676
+ }
677
+
678
+ if (_isTransformer(obj)) {
679
+ var transducer = transducerCreator.apply(null, Array.prototype.slice.call(arguments, 0, -1));
680
+ return transducer(obj);
681
+ }
682
+ }
683
+
684
+ return fn.apply(this, arguments);
685
+ };
686
+ }
687
+
688
+ function _reduced(x) {
689
+ return x && x['@@transducer/reduced'] ? x : {
690
+ '@@transducer/value': x,
691
+ '@@transducer/reduced': true
692
+ };
693
+ }
694
+
695
+ var _xfBase = {
696
+ init: function () {
697
+ return this.xf['@@transducer/init']();
698
+ },
699
+ result: function (result) {
700
+ return this.xf['@@transducer/result'](result);
701
+ }
702
+ };
703
+
704
+ function _arrayFromIterator(iter) {
705
+ var list = [];
706
+ var next;
707
+
708
+ while (!(next = iter.next()).done) {
709
+ list.push(next.value);
710
+ }
711
+
712
+ return list;
713
+ }
714
+
715
+ function _includesWith(pred, x, list) {
716
+ var idx = 0;
717
+ var len = list.length;
718
+
719
+ while (idx < len) {
720
+ if (pred(x, list[idx])) {
721
+ return true;
722
+ }
723
+
724
+ idx += 1;
725
+ }
726
+
727
+ return false;
728
+ }
729
+
730
+ function _functionName(f) {
731
+ // String(x => x) evaluates to "x => x", so the pattern may not match.
732
+ var match = String(f).match(/^function (\w*)/);
733
+ return match == null ? '' : match[1];
734
+ }
735
+
736
+ function _has(prop, obj) {
737
+ return Object.prototype.hasOwnProperty.call(obj, prop);
738
+ }
739
+
740
+ // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
741
+ function _objectIs(a, b) {
742
+ // SameValue algorithm
743
+ if (a === b) {
744
+ // Steps 1-5, 7-10
745
+ // Steps 6.b-6.e: +0 != -0
746
+ return a !== 0 || 1 / a === 1 / b;
747
+ } else {
748
+ // Step 6.a: NaN == NaN
749
+ return a !== a && b !== b;
750
+ }
751
+ }
752
+
753
+ var _objectIs$1 = typeof Object.is === 'function' ? Object.is : _objectIs;
754
+
755
+ var toString$1 = Object.prototype.toString;
756
+
757
+ var _isArguments =
758
+ /*#__PURE__*/
759
+ function () {
760
+ return toString$1.call(arguments) === '[object Arguments]' ? function _isArguments(x) {
761
+ return toString$1.call(x) === '[object Arguments]';
762
+ } : function _isArguments(x) {
763
+ return _has('callee', x);
764
+ };
765
+ }();
766
+
767
+ var hasEnumBug = !
768
+ /*#__PURE__*/
769
+ {
770
+ toString: null
771
+ }.propertyIsEnumerable('toString');
772
+ var nonEnumerableProps = ['constructor', 'valueOf', 'isPrototypeOf', 'toString', 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; // Safari bug
773
+
774
+ var hasArgsEnumBug =
775
+ /*#__PURE__*/
776
+ function () {
777
+
778
+ return arguments.propertyIsEnumerable('length');
779
+ }();
780
+
781
+ var contains = function contains(list, item) {
782
+ var idx = 0;
783
+
784
+ while (idx < list.length) {
785
+ if (list[idx] === item) {
786
+ return true;
787
+ }
788
+
789
+ idx += 1;
790
+ }
791
+
792
+ return false;
793
+ };
794
+ /**
795
+ * Returns a list containing the names of all the enumerable own properties of
796
+ * the supplied object.
797
+ * Note that the order of the output array is not guaranteed to be consistent
798
+ * across different JS platforms.
799
+ *
800
+ * @func
801
+ * @memberOf R
802
+ * @since v0.1.0
803
+ * @category Object
804
+ * @sig {k: v} -> [k]
805
+ * @param {Object} obj The object to extract properties from
806
+ * @return {Array} An array of the object's own properties.
807
+ * @see R.keysIn, R.values, R.toPairs
808
+ * @example
809
+ *
810
+ * R.keys({a: 1, b: 2, c: 3}); //=> ['a', 'b', 'c']
811
+ */
812
+
813
+
814
+ var keys = typeof Object.keys === 'function' && !hasArgsEnumBug ?
815
+ /*#__PURE__*/
816
+ _curry1(function keys(obj) {
817
+ return Object(obj) !== obj ? [] : Object.keys(obj);
818
+ }) :
819
+ /*#__PURE__*/
820
+ _curry1(function keys(obj) {
821
+ if (Object(obj) !== obj) {
822
+ return [];
823
+ }
824
+
825
+ var prop, nIdx;
826
+ var ks = [];
827
+
828
+ var checkArgsLength = hasArgsEnumBug && _isArguments(obj);
829
+
830
+ for (prop in obj) {
831
+ if (_has(prop, obj) && (!checkArgsLength || prop !== 'length')) {
832
+ ks[ks.length] = prop;
833
+ }
834
+ }
835
+
836
+ if (hasEnumBug) {
837
+ nIdx = nonEnumerableProps.length - 1;
838
+
839
+ while (nIdx >= 0) {
840
+ prop = nonEnumerableProps[nIdx];
841
+
842
+ if (_has(prop, obj) && !contains(ks, prop)) {
843
+ ks[ks.length] = prop;
844
+ }
845
+
846
+ nIdx -= 1;
847
+ }
848
+ }
849
+
850
+ return ks;
851
+ });
852
+
853
+ /**
854
+ * Gives a single-word string description of the (native) type of a value,
855
+ * returning such answers as 'Object', 'Number', 'Array', or 'Null'. Does not
856
+ * attempt to distinguish user Object types any further, reporting them all as
857
+ * 'Object'.
858
+ *
859
+ * @func
860
+ * @memberOf R
861
+ * @since v0.8.0
862
+ * @category Type
863
+ * @sig * -> String
864
+ * @param {*} val The value to test
865
+ * @return {String}
866
+ * @example
867
+ *
868
+ * R.type({}); //=> "Object"
869
+ * R.type(1); //=> "Number"
870
+ * R.type(false); //=> "Boolean"
871
+ * R.type('s'); //=> "String"
872
+ * R.type(null); //=> "Null"
873
+ * R.type([]); //=> "Array"
874
+ * R.type(/[A-z]/); //=> "RegExp"
875
+ * R.type(() => {}); //=> "Function"
876
+ * R.type(async () => {}); //=> "AsyncFunction"
877
+ * R.type(undefined); //=> "Undefined"
878
+ */
879
+
880
+ var type =
881
+ /*#__PURE__*/
882
+ _curry1(function type(val) {
883
+ return val === null ? 'Null' : val === undefined ? 'Undefined' : Object.prototype.toString.call(val).slice(8, -1);
884
+ });
885
+
886
+ /**
887
+ * private _uniqContentEquals function.
888
+ * That function is checking equality of 2 iterator contents with 2 assumptions
889
+ * - iterators lengths are the same
890
+ * - iterators values are unique
891
+ *
892
+ * false-positive result will be returned for comparison of, e.g.
893
+ * - [1,2,3] and [1,2,3,4]
894
+ * - [1,1,1] and [1,2,3]
895
+ * */
896
+
897
+ function _uniqContentEquals(aIterator, bIterator, stackA, stackB) {
898
+ var a = _arrayFromIterator(aIterator);
899
+
900
+ var b = _arrayFromIterator(bIterator);
901
+
902
+ function eq(_a, _b) {
903
+ return _equals(_a, _b, stackA.slice(), stackB.slice());
904
+ } // if *a* array contains any element that is not included in *b*
905
+
906
+
907
+ return !_includesWith(function (b, aItem) {
908
+ return !_includesWith(eq, aItem, b);
909
+ }, b, a);
910
+ }
911
+
912
+ function _equals(a, b, stackA, stackB) {
913
+ if (_objectIs$1(a, b)) {
914
+ return true;
915
+ }
916
+
917
+ var typeA = type(a);
918
+
919
+ if (typeA !== type(b)) {
920
+ return false;
921
+ }
922
+
923
+ if (typeof a['fantasy-land/equals'] === 'function' || typeof b['fantasy-land/equals'] === 'function') {
924
+ return typeof a['fantasy-land/equals'] === 'function' && a['fantasy-land/equals'](b) && typeof b['fantasy-land/equals'] === 'function' && b['fantasy-land/equals'](a);
925
+ }
926
+
927
+ if (typeof a.equals === 'function' || typeof b.equals === 'function') {
928
+ return typeof a.equals === 'function' && a.equals(b) && typeof b.equals === 'function' && b.equals(a);
929
+ }
930
+
931
+ switch (typeA) {
932
+ case 'Arguments':
933
+ case 'Array':
934
+ case 'Object':
935
+ if (typeof a.constructor === 'function' && _functionName(a.constructor) === 'Promise') {
936
+ return a === b;
937
+ }
938
+
939
+ break;
940
+
941
+ case 'Boolean':
942
+ case 'Number':
943
+ case 'String':
944
+ if (!(typeof a === typeof b && _objectIs$1(a.valueOf(), b.valueOf()))) {
945
+ return false;
946
+ }
947
+
948
+ break;
949
+
950
+ case 'Date':
951
+ if (!_objectIs$1(a.valueOf(), b.valueOf())) {
952
+ return false;
953
+ }
954
+
955
+ break;
956
+
957
+ case 'Error':
958
+ return a.name === b.name && a.message === b.message;
959
+
960
+ case 'RegExp':
961
+ if (!(a.source === b.source && a.global === b.global && a.ignoreCase === b.ignoreCase && a.multiline === b.multiline && a.sticky === b.sticky && a.unicode === b.unicode)) {
962
+ return false;
963
+ }
964
+
965
+ break;
966
+ }
967
+
968
+ var idx = stackA.length - 1;
969
+
970
+ while (idx >= 0) {
971
+ if (stackA[idx] === a) {
972
+ return stackB[idx] === b;
973
+ }
974
+
975
+ idx -= 1;
976
+ }
977
+
978
+ switch (typeA) {
979
+ case 'Map':
980
+ if (a.size !== b.size) {
981
+ return false;
982
+ }
983
+
984
+ return _uniqContentEquals(a.entries(), b.entries(), stackA.concat([a]), stackB.concat([b]));
985
+
986
+ case 'Set':
987
+ if (a.size !== b.size) {
988
+ return false;
989
+ }
990
+
991
+ return _uniqContentEquals(a.values(), b.values(), stackA.concat([a]), stackB.concat([b]));
992
+
993
+ case 'Arguments':
994
+ case 'Array':
995
+ case 'Object':
996
+ case 'Boolean':
997
+ case 'Number':
998
+ case 'String':
999
+ case 'Date':
1000
+ case 'Error':
1001
+ case 'RegExp':
1002
+ case 'Int8Array':
1003
+ case 'Uint8Array':
1004
+ case 'Uint8ClampedArray':
1005
+ case 'Int16Array':
1006
+ case 'Uint16Array':
1007
+ case 'Int32Array':
1008
+ case 'Uint32Array':
1009
+ case 'Float32Array':
1010
+ case 'Float64Array':
1011
+ case 'ArrayBuffer':
1012
+ break;
1013
+
1014
+ default:
1015
+ // Values of other types are only equal if identical.
1016
+ return false;
1017
+ }
1018
+
1019
+ var keysA = keys(a);
1020
+
1021
+ if (keysA.length !== keys(b).length) {
1022
+ return false;
1023
+ }
1024
+
1025
+ var extendedStackA = stackA.concat([a]);
1026
+ var extendedStackB = stackB.concat([b]);
1027
+ idx = keysA.length - 1;
1028
+
1029
+ while (idx >= 0) {
1030
+ var key = keysA[idx];
1031
+
1032
+ if (!(_has(key, b) && _equals(b[key], a[key], extendedStackA, extendedStackB))) {
1033
+ return false;
1034
+ }
1035
+
1036
+ idx -= 1;
1037
+ }
1038
+
1039
+ return true;
1040
+ }
1041
+
1042
+ /**
1043
+ * Returns `true` if its arguments are equivalent, `false` otherwise. Handles
1044
+ * cyclical data structures.
1045
+ *
1046
+ * Dispatches symmetrically to the `equals` methods of both arguments, if
1047
+ * present.
1048
+ *
1049
+ * @func
1050
+ * @memberOf R
1051
+ * @since v0.15.0
1052
+ * @category Relation
1053
+ * @sig a -> b -> Boolean
1054
+ * @param {*} a
1055
+ * @param {*} b
1056
+ * @return {Boolean}
1057
+ * @example
1058
+ *
1059
+ * R.equals(1, 1); //=> true
1060
+ * R.equals(1, '1'); //=> false
1061
+ * R.equals([1, 2, 3], [1, 2, 3]); //=> true
1062
+ *
1063
+ * const a = {}; a.v = a;
1064
+ * const b = {}; b.v = b;
1065
+ * R.equals(a, b); //=> true
1066
+ */
1067
+
1068
+ var equals =
1069
+ /*#__PURE__*/
1070
+ _curry2(function equals(a, b) {
1071
+ return _equals(a, b, [], []);
1072
+ });
1073
+
1074
+ function _indexOf(list, a, idx) {
1075
+ var inf, item; // Array.prototype.indexOf doesn't exist below IE9
1076
+
1077
+ if (typeof list.indexOf === 'function') {
1078
+ switch (typeof a) {
1079
+ case 'number':
1080
+ if (a === 0) {
1081
+ // manually crawl the list to distinguish between +0 and -0
1082
+ inf = 1 / a;
1083
+
1084
+ while (idx < list.length) {
1085
+ item = list[idx];
1086
+
1087
+ if (item === 0 && 1 / item === inf) {
1088
+ return idx;
1089
+ }
1090
+
1091
+ idx += 1;
1092
+ }
1093
+
1094
+ return -1;
1095
+ } else if (a !== a) {
1096
+ // NaN
1097
+ while (idx < list.length) {
1098
+ item = list[idx];
1099
+
1100
+ if (typeof item === 'number' && item !== item) {
1101
+ return idx;
1102
+ }
1103
+
1104
+ idx += 1;
1105
+ }
1106
+
1107
+ return -1;
1108
+ } // non-zero numbers can utilise Set
1109
+
1110
+
1111
+ return list.indexOf(a, idx);
1112
+ // all these types can utilise Set
1113
+
1114
+ case 'string':
1115
+ case 'boolean':
1116
+ case 'function':
1117
+ case 'undefined':
1118
+ return list.indexOf(a, idx);
1119
+
1120
+ case 'object':
1121
+ if (a === null) {
1122
+ // null can utilise Set
1123
+ return list.indexOf(a, idx);
1124
+ }
1125
+
1126
+ }
1127
+ } // anything else not covered above, defer to R.equals
1128
+
1129
+
1130
+ while (idx < list.length) {
1131
+ if (equals(list[idx], a)) {
1132
+ return idx;
1133
+ }
1134
+
1135
+ idx += 1;
1136
+ }
1137
+
1138
+ return -1;
1139
+ }
1140
+
1141
+ function _includes(a, list) {
1142
+ return _indexOf(list, a, 0) >= 0;
1143
+ }
1144
+
1145
+ function _map(fn, functor) {
1146
+ var idx = 0;
1147
+ var len = functor.length;
1148
+ var result = Array(len);
1149
+
1150
+ while (idx < len) {
1151
+ result[idx] = fn(functor[idx]);
1152
+ idx += 1;
1153
+ }
1154
+
1155
+ return result;
1156
+ }
1157
+
1158
+ function _quote(s) {
1159
+ var escaped = s.replace(/\\/g, '\\\\').replace(/[\b]/g, '\\b') // \b matches word boundary; [\b] matches backspace
1160
+ .replace(/\f/g, '\\f').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\t/g, '\\t').replace(/\v/g, '\\v').replace(/\0/g, '\\0');
1161
+ return '"' + escaped.replace(/"/g, '\\"') + '"';
1162
+ }
1163
+
1164
+ /**
1165
+ * Polyfill from <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString>.
1166
+ */
1167
+ var pad = function pad(n) {
1168
+ return (n < 10 ? '0' : '') + n;
1169
+ };
1170
+
1171
+ var _toISOString = typeof Date.prototype.toISOString === 'function' ? function _toISOString(d) {
1172
+ return d.toISOString();
1173
+ } : function _toISOString(d) {
1174
+ return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) + 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + '.' + (d.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) + 'Z';
1175
+ };
1176
+
1177
+ function _complement(f) {
1178
+ return function () {
1179
+ return !f.apply(this, arguments);
1180
+ };
1181
+ }
1182
+
1183
+ function _arrayReduce(reducer, acc, list) {
1184
+ var index = 0;
1185
+ var length = list.length;
1186
+
1187
+ while (index < length) {
1188
+ acc = reducer(acc, list[index]);
1189
+ index += 1;
1190
+ }
1191
+
1192
+ return acc;
1193
+ }
1194
+
1195
+ function _filter(fn, list) {
1196
+ var idx = 0;
1197
+ var len = list.length;
1198
+ var result = [];
1199
+
1200
+ while (idx < len) {
1201
+ if (fn(list[idx])) {
1202
+ result[result.length] = list[idx];
1203
+ }
1204
+
1205
+ idx += 1;
1206
+ }
1207
+
1208
+ return result;
1209
+ }
1210
+
1211
+ function _isObject(x) {
1212
+ return Object.prototype.toString.call(x) === '[object Object]';
1213
+ }
1214
+
1215
+ var XFilter =
1216
+ /*#__PURE__*/
1217
+ function () {
1218
+ function XFilter(f, xf) {
1219
+ this.xf = xf;
1220
+ this.f = f;
1221
+ }
1222
+
1223
+ XFilter.prototype['@@transducer/init'] = _xfBase.init;
1224
+ XFilter.prototype['@@transducer/result'] = _xfBase.result;
1225
+
1226
+ XFilter.prototype['@@transducer/step'] = function (result, input) {
1227
+ return this.f(input) ? this.xf['@@transducer/step'](result, input) : result;
1228
+ };
1229
+
1230
+ return XFilter;
1231
+ }();
1232
+
1233
+ function _xfilter(f) {
1234
+ return function (xf) {
1235
+ return new XFilter(f, xf);
1236
+ };
1237
+ }
1238
+
1239
+ /**
1240
+ * Takes a predicate and a `Filterable`, and returns a new filterable of the
1241
+ * same type containing the members of the given filterable which satisfy the
1242
+ * given predicate. Filterable objects include plain objects or any object
1243
+ * that has a filter method such as `Array`.
1244
+ *
1245
+ * Dispatches to the `filter` method of the second argument, if present.
1246
+ *
1247
+ * Acts as a transducer if a transformer is given in list position.
1248
+ *
1249
+ * @func
1250
+ * @memberOf R
1251
+ * @since v0.1.0
1252
+ * @category List
1253
+ * @category Object
1254
+ * @sig Filterable f => (a -> Boolean) -> f a -> f a
1255
+ * @param {Function} pred
1256
+ * @param {Array} filterable
1257
+ * @return {Array} Filterable
1258
+ * @see R.reject, R.transduce, R.addIndex
1259
+ * @example
1260
+ *
1261
+ * const isEven = n => n % 2 === 0;
1262
+ *
1263
+ * R.filter(isEven, [1, 2, 3, 4]); //=> [2, 4]
1264
+ *
1265
+ * R.filter(isEven, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}
1266
+ */
1267
+
1268
+ var filter =
1269
+ /*#__PURE__*/
1270
+ _curry2(
1271
+ /*#__PURE__*/
1272
+ _dispatchable(['fantasy-land/filter', 'filter'], _xfilter, function (pred, filterable) {
1273
+ return _isObject(filterable) ? _arrayReduce(function (acc, key) {
1274
+ if (pred(filterable[key])) {
1275
+ acc[key] = filterable[key];
1276
+ }
1277
+
1278
+ return acc;
1279
+ }, {}, keys(filterable)) : // else
1280
+ _filter(pred, filterable);
1281
+ }));
1282
+
1283
+ /**
1284
+ * The complement of [`filter`](#filter).
1285
+ *
1286
+ * Acts as a transducer if a transformer is given in list position. Filterable
1287
+ * objects include plain objects or any object that has a filter method such
1288
+ * as `Array`.
1289
+ *
1290
+ * @func
1291
+ * @memberOf R
1292
+ * @since v0.1.0
1293
+ * @category List
1294
+ * @sig Filterable f => (a -> Boolean) -> f a -> f a
1295
+ * @param {Function} pred
1296
+ * @param {Array} filterable
1297
+ * @return {Array}
1298
+ * @see R.filter, R.transduce, R.addIndex
1299
+ * @example
1300
+ *
1301
+ * const isOdd = (n) => n % 2 !== 0;
1302
+ *
1303
+ * R.reject(isOdd, [1, 2, 3, 4]); //=> [2, 4]
1304
+ *
1305
+ * R.reject(isOdd, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}
1306
+ */
1307
+
1308
+ var reject =
1309
+ /*#__PURE__*/
1310
+ _curry2(function reject(pred, filterable) {
1311
+ return filter(_complement(pred), filterable);
1312
+ });
1313
+
1314
+ function _toString(x, seen) {
1315
+ var recur = function recur(y) {
1316
+ var xs = seen.concat([x]);
1317
+ return _includes(y, xs) ? '<Circular>' : _toString(y, xs);
1318
+ }; // mapPairs :: (Object, [String]) -> [String]
1319
+
1320
+
1321
+ var mapPairs = function (obj, keys) {
1322
+ return _map(function (k) {
1323
+ return _quote(k) + ': ' + recur(obj[k]);
1324
+ }, keys.slice().sort());
1325
+ };
1326
+
1327
+ switch (Object.prototype.toString.call(x)) {
1328
+ case '[object Arguments]':
1329
+ return '(function() { return arguments; }(' + _map(recur, x).join(', ') + '))';
1330
+
1331
+ case '[object Array]':
1332
+ return '[' + _map(recur, x).concat(mapPairs(x, reject(function (k) {
1333
+ return /^\d+$/.test(k);
1334
+ }, keys(x)))).join(', ') + ']';
1335
+
1336
+ case '[object Boolean]':
1337
+ return typeof x === 'object' ? 'new Boolean(' + recur(x.valueOf()) + ')' : x.toString();
1338
+
1339
+ case '[object Date]':
1340
+ return 'new Date(' + (isNaN(x.valueOf()) ? recur(NaN) : _quote(_toISOString(x))) + ')';
1341
+
1342
+ case '[object Map]':
1343
+ return 'new Map(' + recur(Array.from(x)) + ')';
1344
+
1345
+ case '[object Null]':
1346
+ return 'null';
1347
+
1348
+ case '[object Number]':
1349
+ return typeof x === 'object' ? 'new Number(' + recur(x.valueOf()) + ')' : 1 / x === -Infinity ? '-0' : x.toString(10);
1350
+
1351
+ case '[object Set]':
1352
+ return 'new Set(' + recur(Array.from(x).sort()) + ')';
1353
+
1354
+ case '[object String]':
1355
+ return typeof x === 'object' ? 'new String(' + recur(x.valueOf()) + ')' : _quote(x);
1356
+
1357
+ case '[object Undefined]':
1358
+ return 'undefined';
1359
+
1360
+ default:
1361
+ if (typeof x.toString === 'function') {
1362
+ var repr = x.toString();
1363
+
1364
+ if (repr !== '[object Object]') {
1365
+ return repr;
1366
+ }
1367
+ }
1368
+
1369
+ return '{' + mapPairs(x, keys(x)).join(', ') + '}';
1370
+ }
1371
+ }
1372
+
1373
+ /**
1374
+ * Returns the string representation of the given value. `eval`'ing the output
1375
+ * should result in a value equivalent to the input value. Many of the built-in
1376
+ * `toString` methods do not satisfy this requirement.
1377
+ *
1378
+ * If the given value is an `[object Object]` with a `toString` method other
1379
+ * than `Object.prototype.toString`, this method is invoked with no arguments
1380
+ * to produce the return value. This means user-defined constructor functions
1381
+ * can provide a suitable `toString` method. For example:
1382
+ *
1383
+ * function Point(x, y) {
1384
+ * this.x = x;
1385
+ * this.y = y;
1386
+ * }
1387
+ *
1388
+ * Point.prototype.toString = function() {
1389
+ * return 'new Point(' + this.x + ', ' + this.y + ')';
1390
+ * };
1391
+ *
1392
+ * R.toString(new Point(1, 2)); //=> 'new Point(1, 2)'
1393
+ *
1394
+ * @func
1395
+ * @memberOf R
1396
+ * @since v0.14.0
1397
+ * @category String
1398
+ * @sig * -> String
1399
+ * @param {*} val
1400
+ * @return {String}
1401
+ * @example
1402
+ *
1403
+ * R.toString(42); //=> '42'
1404
+ * R.toString('abc'); //=> '"abc"'
1405
+ * R.toString([1, 2, 3]); //=> '[1, 2, 3]'
1406
+ * R.toString({foo: 1, bar: 2, baz: 3}); //=> '{"bar": 2, "baz": 3, "foo": 1}'
1407
+ * R.toString(new Date('2001-02-03T04:05:06Z')); //=> 'new Date("2001-02-03T04:05:06.000Z")'
1408
+ */
1409
+
1410
+ var toString =
1411
+ /*#__PURE__*/
1412
+ _curry1(function toString(val) {
1413
+ return _toString(val, []);
1414
+ });
1415
+
1416
+ var XMap =
1417
+ /*#__PURE__*/
1418
+ function () {
1419
+ function XMap(f, xf) {
1420
+ this.xf = xf;
1421
+ this.f = f;
1422
+ }
1423
+
1424
+ XMap.prototype['@@transducer/init'] = _xfBase.init;
1425
+ XMap.prototype['@@transducer/result'] = _xfBase.result;
1426
+
1427
+ XMap.prototype['@@transducer/step'] = function (result, input) {
1428
+ return this.xf['@@transducer/step'](result, this.f(input));
1429
+ };
1430
+
1431
+ return XMap;
1432
+ }();
1433
+
1434
+ var _xmap = function _xmap(f) {
1435
+ return function (xf) {
1436
+ return new XMap(f, xf);
1437
+ };
1438
+ };
1439
+
1440
+ /**
1441
+ * Takes a function and
1442
+ * a [functor](https://github.com/fantasyland/fantasy-land#functor),
1443
+ * applies the function to each of the functor's values, and returns
1444
+ * a functor of the same shape.
1445
+ *
1446
+ * Ramda provides suitable `map` implementations for `Array` and `Object`,
1447
+ * so this function may be applied to `[1, 2, 3]` or `{x: 1, y: 2, z: 3}`.
1448
+ *
1449
+ * Dispatches to the `map` method of the second argument, if present.
1450
+ *
1451
+ * Acts as a transducer if a transformer is given in list position.
1452
+ *
1453
+ * Also treats functions as functors and will compose them together.
1454
+ *
1455
+ * @func
1456
+ * @memberOf R
1457
+ * @since v0.1.0
1458
+ * @category List
1459
+ * @sig Functor f => (a -> b) -> f a -> f b
1460
+ * @param {Function} fn The function to be called on every element of the input `list`.
1461
+ * @param {Array} list The list to be iterated over.
1462
+ * @return {Array} The new list.
1463
+ * @see R.transduce, R.addIndex, R.pluck, R.project
1464
+ * @example
1465
+ *
1466
+ * const double = x => x * 2;
1467
+ *
1468
+ * R.map(double, [1, 2, 3]); //=> [2, 4, 6]
1469
+ *
1470
+ * R.map(double, {x: 1, y: 2, z: 3}); //=> {x: 2, y: 4, z: 6}
1471
+ * @symb R.map(f, [a, b]) = [f(a), f(b)]
1472
+ * @symb R.map(f, { x: a, y: b }) = { x: f(a), y: f(b) }
1473
+ * @symb R.map(f, functor_o) = functor_o.map(f)
1474
+ */
1475
+
1476
+ var map =
1477
+ /*#__PURE__*/
1478
+ _curry2(
1479
+ /*#__PURE__*/
1480
+ _dispatchable(['fantasy-land/map', 'map'], _xmap, function map(fn, functor) {
1481
+ switch (Object.prototype.toString.call(functor)) {
1482
+ case '[object Function]':
1483
+ return curryN(functor.length, function () {
1484
+ return fn.call(this, functor.apply(this, arguments));
1485
+ });
1486
+
1487
+ case '[object Object]':
1488
+ return _arrayReduce(function (acc, key) {
1489
+ acc[key] = fn(functor[key]);
1490
+ return acc;
1491
+ }, {}, keys(functor));
1492
+
1493
+ default:
1494
+ return _map(fn, functor);
1495
+ }
1496
+ }));
1497
+
1498
+ /**
1499
+ * Determine if the passed argument is an integer.
1500
+ *
1501
+ * @private
1502
+ * @param {*} n
1503
+ * @category Type
1504
+ * @return {Boolean}
1505
+ */
1506
+ var _isInteger = Number.isInteger || function _isInteger(n) {
1507
+ return n << 0 === n;
1508
+ };
1509
+
1510
+ function _isString(x) {
1511
+ return Object.prototype.toString.call(x) === '[object String]';
1512
+ }
1513
+
1514
+ /**
1515
+ * Returns the nth element of the given list or string. If n is negative the
1516
+ * element at index length + n is returned.
1517
+ *
1518
+ * @func
1519
+ * @memberOf R
1520
+ * @since v0.1.0
1521
+ * @category List
1522
+ * @sig Number -> [a] -> a | Undefined
1523
+ * @sig Number -> String -> String
1524
+ * @param {Number} offset
1525
+ * @param {*} list
1526
+ * @return {*}
1527
+ * @example
1528
+ *
1529
+ * const list = ['foo', 'bar', 'baz', 'quux'];
1530
+ * R.nth(1, list); //=> 'bar'
1531
+ * R.nth(-1, list); //=> 'quux'
1532
+ * R.nth(-99, list); //=> undefined
1533
+ *
1534
+ * R.nth(2, 'abc'); //=> 'c'
1535
+ * R.nth(3, 'abc'); //=> ''
1536
+ * @symb R.nth(-1, [a, b, c]) = c
1537
+ * @symb R.nth(0, [a, b, c]) = a
1538
+ * @symb R.nth(1, [a, b, c]) = b
1539
+ */
1540
+
1541
+ var nth =
1542
+ /*#__PURE__*/
1543
+ _curry2(function nth(offset, list) {
1544
+ var idx = offset < 0 ? list.length + offset : offset;
1545
+ return _isString(list) ? list.charAt(idx) : list[idx];
1546
+ });
1547
+
1548
+ /**
1549
+ * Returns a function that when supplied an object returns the indicated
1550
+ * property of that object, if it exists.
1551
+ *
1552
+ * @func
1553
+ * @memberOf R
1554
+ * @since v0.1.0
1555
+ * @category Object
1556
+ * @typedefn Idx = String | Int | Symbol
1557
+ * @sig Idx -> {s: a} -> a | Undefined
1558
+ * @param {String|Number} p The property name or array index
1559
+ * @param {Object} obj The object to query
1560
+ * @return {*} The value at `obj.p`.
1561
+ * @see R.path, R.props, R.pluck, R.project, R.nth
1562
+ * @example
1563
+ *
1564
+ * R.prop('x', {x: 100}); //=> 100
1565
+ * R.prop('x', {}); //=> undefined
1566
+ * R.prop(0, [100]); //=> 100
1567
+ * R.compose(R.inc, R.prop('x'))({ x: 3 }) //=> 4
1568
+ */
1569
+
1570
+ var prop =
1571
+ /*#__PURE__*/
1572
+ _curry2(function prop(p, obj) {
1573
+ if (obj == null) {
1574
+ return;
1575
+ }
1576
+
1577
+ return _isInteger(p) ? nth(p, obj) : obj[p];
1578
+ });
1579
+
1580
+ /**
1581
+ * Tests whether or not an object is similar to an array.
1582
+ *
1583
+ * @private
1584
+ * @category Type
1585
+ * @category List
1586
+ * @sig * -> Boolean
1587
+ * @param {*} x The object to test.
1588
+ * @return {Boolean} `true` if `x` has a numeric length property and extreme indices defined; `false` otherwise.
1589
+ * @example
1590
+ *
1591
+ * _isArrayLike([]); //=> true
1592
+ * _isArrayLike(true); //=> false
1593
+ * _isArrayLike({}); //=> false
1594
+ * _isArrayLike({length: 10}); //=> false
1595
+ * _isArrayLike({0: 'zero', 9: 'nine', length: 10}); //=> true
1596
+ * _isArrayLike({nodeType: 1, length: 1}) // => false
1597
+ */
1598
+
1599
+ var _isArrayLike =
1600
+ /*#__PURE__*/
1601
+ _curry1(function isArrayLike(x) {
1602
+ if (_isArray(x)) {
1603
+ return true;
1604
+ }
1605
+
1606
+ if (!x) {
1607
+ return false;
1608
+ }
1609
+
1610
+ if (typeof x !== 'object') {
1611
+ return false;
1612
+ }
1613
+
1614
+ if (_isString(x)) {
1615
+ return false;
1616
+ }
1617
+
1618
+ if (x.length === 0) {
1619
+ return true;
1620
+ }
1621
+
1622
+ if (x.length > 0) {
1623
+ return x.hasOwnProperty(0) && x.hasOwnProperty(x.length - 1);
1624
+ }
1625
+
1626
+ return false;
1627
+ });
1628
+
1629
+ var symIterator = typeof Symbol !== 'undefined' ? Symbol.iterator : '@@iterator';
1630
+ function _createReduce(arrayReduce, methodReduce, iterableReduce) {
1631
+ return function _reduce(xf, acc, list) {
1632
+ if (_isArrayLike(list)) {
1633
+ return arrayReduce(xf, acc, list);
1634
+ }
1635
+
1636
+ if (list == null) {
1637
+ return acc;
1638
+ }
1639
+
1640
+ if (typeof list['fantasy-land/reduce'] === 'function') {
1641
+ return methodReduce(xf, acc, list, 'fantasy-land/reduce');
1642
+ }
1643
+
1644
+ if (list[symIterator] != null) {
1645
+ return iterableReduce(xf, acc, list[symIterator]());
1646
+ }
1647
+
1648
+ if (typeof list.next === 'function') {
1649
+ return iterableReduce(xf, acc, list);
1650
+ }
1651
+
1652
+ if (typeof list.reduce === 'function') {
1653
+ return methodReduce(xf, acc, list, 'reduce');
1654
+ }
1655
+
1656
+ throw new TypeError('reduce: list must be array or iterable');
1657
+ };
1658
+ }
1659
+
1660
+ function _xArrayReduce(xf, acc, list) {
1661
+ var idx = 0;
1662
+ var len = list.length;
1663
+
1664
+ while (idx < len) {
1665
+ acc = xf['@@transducer/step'](acc, list[idx]);
1666
+
1667
+ if (acc && acc['@@transducer/reduced']) {
1668
+ acc = acc['@@transducer/value'];
1669
+ break;
1670
+ }
1671
+
1672
+ idx += 1;
1673
+ }
1674
+
1675
+ return xf['@@transducer/result'](acc);
1676
+ }
1677
+
1678
+ /**
1679
+ * Creates a function that is bound to a context.
1680
+ * Note: `R.bind` does not provide the additional argument-binding capabilities of
1681
+ * [Function.prototype.bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).
1682
+ *
1683
+ * @func
1684
+ * @memberOf R
1685
+ * @since v0.6.0
1686
+ * @category Function
1687
+ * @category Object
1688
+ * @sig (* -> *) -> {*} -> (* -> *)
1689
+ * @param {Function} fn The function to bind to context
1690
+ * @param {Object} thisObj The context to bind `fn` to
1691
+ * @return {Function} A function that will execute in the context of `thisObj`.
1692
+ * @see R.partial
1693
+ * @example
1694
+ *
1695
+ * const log = R.bind(console.log, console);
1696
+ * R.pipe(R.assoc('a', 2), R.tap(log), R.assoc('a', 3))({a: 1}); //=> {a: 3}
1697
+ * // logs {a: 2}
1698
+ * @symb R.bind(f, o)(a, b) = f.call(o, a, b)
1699
+ */
1700
+
1701
+ var bind =
1702
+ /*#__PURE__*/
1703
+ _curry2(function bind(fn, thisObj) {
1704
+ return _arity(fn.length, function () {
1705
+ return fn.apply(thisObj, arguments);
1706
+ });
1707
+ });
1708
+
1709
+ function _xIterableReduce(xf, acc, iter) {
1710
+ var step = iter.next();
1711
+
1712
+ while (!step.done) {
1713
+ acc = xf['@@transducer/step'](acc, step.value);
1714
+
1715
+ if (acc && acc['@@transducer/reduced']) {
1716
+ acc = acc['@@transducer/value'];
1717
+ break;
1718
+ }
1719
+
1720
+ step = iter.next();
1721
+ }
1722
+
1723
+ return xf['@@transducer/result'](acc);
1724
+ }
1725
+
1726
+ function _xMethodReduce(xf, acc, obj, methodName) {
1727
+ return xf['@@transducer/result'](obj[methodName](bind(xf['@@transducer/step'], xf), acc));
1728
+ }
1729
+
1730
+ var _xReduce =
1731
+ /*#__PURE__*/
1732
+ _createReduce(_xArrayReduce, _xMethodReduce, _xIterableReduce);
1733
+
1734
+ var XWrap =
1735
+ /*#__PURE__*/
1736
+ function () {
1737
+ function XWrap(fn) {
1738
+ this.f = fn;
1739
+ }
1740
+
1741
+ XWrap.prototype['@@transducer/init'] = function () {
1742
+ throw new Error('init not implemented on XWrap');
1743
+ };
1744
+
1745
+ XWrap.prototype['@@transducer/result'] = function (acc) {
1746
+ return acc;
1747
+ };
1748
+
1749
+ XWrap.prototype['@@transducer/step'] = function (acc, x) {
1750
+ return this.f(acc, x);
1751
+ };
1752
+
1753
+ return XWrap;
1754
+ }();
1755
+
1756
+ function _xwrap(fn) {
1757
+ return new XWrap(fn);
1758
+ }
1759
+
1760
+ /**
1761
+ * Returns a single item by iterating through the list, successively calling
1762
+ * the iterator function and passing it an accumulator value and the current
1763
+ * value from the array, and then passing the result to the next call.
1764
+ *
1765
+ * The iterator function receives two values: *(acc, value)*. It may use
1766
+ * [`R.reduced`](#reduced) to shortcut the iteration.
1767
+ *
1768
+ * The arguments' order of [`reduceRight`](#reduceRight)'s iterator function
1769
+ * is *(value, acc)*.
1770
+ *
1771
+ * Note: `R.reduce` does not skip deleted or unassigned indices (sparse
1772
+ * arrays), unlike the native `Array.prototype.reduce` method. For more details
1773
+ * on this behavior, see:
1774
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Description
1775
+ *
1776
+ * Be cautious of mutating and returning the accumulator. If you reuse it across
1777
+ * invocations, it will continue to accumulate onto the same value. The general
1778
+ * recommendation is to always return a new value. If you can't do so for
1779
+ * performance reasons, then be sure to reinitialize the accumulator on each
1780
+ * invocation.
1781
+ *
1782
+ * Dispatches to the `reduce` method of the third argument, if present. When
1783
+ * doing so, it is up to the user to handle the [`R.reduced`](#reduced)
1784
+ * shortcuting, as this is not implemented by `reduce`.
1785
+ *
1786
+ * @func
1787
+ * @memberOf R
1788
+ * @since v0.1.0
1789
+ * @category List
1790
+ * @sig ((a, b) -> a) -> a -> [b] -> a
1791
+ * @param {Function} fn The iterator function. Receives two values, the accumulator and the
1792
+ * current element from the array.
1793
+ * @param {*} acc The accumulator value.
1794
+ * @param {Array} list The list to iterate over.
1795
+ * @return {*} The final, accumulated value.
1796
+ * @see R.reduced, R.addIndex, R.reduceRight
1797
+ * @example
1798
+ *
1799
+ * R.reduce(R.subtract, 0, [1, 2, 3, 4]) // => ((((0 - 1) - 2) - 3) - 4) = -10
1800
+ * // - -10
1801
+ * // / \ / \
1802
+ * // - 4 -6 4
1803
+ * // / \ / \
1804
+ * // - 3 ==> -3 3
1805
+ * // / \ / \
1806
+ * // - 2 -1 2
1807
+ * // / \ / \
1808
+ * // 0 1 0 1
1809
+ *
1810
+ * @symb R.reduce(f, a, [b, c, d]) = f(f(f(a, b), c), d)
1811
+ */
1812
+
1813
+ var reduce =
1814
+ /*#__PURE__*/
1815
+ _curry3(function (xf, acc, list) {
1816
+ return _xReduce(typeof xf === 'function' ? _xwrap(xf) : xf, acc, list);
1817
+ });
1818
+
1819
+ /**
1820
+ * Makes a shallow clone of an object, setting or overriding the specified
1821
+ * property with the given value. Note that this copies and flattens prototype
1822
+ * properties onto the new object as well. All non-primitive properties are
1823
+ * copied by reference.
1824
+ *
1825
+ * @private
1826
+ * @param {String|Number} prop The property name to set
1827
+ * @param {*} val The new value
1828
+ * @param {Object|Array} obj The object to clone
1829
+ * @return {Object|Array} A new object equivalent to the original except for the changed property.
1830
+ */
1831
+
1832
+ function _assoc(prop, val, obj) {
1833
+ if (_isInteger(prop) && _isArray(obj)) {
1834
+ var arr = [].concat(obj);
1835
+ arr[prop] = val;
1836
+ return arr;
1837
+ }
1838
+
1839
+ var result = {};
1840
+
1841
+ for (var p in obj) {
1842
+ result[p] = obj[p];
1843
+ }
1844
+
1845
+ result[prop] = val;
1846
+ return result;
1847
+ }
1848
+
1849
+ /**
1850
+ * Checks if the input value is `null` or `undefined`.
1851
+ *
1852
+ * @func
1853
+ * @memberOf R
1854
+ * @since v0.9.0
1855
+ * @category Type
1856
+ * @sig * -> Boolean
1857
+ * @param {*} x The value to test.
1858
+ * @return {Boolean} `true` if `x` is `undefined` or `null`, otherwise `false`.
1859
+ * @example
1860
+ *
1861
+ * R.isNil(null); //=> true
1862
+ * R.isNil(undefined); //=> true
1863
+ * R.isNil(0); //=> false
1864
+ * R.isNil([]); //=> false
1865
+ */
1866
+
1867
+ var isNil =
1868
+ /*#__PURE__*/
1869
+ _curry1(function isNil(x) {
1870
+ return x == null;
1871
+ });
1872
+
1873
+ /**
1874
+ * Makes a shallow clone of an object, setting or overriding the nodes required
1875
+ * to create the given path, and placing the specific value at the tail end of
1876
+ * that path. Note that this copies and flattens prototype properties onto the
1877
+ * new object as well. All non-primitive properties are copied by reference.
1878
+ *
1879
+ * @func
1880
+ * @memberOf R
1881
+ * @since v0.8.0
1882
+ * @category Object
1883
+ * @typedefn Idx = String | Int | Symbol
1884
+ * @sig [Idx] -> a -> {a} -> {a}
1885
+ * @param {Array} path the path to set
1886
+ * @param {*} val The new value
1887
+ * @param {Object} obj The object to clone
1888
+ * @return {Object} A new object equivalent to the original except along the specified path.
1889
+ * @see R.dissocPath
1890
+ * @example
1891
+ *
1892
+ * R.assocPath(['a', 'b', 'c'], 42, {a: {b: {c: 0}}}); //=> {a: {b: {c: 42}}}
1893
+ *
1894
+ * // Any missing or non-object keys in path will be overridden
1895
+ * R.assocPath(['a', 'b', 'c'], 42, {a: 5}); //=> {a: {b: {c: 42}}}
1896
+ */
1897
+
1898
+ var assocPath =
1899
+ /*#__PURE__*/
1900
+ _curry3(function assocPath(path, val, obj) {
1901
+ if (path.length === 0) {
1902
+ return val;
1903
+ }
1904
+
1905
+ var idx = path[0];
1906
+
1907
+ if (path.length > 1) {
1908
+ var nextObj = !isNil(obj) && _has(idx, obj) && typeof obj[idx] === 'object' ? obj[idx] : _isInteger(path[1]) ? [] : {};
1909
+ val = assocPath(Array.prototype.slice.call(path, 1), val, nextObj);
1910
+ }
1911
+
1912
+ return _assoc(idx, val, obj);
1913
+ });
1914
+
1915
+ function _isFunction(x) {
1916
+ var type = Object.prototype.toString.call(x);
1917
+ return type === '[object Function]' || type === '[object AsyncFunction]' || type === '[object GeneratorFunction]' || type === '[object AsyncGeneratorFunction]';
1918
+ }
1919
+
1920
+ function _pipe(f, g) {
1921
+ return function () {
1922
+ return g.call(this, f.apply(this, arguments));
1923
+ };
1924
+ }
1925
+
1926
+ /**
1927
+ * This checks whether a function has a [methodname] function. If it isn't an
1928
+ * array it will execute that function otherwise it will default to the ramda
1929
+ * implementation.
1930
+ *
1931
+ * @private
1932
+ * @param {Function} fn ramda implementation
1933
+ * @param {String} methodname property to check for a custom implementation
1934
+ * @return {Object} Whatever the return value of the method is.
1935
+ */
1936
+
1937
+ function _checkForMethod(methodname, fn) {
1938
+ return function () {
1939
+ var length = arguments.length;
1940
+
1941
+ if (length === 0) {
1942
+ return fn();
1943
+ }
1944
+
1945
+ var obj = arguments[length - 1];
1946
+ return _isArray(obj) || typeof obj[methodname] !== 'function' ? fn.apply(this, arguments) : obj[methodname].apply(obj, Array.prototype.slice.call(arguments, 0, length - 1));
1947
+ };
1948
+ }
1949
+
1950
+ /**
1951
+ * Returns the elements of the given list or string (or object with a `slice`
1952
+ * method) from `fromIndex` (inclusive) to `toIndex` (exclusive).
1953
+ *
1954
+ * Dispatches to the `slice` method of the third argument, if present.
1955
+ *
1956
+ * @func
1957
+ * @memberOf R
1958
+ * @since v0.1.4
1959
+ * @category List
1960
+ * @sig Number -> Number -> [a] -> [a]
1961
+ * @sig Number -> Number -> String -> String
1962
+ * @param {Number} fromIndex The start index (inclusive).
1963
+ * @param {Number} toIndex The end index (exclusive).
1964
+ * @param {*} list
1965
+ * @return {*}
1966
+ * @example
1967
+ *
1968
+ * R.slice(1, 3, ['a', 'b', 'c', 'd']); //=> ['b', 'c']
1969
+ * R.slice(1, Infinity, ['a', 'b', 'c', 'd']); //=> ['b', 'c', 'd']
1970
+ * R.slice(0, -1, ['a', 'b', 'c', 'd']); //=> ['a', 'b', 'c']
1971
+ * R.slice(-3, -1, ['a', 'b', 'c', 'd']); //=> ['b', 'c']
1972
+ * R.slice(0, 3, 'ramda'); //=> 'ram'
1973
+ */
1974
+
1975
+ var slice =
1976
+ /*#__PURE__*/
1977
+ _curry3(
1978
+ /*#__PURE__*/
1979
+ _checkForMethod('slice', function slice(fromIndex, toIndex, list) {
1980
+ return Array.prototype.slice.call(list, fromIndex, toIndex);
1981
+ }));
1982
+
1983
+ /**
1984
+ * Returns all but the first element of the given list or string (or object
1985
+ * with a `tail` method).
1986
+ *
1987
+ * Dispatches to the `slice` method of the first argument, if present.
1988
+ *
1989
+ * @func
1990
+ * @memberOf R
1991
+ * @since v0.1.0
1992
+ * @category List
1993
+ * @sig [a] -> [a]
1994
+ * @sig String -> String
1995
+ * @param {*} list
1996
+ * @return {*}
1997
+ * @see R.head, R.init, R.last
1998
+ * @example
1999
+ *
2000
+ * R.tail([1, 2, 3]); //=> [2, 3]
2001
+ * R.tail([1, 2]); //=> [2]
2002
+ * R.tail([1]); //=> []
2003
+ * R.tail([]); //=> []
2004
+ *
2005
+ * R.tail('abc'); //=> 'bc'
2006
+ * R.tail('ab'); //=> 'b'
2007
+ * R.tail('a'); //=> ''
2008
+ * R.tail(''); //=> ''
2009
+ */
2010
+
2011
+ var tail =
2012
+ /*#__PURE__*/
2013
+ _curry1(
2014
+ /*#__PURE__*/
2015
+ _checkForMethod('tail',
2016
+ /*#__PURE__*/
2017
+ slice(1, Infinity)));
2018
+
2019
+ /**
2020
+ * Performs left-to-right function composition. The first argument may have
2021
+ * any arity; the remaining arguments must be unary.
2022
+ *
2023
+ * In some libraries this function is named `sequence`.
2024
+ *
2025
+ * **Note:** The result of pipe is not automatically curried.
2026
+ *
2027
+ * @func
2028
+ * @memberOf R
2029
+ * @since v0.1.0
2030
+ * @category Function
2031
+ * @sig (((a, b, ..., n) -> o), (o -> p), ..., (x -> y), (y -> z)) -> ((a, b, ..., n) -> z)
2032
+ * @param {...Function} functions
2033
+ * @return {Function}
2034
+ * @see R.compose
2035
+ * @example
2036
+ *
2037
+ * const f = R.pipe(Math.pow, R.negate, R.inc);
2038
+ *
2039
+ * f(3, 4); // -(3^4) + 1
2040
+ * @symb R.pipe(f, g, h)(a, b) = h(g(f(a, b)))
2041
+ * @symb R.pipe(f, g, h)(a)(b) = h(g(f(a)))(b)
2042
+ */
2043
+
2044
+ function pipe() {
2045
+ if (arguments.length === 0) {
2046
+ throw new Error('pipe requires at least one argument');
2047
+ }
2048
+
2049
+ return _arity(arguments[0].length, reduce(_pipe, arguments[0], tail(arguments)));
2050
+ }
2051
+
2052
+ /**
2053
+ * Returns a new list or string with the elements or characters in reverse
2054
+ * order.
2055
+ *
2056
+ * @func
2057
+ * @memberOf R
2058
+ * @since v0.1.0
2059
+ * @category List
2060
+ * @sig [a] -> [a]
2061
+ * @sig String -> String
2062
+ * @param {Array|String} list
2063
+ * @return {Array|String}
2064
+ * @example
2065
+ *
2066
+ * R.reverse([1, 2, 3]); //=> [3, 2, 1]
2067
+ * R.reverse([1, 2]); //=> [2, 1]
2068
+ * R.reverse([1]); //=> [1]
2069
+ * R.reverse([]); //=> []
2070
+ *
2071
+ * R.reverse('abc'); //=> 'cba'
2072
+ * R.reverse('ab'); //=> 'ba'
2073
+ * R.reverse('a'); //=> 'a'
2074
+ * R.reverse(''); //=> ''
2075
+ */
2076
+
2077
+ var reverse =
2078
+ /*#__PURE__*/
2079
+ _curry1(function reverse(list) {
2080
+ return _isString(list) ? list.split('').reverse().join('') : Array.prototype.slice.call(list, 0).reverse();
2081
+ });
2082
+
2083
+ /**
2084
+ * Performs right-to-left function composition. The last argument may have
2085
+ * any arity; the remaining arguments must be unary.
2086
+ *
2087
+ * **Note:** The result of compose is not automatically curried.
2088
+ *
2089
+ * @func
2090
+ * @memberOf R
2091
+ * @since v0.1.0
2092
+ * @category Function
2093
+ * @sig ((y -> z), (x -> y), ..., (o -> p), ((a, b, ..., n) -> o)) -> ((a, b, ..., n) -> z)
2094
+ * @param {...Function} ...functions The functions to compose
2095
+ * @return {Function}
2096
+ * @see R.pipe
2097
+ * @example
2098
+ *
2099
+ * const classyGreeting = (firstName, lastName) => "The name's " + lastName + ", " + firstName + " " + lastName
2100
+ * const yellGreeting = R.compose(R.toUpper, classyGreeting);
2101
+ * yellGreeting('James', 'Bond'); //=> "THE NAME'S BOND, JAMES BOND"
2102
+ *
2103
+ * R.compose(Math.abs, R.add(1), R.multiply(2))(-4) //=> 7
2104
+ *
2105
+ * @symb R.compose(f, g, h)(a, b) = f(g(h(a, b)))
2106
+ * @symb R.compose(f, g, h)(a)(b) = f(g(h(a)))(b)
2107
+ */
2108
+
2109
+ function compose() {
2110
+ if (arguments.length === 0) {
2111
+ throw new Error('compose requires at least one argument');
2112
+ }
2113
+
2114
+ return pipe.apply(this, reverse(arguments));
2115
+ }
2116
+
2117
+ /**
2118
+ * Returns a curried equivalent of the provided function. The curried function
2119
+ * has two unusual capabilities. First, its arguments needn't be provided one
2120
+ * at a time. If `f` is a ternary function and `g` is `R.curry(f)`, the
2121
+ * following are equivalent:
2122
+ *
2123
+ * - `g(1)(2)(3)`
2124
+ * - `g(1)(2, 3)`
2125
+ * - `g(1, 2)(3)`
2126
+ * - `g(1, 2, 3)`
2127
+ *
2128
+ * Secondly, the special placeholder value [`R.__`](#__) may be used to specify
2129
+ * "gaps", allowing partial application of any combination of arguments,
2130
+ * regardless of their positions. If `g` is as above and `_` is [`R.__`](#__),
2131
+ * the following are equivalent:
2132
+ *
2133
+ * - `g(1, 2, 3)`
2134
+ * - `g(_, 2, 3)(1)`
2135
+ * - `g(_, _, 3)(1)(2)`
2136
+ * - `g(_, _, 3)(1, 2)`
2137
+ * - `g(_, 2)(1)(3)`
2138
+ * - `g(_, 2)(1, 3)`
2139
+ * - `g(_, 2)(_, 3)(1)`
2140
+ *
2141
+ * Please note that default parameters don't count towards a [function arity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length)
2142
+ * and therefore `curry` won't work well with those.
2143
+ *
2144
+ * @func
2145
+ * @memberOf R
2146
+ * @since v0.1.0
2147
+ * @category Function
2148
+ * @sig (* -> a) -> (* -> a)
2149
+ * @param {Function} fn The function to curry.
2150
+ * @return {Function} A new, curried function.
2151
+ * @see R.curryN, R.partial
2152
+ * @example
2153
+ *
2154
+ * const addFourNumbers = (a, b, c, d) => a + b + c + d;
2155
+ * const curriedAddFourNumbers = R.curry(addFourNumbers);
2156
+ * const f = curriedAddFourNumbers(1, 2);
2157
+ * const g = f(3);
2158
+ * g(4); //=> 10
2159
+ *
2160
+ * // R.curry not working well with default parameters
2161
+ * const h = R.curry((a, b, c = 2) => a + b + c);
2162
+ * h(1)(2)(7); //=> Error! (`3` is not a function!)
2163
+ */
2164
+
2165
+ var curry =
2166
+ /*#__PURE__*/
2167
+ _curry1(function curry(fn) {
2168
+ return curryN(fn.length, fn);
2169
+ });
2170
+
2171
+ /**
2172
+ * Tests whether or not an object is a typed array.
2173
+ *
2174
+ * @private
2175
+ * @param {*} val The object to test.
2176
+ * @return {Boolean} `true` if `val` is a typed array, `false` otherwise.
2177
+ * @example
2178
+ *
2179
+ * _isTypedArray(new Uint8Array([])); //=> true
2180
+ * _isTypedArray(new Float32Array([])); //=> true
2181
+ * _isTypedArray([]); //=> false
2182
+ * _isTypedArray(null); //=> false
2183
+ * _isTypedArray({}); //=> false
2184
+ */
2185
+ function _isTypedArray(val) {
2186
+ var type = Object.prototype.toString.call(val);
2187
+ return type === '[object Uint8ClampedArray]' || type === '[object Int8Array]' || type === '[object Uint8Array]' || type === '[object Int16Array]' || type === '[object Uint16Array]' || type === '[object Int32Array]' || type === '[object Uint32Array]' || type === '[object Float32Array]' || type === '[object Float64Array]' || type === '[object BigInt64Array]' || type === '[object BigUint64Array]';
2188
+ }
2189
+
2190
+ /**
2191
+ * Returns the empty value of its argument's type. Ramda defines the empty
2192
+ * value of Array (`[]`), Object (`{}`), String (`''`),
2193
+ * TypedArray (`Uint8Array []`, `Float32Array []`, etc), and Arguments. Other
2194
+ * types are supported if they define `<Type>.empty`,
2195
+ * `<Type>.prototype.empty` or implement the
2196
+ * [FantasyLand Monoid spec](https://github.com/fantasyland/fantasy-land#monoid).
2197
+ *
2198
+ * Dispatches to the `empty` method of the first argument, if present.
2199
+ *
2200
+ * @func
2201
+ * @memberOf R
2202
+ * @since v0.3.0
2203
+ * @category Function
2204
+ * @sig a -> a
2205
+ * @param {*} x
2206
+ * @return {*}
2207
+ * @example
2208
+ *
2209
+ * R.empty(Just(42)); //=> Nothing()
2210
+ * R.empty([1, 2, 3]); //=> []
2211
+ * R.empty('unicorns'); //=> ''
2212
+ * R.empty({x: 1, y: 2}); //=> {}
2213
+ * R.empty(Uint8Array.from('123')); //=> Uint8Array []
2214
+ */
2215
+
2216
+ var empty =
2217
+ /*#__PURE__*/
2218
+ _curry1(function empty(x) {
2219
+ return x != null && typeof x['fantasy-land/empty'] === 'function' ? x['fantasy-land/empty']() : x != null && x.constructor != null && typeof x.constructor['fantasy-land/empty'] === 'function' ? x.constructor['fantasy-land/empty']() : x != null && typeof x.empty === 'function' ? x.empty() : x != null && x.constructor != null && typeof x.constructor.empty === 'function' ? x.constructor.empty() : _isArray(x) ? [] : _isString(x) ? '' : _isObject(x) ? {} : _isArguments(x) ? function () {
2220
+ return arguments;
2221
+ }() : _isTypedArray(x) ? x.constructor.from('') : void 0 // else
2222
+ ;
2223
+ });
2224
+
2225
+ var XFind =
2226
+ /*#__PURE__*/
2227
+ function () {
2228
+ function XFind(f, xf) {
2229
+ this.xf = xf;
2230
+ this.f = f;
2231
+ this.found = false;
2232
+ }
2233
+
2234
+ XFind.prototype['@@transducer/init'] = _xfBase.init;
2235
+
2236
+ XFind.prototype['@@transducer/result'] = function (result) {
2237
+ if (!this.found) {
2238
+ result = this.xf['@@transducer/step'](result, void 0);
2239
+ }
2240
+
2241
+ return this.xf['@@transducer/result'](result);
2242
+ };
2243
+
2244
+ XFind.prototype['@@transducer/step'] = function (result, input) {
2245
+ if (this.f(input)) {
2246
+ this.found = true;
2247
+ result = _reduced(this.xf['@@transducer/step'](result, input));
2248
+ }
2249
+
2250
+ return result;
2251
+ };
2252
+
2253
+ return XFind;
2254
+ }();
2255
+
2256
+ function _xfind(f) {
2257
+ return function (xf) {
2258
+ return new XFind(f, xf);
2259
+ };
2260
+ }
2261
+
2262
+ /**
2263
+ * Returns the first element of the list which matches the predicate, or
2264
+ * `undefined` if no element matches.
2265
+ *
2266
+ * Dispatches to the `find` method of the second argument, if present.
2267
+ *
2268
+ * Acts as a transducer if a transformer is given in list position.
2269
+ *
2270
+ * @func
2271
+ * @memberOf R
2272
+ * @since v0.1.0
2273
+ * @category List
2274
+ * @sig (a -> Boolean) -> [a] -> a | undefined
2275
+ * @param {Function} fn The predicate function used to determine if the element is the
2276
+ * desired one.
2277
+ * @param {Array} list The array to consider.
2278
+ * @return {Object} The element found, or `undefined`.
2279
+ * @see R.transduce
2280
+ * @example
2281
+ *
2282
+ * const xs = [{a: 1}, {a: 2}, {a: 3}];
2283
+ * R.find(R.propEq(2, 'a'))(xs); //=> {a: 2}
2284
+ * R.find(R.propEq(4, 'a'))(xs); //=> undefined
2285
+ */
2286
+
2287
+ var find =
2288
+ /*#__PURE__*/
2289
+ _curry2(
2290
+ /*#__PURE__*/
2291
+ _dispatchable(['find'], _xfind, function find(fn, list) {
2292
+ var idx = 0;
2293
+ var len = list.length;
2294
+
2295
+ while (idx < len) {
2296
+ if (fn(list[idx])) {
2297
+ return list[idx];
2298
+ }
2299
+
2300
+ idx += 1;
2301
+ }
2302
+ }));
2303
+
2304
+ /**
2305
+ * Returns `true` if the specified value is equal, in [`R.equals`](#equals)
2306
+ * terms, to at least one element of the given list; `false` otherwise.
2307
+ * Also works with strings.
2308
+ *
2309
+ * @func
2310
+ * @memberOf R
2311
+ * @since v0.26.0
2312
+ * @category List
2313
+ * @sig a -> [a] -> Boolean
2314
+ * @param {Object} a The item to compare against.
2315
+ * @param {Array} list The array to consider.
2316
+ * @return {Boolean} `true` if an equivalent item is in the list, `false` otherwise.
2317
+ * @see R.any
2318
+ * @example
2319
+ *
2320
+ * R.includes(3, [1, 2, 3]); //=> true
2321
+ * R.includes(4, [1, 2, 3]); //=> false
2322
+ * R.includes({ name: 'Fred' }, [{ name: 'Fred' }]); //=> true
2323
+ * R.includes([42], [[42]]); //=> true
2324
+ * R.includes('ba', 'banana'); //=>true
2325
+ */
2326
+
2327
+ var includes =
2328
+ /*#__PURE__*/
2329
+ _curry2(_includes);
2330
+
2331
+ /**
2332
+ * Given an `arity` (Number) and a `name` (String) the `invoker` function
2333
+ * returns a curried function that takes `arity` arguments and a `context`
2334
+ * object. It will "invoke" the `name`'d function (a method) on the `context`
2335
+ * object.
2336
+ *
2337
+ * @func
2338
+ * @memberOf R
2339
+ * @since v0.1.0
2340
+ * @category Function
2341
+ * @sig Number -> String -> (a -> b -> ... -> n -> Object -> *)
2342
+ * @param {Number} arity Number of arguments the returned function should take
2343
+ * before the target object.
2344
+ * @param {String} method Name of any of the target object's methods to call.
2345
+ * @return {Function} A new curried function.
2346
+ * @see R.construct
2347
+ * @example
2348
+ * // A function with no arguments
2349
+ * const asJson = invoker(0, "json")
2350
+ * // Just like calling .then((response) => response.json())
2351
+ * fetch("http://example.com/index.json").then(asJson)
2352
+ *
2353
+ * // A function with one argument
2354
+ * const sliceFrom = invoker(1, 'slice');
2355
+ * sliceFrom(6, 'abcdefghijklm'); //=> 'ghijklm'
2356
+ *
2357
+ * // A function with two arguments
2358
+ * const sliceFrom6 = invoker(2, 'slice')(6);
2359
+ * sliceFrom6(8, 'abcdefghijklm'); //=> 'gh'
2360
+ *
2361
+ * // NOTE: You can't simply pass some of the arguments to the initial invoker function.
2362
+ * const firstCreditCardSection = invoker(2, "slice", 0, 4)
2363
+ * firstCreditCardSection("4242 4242 4242 4242") // => Function<...>
2364
+ *
2365
+ * // Since invoker returns a curried function, you may partially apply it to create the function you need.
2366
+ * const firstCreditCardSection = invoker(2, "slice")(0, 4)
2367
+ * firstCreditCardSection("4242 4242 4242 4242") // => "4242"
2368
+ *
2369
+ * @symb R.invoker(0, 'method')(o) = o['method']()
2370
+ * @symb R.invoker(1, 'method')(a, o) = o['method'](a)
2371
+ * @symb R.invoker(2, 'method')(a, b, o) = o['method'](a, b)
2372
+ */
2373
+
2374
+ var invoker =
2375
+ /*#__PURE__*/
2376
+ _curry2(function invoker(arity, method) {
2377
+ return curryN(arity + 1, function () {
2378
+ var target = arguments[arity];
2379
+
2380
+ if (target != null && _isFunction(target[method])) {
2381
+ return target[method].apply(target, Array.prototype.slice.call(arguments, 0, arity));
2382
+ }
2383
+
2384
+ throw new TypeError(toString(target) + ' does not have a method named "' + method + '"');
2385
+ });
2386
+ });
2387
+
2388
+ /**
2389
+ * Returns `true` if the given value is its type's empty value; `false`
2390
+ * otherwise.
2391
+ *
2392
+ * @func
2393
+ * @memberOf R
2394
+ * @since v0.1.0
2395
+ * @category Logic
2396
+ * @sig a -> Boolean
2397
+ * @param {*} x
2398
+ * @return {Boolean}
2399
+ * @see R.empty
2400
+ * @example
2401
+ *
2402
+ * R.isEmpty([1, 2, 3]); //=> false
2403
+ * R.isEmpty([]); //=> true
2404
+ * R.isEmpty(''); //=> true
2405
+ * R.isEmpty(null); //=> false
2406
+ * R.isEmpty({}); //=> true
2407
+ * R.isEmpty({length: 0}); //=> false
2408
+ * R.isEmpty(Uint8Array.from('')); //=> true
2409
+ */
2410
+
2411
+ var isEmpty =
2412
+ /*#__PURE__*/
2413
+ _curry1(function isEmpty(x) {
2414
+ return x != null && equals(x, empty(x));
2415
+ });
2416
+
2417
+ /**
2418
+ * Returns a string made by inserting the `separator` between each element and
2419
+ * concatenating all the elements into a single string.
2420
+ *
2421
+ * @func
2422
+ * @memberOf R
2423
+ * @since v0.1.0
2424
+ * @category List
2425
+ * @sig String -> [a] -> String
2426
+ * @param {Number|String} separator The string used to separate the elements.
2427
+ * @param {Array} xs The elements to join into a string.
2428
+ * @return {String} str The string made by concatenating `xs` with `separator`.
2429
+ * @see R.split
2430
+ * @example
2431
+ *
2432
+ * const spacer = R.join(' ');
2433
+ * spacer(['a', 2, 3.4]); //=> 'a 2 3.4'
2434
+ * R.join('|', [1, 2, 3]); //=> '1|2|3'
2435
+ */
2436
+
2437
+ var join =
2438
+ /*#__PURE__*/
2439
+ invoker(1, 'join');
2440
+
2441
+ /**
2442
+ * Returns a lens for the given getter and setter functions. The getter "gets"
2443
+ * the value of the focus; the setter "sets" the value of the focus. The setter
2444
+ * should not mutate the data structure.
2445
+ *
2446
+ * @func
2447
+ * @memberOf R
2448
+ * @since v0.8.0
2449
+ * @category Object
2450
+ * @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
2451
+ * @sig (s -> a) -> ((a, s) -> s) -> Lens s a
2452
+ * @param {Function} getter
2453
+ * @param {Function} setter
2454
+ * @return {Lens}
2455
+ * @see R.view, R.set, R.over, R.lensIndex, R.lensProp
2456
+ * @example
2457
+ *
2458
+ * const xLens = R.lens(R.prop('x'), R.assoc('x'));
2459
+ *
2460
+ * R.view(xLens, {x: 1, y: 2}); //=> 1
2461
+ * R.set(xLens, 4, {x: 1, y: 2}); //=> {x: 4, y: 2}
2462
+ * R.over(xLens, R.negate, {x: 1, y: 2}); //=> {x: -1, y: 2}
2463
+ */
2464
+
2465
+ var lens =
2466
+ /*#__PURE__*/
2467
+ _curry2(function lens(getter, setter) {
2468
+ return function (toFunctorFn) {
2469
+ return function (target) {
2470
+ return map(function (focus) {
2471
+ return setter(focus, target);
2472
+ }, toFunctorFn(getter(target)));
2473
+ };
2474
+ };
2475
+ });
2476
+
2477
+ /**
2478
+ * Retrieves the values at given paths of an object.
2479
+ *
2480
+ * @func
2481
+ * @memberOf R
2482
+ * @since v0.27.1
2483
+ * @category Object
2484
+ * @typedefn Idx = [String | Int | Symbol]
2485
+ * @sig [Idx] -> {a} -> [a | Undefined]
2486
+ * @param {Array} pathsArray The array of paths to be fetched.
2487
+ * @param {Object} obj The object to retrieve the nested properties from.
2488
+ * @return {Array} A list consisting of values at paths specified by "pathsArray".
2489
+ * @see R.path
2490
+ * @example
2491
+ *
2492
+ * R.paths([['a', 'b'], ['p', 0, 'q']], {a: {b: 2}, p: [{q: 3}]}); //=> [2, 3]
2493
+ * R.paths([['a', 'b'], ['p', 'r']], {a: {b: 2}, p: [{q: 3}]}); //=> [2, undefined]
2494
+ */
2495
+
2496
+ var paths =
2497
+ /*#__PURE__*/
2498
+ _curry2(function paths(pathsArray, obj) {
2499
+ return pathsArray.map(function (paths) {
2500
+ var val = obj;
2501
+ var idx = 0;
2502
+ var p;
2503
+
2504
+ while (idx < paths.length) {
2505
+ if (val == null) {
2506
+ return;
2507
+ }
2508
+
2509
+ p = paths[idx];
2510
+ val = _isInteger(p) ? nth(p, val) : val[p];
2511
+ idx += 1;
2512
+ }
2513
+
2514
+ return val;
2515
+ });
2516
+ });
2517
+
2518
+ /**
2519
+ * Retrieves the value at a given path. The nodes of the path can be arbitrary strings or non-negative integers.
2520
+ * For anything else, the value is unspecified. Integer paths are meant to index arrays, strings are meant for objects.
2521
+ *
2522
+ * @func
2523
+ * @memberOf R
2524
+ * @since v0.2.0
2525
+ * @category Object
2526
+ * @typedefn Idx = String | Int | Symbol
2527
+ * @sig [Idx] -> {a} -> a | Undefined
2528
+ * @sig Idx = String | NonNegativeInt
2529
+ * @param {Array} path The path to use.
2530
+ * @param {Object} obj The object or array to retrieve the nested property from.
2531
+ * @return {*} The data at `path`.
2532
+ * @see R.prop, R.nth, R.assocPath, R.dissocPath
2533
+ * @example
2534
+ *
2535
+ * R.path(['a', 'b'], {a: {b: 2}}); //=> 2
2536
+ * R.path(['a', 'b'], {c: {b: 2}}); //=> undefined
2537
+ * R.path(['a', 'b', 0], {a: {b: [1, 2, 3]}}); //=> 1
2538
+ * R.path(['a', 'b', -2], {a: {b: [1, 2, 3]}}); //=> 2
2539
+ * R.path([2], {'2': 2}); //=> 2
2540
+ * R.path([-2], {'-2': 'a'}); //=> undefined
2541
+ */
2542
+
2543
+ var path =
2544
+ /*#__PURE__*/
2545
+ _curry2(function path(pathAr, obj) {
2546
+ return paths([pathAr], obj)[0];
2547
+ });
2548
+
2549
+ /**
2550
+ * Returns a lens whose focus is the specified path.
2551
+ *
2552
+ * @func
2553
+ * @memberOf R
2554
+ * @since v0.19.0
2555
+ * @category Object
2556
+ * @typedefn Idx = String | Int | Symbol
2557
+ * @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
2558
+ * @sig [Idx] -> Lens s a
2559
+ * @param {Array} path The path to use.
2560
+ * @return {Lens}
2561
+ * @see R.view, R.set, R.over
2562
+ * @example
2563
+ *
2564
+ * const xHeadYLens = R.lensPath(['x', 0, 'y']);
2565
+ *
2566
+ * R.view(xHeadYLens, {x: [{y: 2, z: 3}, {y: 4, z: 5}]});
2567
+ * //=> 2
2568
+ * R.set(xHeadYLens, 1, {x: [{y: 2, z: 3}, {y: 4, z: 5}]});
2569
+ * //=> {x: [{y: 1, z: 3}, {y: 4, z: 5}]}
2570
+ * R.over(xHeadYLens, R.negate, {x: [{y: 2, z: 3}, {y: 4, z: 5}]});
2571
+ * //=> {x: [{y: -2, z: 3}, {y: 4, z: 5}]}
2572
+ */
2573
+
2574
+ var lensPath =
2575
+ /*#__PURE__*/
2576
+ _curry1(function lensPath(p) {
2577
+ return lens(path(p), assocPath(p));
2578
+ });
2579
+
2580
+ var Const = function (x) {
2581
+ return {
2582
+ value: x,
2583
+ 'fantasy-land/map': function () {
2584
+ return this;
2585
+ }
2586
+ };
2587
+ };
2588
+ /**
2589
+ * Returns a "view" of the given data structure, determined by the given lens.
2590
+ * The lens's focus determines which portion of the data structure is visible.
2591
+ *
2592
+ * @func
2593
+ * @memberOf R
2594
+ * @since v0.16.0
2595
+ * @category Object
2596
+ * @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
2597
+ * @sig Lens s a -> s -> a
2598
+ * @param {Lens} lens
2599
+ * @param {*} x
2600
+ * @return {*}
2601
+ * @see R.set, R.over, R.lens, R.lensIndex, R.lensProp, R.lensPath
2602
+ * @example
2603
+ *
2604
+ * const xLens = R.lensProp('x');
2605
+ *
2606
+ * R.view(xLens, {x: 1, y: 2}); //=> 1
2607
+ * R.view(xLens, {x: 4, y: 2}); //=> 4
2608
+ */
2609
+
2610
+
2611
+ var view =
2612
+ /*#__PURE__*/
2613
+ _curry2(function view(lens, x) {
2614
+ // Using `Const` effectively ignores the setter function of the `lens`,
2615
+ // leaving the value returned by the getter function unmodified.
2616
+ return lens(Const)(x).value;
2617
+ });
2618
+
2619
+ // helper functions
2620
+ const findValueBy = curry((src, filterKey, searchStr, key) => {
2621
+ const found = (obj) => includes(searchStr, obj[filterKey]);
2622
+ return compose(prop(key), find(found))(src);
2623
+ });
2624
+ const addressLens = lensPath([ 'results', '0', 'address_components' ]);
2625
+
2626
+ const transformPredictionResponse = (predictions, options = {}) => {
2627
+ const { requestCity, requestState, requestZipcode } = options;
2628
+
2629
+ const extractPrediction = (prediction) => {
2630
+ return { description: prediction.description, placeId: prediction.place_id };
2631
+ };
2632
+
2633
+ let scoredPredictions = null;
2634
+ if (!(requestCity || requestState || requestZipcode)) {
2635
+ scoredPredictions = predictions.map(extractPrediction);
2636
+ }
2637
+
2638
+ scoredPredictions = predictions.map((row) => {
2639
+ const result = {
2640
+ description: row.description,
2641
+ place_id: row.place_id
2642
+ };
2643
+ const cityMatch = row.terms.filter((term) => requestCity && term.value === requestCity).length > 0 ? 1 : 0;
2644
+ const stateMatch = row.terms.filter((term) => requestState && term.value === requestState).length > 0 ? 1 : 0;
2645
+ const zipMatch = row.terms.filter((term) => requestZipcode && term.value === requestZipcode).length > 0 ? 1 : 0;
2646
+
2647
+ result.score = cityMatch + stateMatch + zipMatch;
2648
+ result.stateMatch = !requestState || (requestState && stateMatch);
2649
+ result.zipCodeMatch = !requestZipcode || (requestZipcode && zipMatch);
2650
+
2651
+ return result;
2652
+ }).filter(
2653
+ rec => !!rec.stateMatch && !!rec.zipCodeMatch
2654
+ ).sort((a, b) => {
2655
+ if (a.score === b.score) {
2656
+ return 0;
2657
+ }
2658
+ return a.score < b.score ? 1 : -1;
2659
+ }).map(extractPrediction);
2660
+
2661
+ return scoredPredictions;
2662
+ };
2663
+
2664
+ const parsePlacesAddress = (res) => {
2665
+ const placeResult = res.results ? res.results[0] : res.result;
2666
+ if (!placeResult || isEmpty(placeResult)) {
2667
+ return {};
2668
+ }
2669
+
2670
+ let addressComponents = null;
2671
+ if (res.results) {
2672
+ addressComponents = view(addressLens)(res);
2673
+ } else {
2674
+ addressComponents = placeResult.address_components;
2675
+ }
2676
+
2677
+ const findAddressComponentByType = findValueBy(addressComponents, 'types');
2678
+
2679
+ const formattedAddress = placeResult.formatted_address;
2680
+ const latitude =
2681
+ placeResult.geometry &&
2682
+ placeResult.geometry.location &&
2683
+ placeResult.geometry.location.lat
2684
+ ? placeResult.geometry.location.lat
2685
+ : null;
2686
+ const longitude =
2687
+ placeResult.geometry &&
2688
+ placeResult.geometry.location &&
2689
+ placeResult.geometry.location.lng
2690
+ ? placeResult.geometry.location.lng
2691
+ : null;
2692
+
2693
+ const streetNumber = findAddressComponentByType('street_number', 'short_name') || '';
2694
+ const streetRoute = findAddressComponentByType('route', 'long_name') || '';
2695
+ const street1 =
2696
+ (streetNumber || streetRoute) && `${streetNumber} ${streetRoute}`;
2697
+
2698
+ const address = {
2699
+ state: findAddressComponentByType('administrative_area_level_1', 'short_name'),
2700
+ city:
2701
+ findAddressComponentByType('locality', 'short_name') ||
2702
+ findAddressComponentByType('sublocality', 'short_name') ||
2703
+ findAddressComponentByType('neighborhood', 'long_name') ||
2704
+ findAddressComponentByType('administrative_area_level_3', 'long_name') ||
2705
+ findAddressComponentByType('administrative_area_level_2', 'short_name'),
2706
+ street_1: street1.trim(),
2707
+ country: findAddressComponentByType('country', 'short_name'),
2708
+ zipcode: findAddressComponentByType('postal_code', 'long_name'),
2709
+ latitude: latitude && Number(latitude),
2710
+ longitude: longitude && Number(longitude),
2711
+ formattedAddress
2712
+ };
2713
+ return filter(Boolean)(address);
2714
+ };
2715
+
2716
+ class GeoService {
2717
+ constructor (mapsKey) {
2718
+ this.mapsKey = mapsKey;
2719
+ }
2720
+
2721
+ async geocode (address) {
2722
+ const res = await fetch(
2723
+ `https://maps.googleapis.com/maps/api/geocode/json?address=${address}&key=${this.mapsKey}`
2724
+ );
2725
+ const response = await res.json();
2726
+ return parsePlacesAddress(response);
2727
+ }
2728
+
2729
+ async geocodeZip (zipCode) {
2730
+ const res = await fetch(
2731
+ `https://maps.googleapis.com/maps/api/geocode/json?components=country:US|postal_code:${zipCode}&key=${this.mapsKey}`
2732
+ );
2733
+ const response = await res.json();
2734
+ return parsePlacesAddress(response);
2735
+ }
2736
+
2737
+ async reverseGeocode (lat, lng) {
2738
+ const res = await fetch(
2739
+ `https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${this.mapsKey}`
2740
+ );
2741
+ const response = await res.json();
2742
+ return parsePlacesAddress(response);
2743
+ }
2744
+
2745
+ async geoLocate () {
2746
+ // https://developers.google.com/maps/documentation/geolocation/overview
2747
+ // NOTE: also returns accuracy (95% confidence of lat, lng in meters)
2748
+ const url = `https://www.googleapis.com/geolocation/v1/geolocate?key=${this.mapsKey}`;
2749
+ const requestConfig = {
2750
+ method: 'POST',
2751
+ headers: {
2752
+ Accept: 'application/json',
2753
+ 'Content-Type': 'application/json'
2754
+ }
2755
+ };
2756
+ const request = await fetch(url, requestConfig);
2757
+ const response = await request.json();
2758
+ const { lat, lng } = response.location;
2759
+ return this.reverseGeocode(lat, lng);
2760
+ }
2761
+
2762
+ async getLocationSuggestions (payload) {
2763
+ /*
2764
+ https://developers.google.com/maps/documentation/places/web-service/autocomplete
2765
+ Component should use session token: https://developers.google.com/maps/documentation/places/web-service/autocomplete#sessiontoken
2766
+ **/
2767
+ const { input, latitude, longitude, radius } = payload;
2768
+ const { requestCity, requestState, requestZipcode } = payload;
2769
+ const location = join(',', filter(Boolean, [ latitude, longitude ]));
2770
+
2771
+ let { sessiontoken } = payload;
2772
+ if (!sessiontoken) {
2773
+ sessiontoken = crypto.randomUUID().replaceAll('-', '');
2774
+ }
2775
+
2776
+ const params = filter(Boolean, {
2777
+ input,
2778
+ sessiontoken,
2779
+ location, // The point around which to retrieve place information.
2780
+ radius, // The radius parameter must also be provided when specifying a location
2781
+ components: 'country:US',
2782
+ types: 'address',
2783
+ key: this.mapsKey
2784
+ });
2785
+
2786
+ let queryString = '';
2787
+ if (params) {
2788
+ const searchParams = new URLSearchParams(params);
2789
+ queryString = searchParams.toString();
2790
+ }
2791
+
2792
+ const url = `https://maps.googleapis.com/maps/api/place/autocomplete/json?${queryString}`;
2793
+ const requestConfig = {
2794
+ method: 'GET',
2795
+ headers: {
2796
+ Accept: 'application/json'
2797
+ }
2798
+ };
2799
+ const request = await fetch(url, requestConfig);
2800
+ const response = await request.json();
2801
+
2802
+ let autocompletePredictions = [];
2803
+ if (response.predictions && response.status === 'OK') {
2804
+ const options = { requestCity, requestState, requestZipcode };
2805
+ autocompletePredictions = transformPredictionResponse(response.predictions, options);
2806
+ }
2807
+ return { autocompletePredictions, sessiontoken };
2808
+ }
2809
+
2810
+ async getPlaceId (payload) {
2811
+ const { placeId, sessiontoken } = payload;
2812
+
2813
+ const params = filter(Boolean, {
2814
+ place_id: placeId,
2815
+ sessiontoken,
2816
+ key: this.mapsKey
2817
+ });
2818
+ let queryString = '';
2819
+ if (params) {
2820
+ const searchParams = new URLSearchParams(params);
2821
+ queryString = searchParams.toString();
2822
+ }
2823
+
2824
+ const url = `https://maps.googleapis.com/maps/api/place/details/json?${queryString}`;
2825
+ const res = await fetch(url);
2826
+ const response = await res.json();
2827
+ return parsePlacesAddress(response);
2828
+ }
2829
+
2830
+ async getNavigatorPosition () {
2831
+ // check if navigator is available
2832
+ // NOTE: also returns accuracy (95% confidence of lat, lng in meters)
2833
+ // TODO: check accuracy and only return if within acceptable limit, provided in payload
2834
+ const handleError = (error) => {
2835
+ console.error(error);
2836
+ };
2837
+ (navigator.geolocation && navigator.geolocation.getCurrentPosition(
2838
+ (position) => {
2839
+ const lat = position.coords.latitude;
2840
+ const lng = position.coords.longitude;
2841
+ return this.reverseGeocode(lat, lng);
2842
+ },
2843
+ handleError
2844
+ )) || handleError({ message: 'geolocation is not enabled.' });
2845
+ }
2846
+ }
2847
+
2848
+ export { GeoService, ThirstieAPI };