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