@controleonline/ui-common 1.2.70 → 1.2.71

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.
Files changed (61) hide show
  1. package/package.json +31 -28
  2. package/src/api/index.js +237 -37
  3. package/src/react/components/AddImportModal.js +1 -1
  4. package/src/react/components/AnimatedModal.js +171 -0
  5. package/src/react/components/AnimatedModal.styles.js +21 -0
  6. package/src/react/components/AppTypeSwitcher.js +164 -0
  7. package/src/react/components/AppTypeSwitcher.styles.js +109 -0
  8. package/src/react/components/BackgroundRuntimeBridge.js +5 -4
  9. package/src/react/components/BottomNavigationBar.js +86 -31
  10. package/src/react/components/BottomNavigationBar.styles.js +118 -110
  11. package/src/react/components/DefaultProvider.native.js +68 -66
  12. package/src/react/components/DefaultProvider.web.js +44 -42
  13. package/src/react/components/DeliveryPushBridge.native.js +2 -2
  14. package/src/react/components/DeviceAlertSoundService.js +3 -3
  15. package/src/react/components/KioskModeBridge.js +2 -2
  16. package/src/react/components/LauncherModeBridge.js +2 -2
  17. package/src/react/components/ManagerPushBridge.native.js +2 -2
  18. package/src/react/components/RemoteCheckoutService.js +28 -20
  19. package/src/react/components/RuntimeBottomNavigationBar.js +146 -119
  20. package/src/react/components/RuntimeInfoFooter.js +37 -9
  21. package/src/react/components/StateStore.js +258 -0
  22. package/src/react/components/WebsocketListener.native.js +11 -11
  23. package/src/react/config/deviceConfigBootstrap.js +66 -27
  24. package/src/react/css/orders.js +72 -0
  25. package/src/react/pages/SettingsPage/PaymentTypesByWalletTab.js +484 -454
  26. package/src/react/pages/SettingsPage/index.js +1266 -1167
  27. package/src/react/print/providers/local.js +1 -1
  28. package/src/react/router/publicRoutes.js +25 -0
  29. package/src/react/services/Cielo/Checkout.js +39 -0
  30. package/src/react/services/Cielo/Cielo.js +193 -0
  31. package/src/react/services/Cielo/Print.js +7 -0
  32. package/src/react/services/InfinitePay/Checkout.js +33 -0
  33. package/src/react/services/InfinitePay/InfinitePay.js +24 -0
  34. package/src/react/{utils → services}/paymentGatewayExecution.js +91 -91
  35. package/src/react/styles/global.js +115 -0
  36. package/src/react/utils/fileUrl.js +182 -16
  37. package/src/react/utils/menuNavigation.js +31 -0
  38. package/src/react/utils/orderIdentity.js +277 -0
  39. package/src/react/utils/remotePayment.js +115 -61
  40. package/src/react/utils/runtimeMenu.js +35 -3
  41. package/src/react/utils/shopConfig.js +50 -24
  42. package/src/react/utils/shopFranchises.js +56 -22
  43. package/src/react/utils/socketRuntimePipeline.js +14 -14
  44. package/src/store/configs/index.js +2 -2
  45. package/src/tests/react/api/loadSmokeIndex.test.js +75 -0
  46. package/src/tests/react/config/deviceConfigBootstrap.test.js +47 -0
  47. package/src/tests/react/print/localPrintProvider.test.js +1 -1
  48. package/src/tests/react/services/Cielo.test.js +190 -0
  49. package/src/tests/react/utils/fileUrl.test.js +62 -0
  50. package/src/tests/react/utils/importStatus.test.js +2 -2
  51. package/src/tests/react/utils/orderIdentity.test.js +139 -0
  52. package/src/tests/react/utils/remotePayment.test.js +62 -0
  53. package/src/tests/react/utils/runtimeFooter.test.js +4 -6
  54. package/src/tests/react/utils/runtimeLanguage.test.js +2 -2
  55. package/src/tests/react/utils/runtimeMenu.test.js +23 -3
  56. package/src/tests/react/utils/shopConfig.test.js +74 -0
  57. package/src/tests/react/utils/shopFranchises.test.js +79 -12
  58. package/src/tests/react/utils/translate.test.mjs +166 -102
  59. package/src/utils/formatter.js +18 -0
  60. package/src/utils/integrationConfigs.js +80 -79
  61. package/src/utils/translate.js +125 -30
@@ -5,9 +5,10 @@ jest.mock('@controleonline/ui-common/src/api', () => ({
5
5
  }));
6
6
 
7
7
  const {api} = require('@controleonline/ui-common/src/api');
8
- const {
9
- fetchShopFranchiseDirectory,
10
- } = require('../../../react/utils/shopFranchises');
8
+ const {
9
+ fetchAllShopFranchiseDirectory,
10
+ fetchShopFranchiseDirectory,
11
+ } = require('../../../react/utils/shopFranchises');
11
12
 
12
13
  const {beforeEach, describe, expect, it} = global;
13
14
 
@@ -54,10 +55,10 @@ describe('shopFranchises', () => {
54
55
  ]);
55
56
  });
56
57
 
57
- it('keeps authenticated management lookup scoped by company', async () => {
58
- api.fetch.mockResolvedValueOnce({
59
- member: [
60
- {
58
+ it('keeps authenticated management lookup scoped by company', async () => {
59
+ api.fetch.mockResolvedValueOnce({
60
+ member: [
61
+ {
61
62
  id: 22,
62
63
  alias: 'Norte',
63
64
  address: [{id: 601, nickname: 'Loja Norte'}],
@@ -75,8 +76,74 @@ describe('shopFranchises', () => {
75
76
  page: 1,
76
77
  },
77
78
  });
78
- expect(directory[0].shopAddresses).toEqual([
79
- {id: 601, nickname: 'Loja Norte'},
80
- ]);
81
- });
82
- });
79
+ expect(directory[0].shopAddresses).toEqual([
80
+ {id: 601, nickname: 'Loja Norte'},
81
+ ]);
82
+ });
83
+
84
+ it('loads every page when building the full franchise directory', async () => {
85
+ api.fetch
86
+ .mockResolvedValueOnce({
87
+ member: [
88
+ {
89
+ id: 21,
90
+ alias: 'Centro',
91
+ shopAddresses: [{id: 501, nickname: 'Loja Centro'}],
92
+ },
93
+ {
94
+ id: 22,
95
+ alias: 'Norte',
96
+ shopAddresses: [{id: 601, nickname: 'Loja Norte'}],
97
+ },
98
+ ],
99
+ })
100
+ .mockResolvedValueOnce({
101
+ member: [
102
+ {
103
+ id: 23,
104
+ alias: 'Sul',
105
+ shopAddresses: [{id: 701, nickname: 'Loja Sul'}],
106
+ },
107
+ ],
108
+ });
109
+
110
+ const directory = await fetchAllShopFranchiseDirectory({
111
+ companyId: 10,
112
+ itemsPerPage: 2,
113
+ });
114
+
115
+ expect(api.fetch).toHaveBeenNthCalledWith(1, 'people', {
116
+ params: {
117
+ 'link.company': '/people/10',
118
+ 'link.linkType': 'franchisee',
119
+ itemsPerPage: 2,
120
+ page: 1,
121
+ },
122
+ });
123
+ expect(api.fetch).toHaveBeenNthCalledWith(2, 'people', {
124
+ params: {
125
+ 'link.company': '/people/10',
126
+ 'link.linkType': 'franchisee',
127
+ itemsPerPage: 2,
128
+ page: 2,
129
+ },
130
+ });
131
+ expect(directory).toEqual([
132
+ {
133
+ id: 21,
134
+ alias: 'Centro',
135
+ shopAddresses: [{id: 501, nickname: 'Loja Centro'}],
136
+ },
137
+ {
138
+ id: 22,
139
+ alias: 'Norte',
140
+ shopAddresses: [{id: 601, nickname: 'Loja Norte'}],
141
+ },
142
+ {
143
+ id: 23,
144
+ alias: 'Sul',
145
+ shopAddresses: [{id: 701, nickname: 'Loja Sul'}],
146
+ },
147
+ ]);
148
+ });
149
+ });
@@ -42,7 +42,7 @@ const normalizeId = value =>
42
42
  .replace(/\D+/g, '')
43
43
  .trim();
44
44
 
45
- const createPendingTranslateStore = ({getItems, save} = {}) => {
45
+ const createPendingTranslateStore = ({getItems, save, resolveQueuedMessages} = {}) => {
46
46
  const store = {
47
47
  getters: {
48
48
  messages: {},
@@ -51,12 +51,17 @@ const createPendingTranslateStore = ({getItems, save} = {}) => {
51
51
  actions: {},
52
52
  };
53
53
 
54
- const translateActions = {
55
- getItems: getItems || (async () => []),
56
- save: save || (async payload => payload),
57
- setMessages: nextMessages => {
58
- store.getters.messages = nextMessages;
59
- return nextMessages;
54
+ const translateActions = {
55
+ getItems: getItems || (async () => []),
56
+ save: save || (async payload => payload),
57
+ ...(resolveQueuedMessages
58
+ ? {
59
+ resolveQueuedMessages,
60
+ }
61
+ : {}),
62
+ setMessages: nextMessages => {
63
+ store.getters.messages = nextMessages;
64
+ return nextMessages;
60
65
  },
61
66
  setPendingMessages: nextMessages => {
62
67
  store.getters.pendingMessages = nextMessages;
@@ -229,19 +234,14 @@ test('hydrates the cached translations into the translate store on startup', ()
229
234
  );
230
235
  });
231
236
 
232
- test('posts missing translations once and keeps the fallback until review', async () => {
233
- installLocalStorage();
234
-
235
- const discoveryCalls = [];
236
- const saveCalls = [];
237
- const translateStore = createPendingTranslateStore({
238
- getItems: async params => {
239
- discoveryCalls.push(params);
240
- return [];
241
- },
242
- save: async payload => {
243
- saveCalls.push(payload);
244
- return payload;
237
+ test('posts missing translations once and keeps the fallback until review', async () => {
238
+ installLocalStorage();
239
+
240
+ const saveCalls = [];
241
+ const translateStore = createPendingTranslateStore({
242
+ save: async payload => {
243
+ saveCalls.push(payload);
244
+ return payload;
245
245
  },
246
246
  });
247
247
  const translate = new Translate(
@@ -257,15 +257,12 @@ test('posts missing translations once and keeps the fallback until review', asyn
257
257
 
258
258
  assert.equal(firstValue, 'None registered title');
259
259
  assert.equal(secondValue, 'None registered title');
260
-
261
- await flushAsync();
262
-
263
- assert.deepEqual(discoveryCalls, [
264
- {store: 'contract', 'language.language': 'pt-br', people: '/people/1', page: 1},
265
- ]);
266
- assert.deepEqual(saveCalls, [{
267
- people: '/people/1',
268
- language: 'pt-br',
260
+
261
+ await flushAsync();
262
+
263
+ assert.deepEqual(saveCalls, [{
264
+ people: '/people/1',
265
+ language: 'pt-br',
269
266
  store: 'contract',
270
267
  type: 'empty',
271
268
  key: 'none_registered_title',
@@ -275,12 +272,95 @@ test('posts missing translations once and keeps the fallback until review', asyn
275
272
  assert.equal(
276
273
  translateStore.messages['pt-br'].companies[1].contract.empty.none_registered_title,
277
274
  'None registered title',
278
- );
279
- assert.deepEqual(translateStore.pendingMessages, {});
280
- });
281
-
282
- test('persists missing translations with the normalized configured language', async () => {
283
- installLocalStorage({language: 'en_US'});
275
+ );
276
+ assert.deepEqual(translateStore.pendingMessages, {});
277
+ });
278
+
279
+ test('queues missing translations in a single batch resolve request', async () => {
280
+ installLocalStorage();
281
+
282
+ const resolveCalls = [];
283
+ const translateStore = createPendingTranslateStore({
284
+ resolveQueuedMessages: async payload => {
285
+ resolveCalls.push(payload);
286
+
287
+ return [
288
+ {
289
+ people: '/people/1',
290
+ language: {
291
+ id: 1,
292
+ language: 'pt-br',
293
+ },
294
+ store: 'contract',
295
+ type: 'empty',
296
+ key: 'none_registered_title',
297
+ translate: 'Nenhum registro cadastrado',
298
+ revised: false,
299
+ },
300
+ {
301
+ people: '/people/1',
302
+ language: {
303
+ id: 1,
304
+ language: 'pt-br',
305
+ },
306
+ store: 'contract',
307
+ type: 'empty',
308
+ key: 'none_registered_subtitle',
309
+ translate: 'Nenhum subtítulo cadastrado',
310
+ revised: false,
311
+ },
312
+ ];
313
+ },
314
+ });
315
+ const translate = new Translate(
316
+ [{id: 1}],
317
+ {id: 1},
318
+ {id: 1},
319
+ ['contract'],
320
+ translateStore,
321
+ );
322
+
323
+ assert.equal(
324
+ translate.t('contract', 'empty', 'none_registered_title'),
325
+ 'None registered title',
326
+ );
327
+ assert.equal(
328
+ translate.t('contract', 'empty', 'none_registered_subtitle'),
329
+ 'None registered subtitle',
330
+ );
331
+ assert.equal(
332
+ translate.t('contract', 'empty', 'none_registered_title'),
333
+ 'None registered title',
334
+ );
335
+
336
+ await flushAsync();
337
+
338
+ assert.deepEqual(resolveCalls, [
339
+ {
340
+ people: '/people/1',
341
+ language: 'pt-br',
342
+ requests: [
343
+ {
344
+ store: 'contract',
345
+ type: 'empty',
346
+ keys: ['none_registered_title', 'none_registered_subtitle'],
347
+ },
348
+ ],
349
+ },
350
+ ]);
351
+ assert.equal(
352
+ translateStore.messages['pt-br'].companies[1].contract.empty.none_registered_title,
353
+ 'Nenhum registro cadastrado',
354
+ );
355
+ assert.equal(
356
+ translateStore.messages['pt-br'].companies[1].contract.empty.none_registered_subtitle,
357
+ 'Nenhum subtítulo cadastrado',
358
+ );
359
+ assert.deepEqual(translateStore.pendingMessages, {});
360
+ });
361
+
362
+ test('persists missing translations with the normalized configured language', async () => {
363
+ installLocalStorage({language: 'en_US'});
284
364
 
285
365
  const saveCalls = [];
286
366
  const translateStore = createPendingTranslateStore({
@@ -312,10 +392,10 @@ test('persists missing translations with the normalized configured language', as
312
392
  );
313
393
  });
314
394
 
315
- test('loads each requested store only for the current and default companies', async () => {
316
- installLocalStorage();
317
-
318
- const calls = [];
395
+ test('loads each requested store only for the current and default companies', async () => {
396
+ installLocalStorage();
397
+
398
+ const calls = [];
319
399
  const translate = new Translate(
320
400
  [{id: 1}, {id: 5}, {id: 9}],
321
401
  {id: 1},
@@ -331,66 +411,50 @@ test('loads each requested store only for the current and default companies', as
331
411
 
332
412
  await translate.discoveryAll();
333
413
 
334
- assert.deepEqual(calls, [
335
- {store: 'orders', 'language.language': 'pt-br', people: '/people/1', page: 1},
336
- {store: 'crm', 'language.language': 'pt-br', people: '/people/1', page: 1},
337
- {store: 'orders', 'language.language': 'pt-br', people: '/people/5', page: 1},
338
- {store: 'crm', 'language.language': 'pt-br', people: '/people/5', page: 1},
339
- ]);
340
- });
341
-
342
- test('removes stale pending entries once a discovered store returns the real translation', async () => {
343
- installLocalStorage();
344
-
345
- const translateStore = createPendingTranslateStore({
346
- getItems: async params => {
347
- if (params.page === 1) {
348
- return [
349
- {
350
- store: 'menu',
351
- type: 'menu',
352
- key: 'orders',
353
- translate: 'Pedidos',
354
- },
355
- ];
356
- }
357
-
358
- return [];
359
- },
360
- });
361
-
362
- let refreshCalls = 0;
363
- global.refreshTranslationsUI = () => {
364
- refreshCalls += 1;
365
- };
366
-
367
- const translate = new Translate(
368
- [{id: 1}],
369
- {id: 1},
370
- {id: 1},
371
- ['orders'],
372
- translateStore,
373
- );
374
-
375
- translateStore.actions.setPendingMessages({
376
- 'pt-br': {
377
- companies: {
378
- 1: {
379
- menu: {
380
- menu: {
381
- orders: 'Orders',
382
- },
383
- },
384
- },
385
- },
386
- },
387
- });
388
-
389
- assert.equal(translate.t('menu', 'menu', 'orders'), 'Orders');
390
-
391
- await flushAsync();
392
-
393
- assert.deepEqual(translateStore.pendingMessages, {});
394
- assert.equal(refreshCalls, 1);
395
- assert.equal(translate.t('menu', 'menu', 'orders'), 'Pedidos');
396
- });
414
+ assert.deepEqual(calls, [
415
+ {store: 'orders', 'language.language': 'pt-br', people: '/people/1', page: 1},
416
+ {store: 'crm', 'language.language': 'pt-br', people: '/people/1', page: 1},
417
+ {store: 'orders', 'language.language': 'pt-br', people: '/people/5', page: 1},
418
+ {store: 'crm', 'language.language': 'pt-br', people: '/people/5', page: 1},
419
+ ]);
420
+ });
421
+
422
+ test('reuses cached store buckets without refetching after in-memory discovery is cleared', async () => {
423
+ installLocalStorage();
424
+ localStorage.setItem('translates', JSON.stringify({
425
+ 'pt-br': {
426
+ companies: {
427
+ 1: {
428
+ contract: {
429
+ empty: {
430
+ none_registered_title: 'None registered title',
431
+ },
432
+ },
433
+ },
434
+ },
435
+ },
436
+ }));
437
+
438
+ const calls = [];
439
+ const translateStore = createPendingTranslateStore({
440
+ getItems: async params => {
441
+ calls.push(params);
442
+ return [];
443
+ },
444
+ });
445
+ const translate = new Translate(
446
+ [{id: 1}],
447
+ {id: 1},
448
+ {id: 1},
449
+ ['contract'],
450
+ translateStore,
451
+ );
452
+
453
+ translate.discoveredStores.clear();
454
+
455
+ assert.equal(translate.t('contract', 'empty', 'none_registered_title'), 'None registered title');
456
+
457
+ await flushAsync();
458
+
459
+ assert.deepEqual(calls, []);
460
+ });
@@ -310,6 +310,24 @@ export default class Formatter {
310
310
  return `${Formatter.formatDecimal(value, locale, maximumFractionDigits)}%`;
311
311
  }
312
312
 
313
+ static formatCount(value, singular, plural = `${singular}s`) {
314
+ return `${value} ${value === 1 ? singular : plural}`;
315
+ }
316
+
317
+ static formatDateTime(value) {
318
+ if (!value) return 'sem data';
319
+
320
+ const date = new Date(value);
321
+
322
+ if (isNaN(date.getTime()))
323
+ return value;
324
+
325
+ return new Intl.DateTimeFormat('pt-BR', {
326
+ dateStyle: 'medium',
327
+ timeStyle: 'short',
328
+ }).format(date);
329
+ }
330
+
313
331
  static formatSignedInteger(value, locale = 'pt-BR') {
314
332
 
315
333
  const numericValue = Number(value || 0);
@@ -1,79 +1,80 @@
1
- export const CIELO_CONFIG_KEY = 'CIELO';
2
- export const NEW_RELIC_CONFIG_KEY = 'NEW_RELIC';
3
- export const SPOTIFY_CONFIG_KEY = 'SPOTIFY';
4
-
5
- export const DEFAULT_CIELO_CONFIG = {
6
- ACCESS_TOKEN: '',
7
- CLIENT_ID: '',
8
- EMAIL: '',
9
- };
10
-
11
- export const DEFAULT_NEW_RELIC_CONFIG = {
12
- LICENSE_KEY: '',
13
- APPLICATION_ID: '',
14
- ACCOUNT_ID: '',
15
- TRUST_KEY: '',
16
- BEACON: 'bam.nr-data.net',
17
- ERROR_BEACON: 'bam.nr-data.net',
18
- };
19
-
20
- export const DEFAULT_SPOTIFY_CONFIG = {
21
- CLIENT_ID: '',
22
- CLIENT_SECRET: '',
23
- };
24
-
25
- const isConfigMap = value =>
26
- value && typeof value === 'object' && !Array.isArray(value);
27
-
28
- const parseJsonValue = (value, fallback) => {
29
- if (value === null || value === undefined || value === '') {
30
- return fallback;
31
- }
32
-
33
- if (typeof value === 'string') {
34
- try {
35
- return JSON.parse(value);
36
- } catch {
37
- return fallback;
38
- }
39
- }
40
-
41
- return value;
42
- };
43
-
44
- const normalizeTextValue = value => String(value || '').trim();
45
-
46
- export const resolveIntegrationConfig = (configs, configKey, defaults) => {
47
- if (!isConfigMap(defaults)) {
48
- return {};
49
- }
50
-
51
- const rawConfig = isConfigMap(configs)
52
- ? parseJsonValue(configs[configKey], {})
53
- : {};
54
- const source = isConfigMap(rawConfig) ? rawConfig : {};
55
-
56
- return Object.keys(defaults).reduce((accumulator, fieldKey) => {
57
- accumulator[fieldKey] = normalizeTextValue(
58
- source[fieldKey] !== undefined ? source[fieldKey] : defaults[fieldKey],
59
- );
60
- return accumulator;
61
- }, {});
62
- };
63
-
64
- export const resolveCieloConfig = configs =>
65
- resolveIntegrationConfig(configs, CIELO_CONFIG_KEY, DEFAULT_CIELO_CONFIG);
66
-
67
- export const resolveNewRelicConfig = configs =>
68
- resolveIntegrationConfig(
69
- configs,
70
- NEW_RELIC_CONFIG_KEY,
71
- DEFAULT_NEW_RELIC_CONFIG,
72
- );
73
-
74
- export const resolveSpotifyConfig = configs =>
75
- resolveIntegrationConfig(
76
- configs,
77
- SPOTIFY_CONFIG_KEY,
78
- DEFAULT_SPOTIFY_CONFIG,
79
- );
1
+ export const CIELO_CONFIG_KEY = 'CIELO';
2
+ export const NEW_RELIC_CONFIG_KEY = 'NEW_RELIC';
3
+ export const SPOTIFY_CONFIG_KEY = 'SPOTIFY';
4
+
5
+ export const DEFAULT_CIELO_CONFIG = {
6
+ ACCESS_TOKEN: '',
7
+ CLIENT_ID: '',
8
+ EMAIL: '',
9
+ MERCHANT_CODE: '',
10
+ };
11
+
12
+ export const DEFAULT_NEW_RELIC_CONFIG = {
13
+ LICENSE_KEY: '',
14
+ APPLICATION_ID: '',
15
+ ACCOUNT_ID: '',
16
+ TRUST_KEY: '',
17
+ BEACON: 'bam.nr-data.net',
18
+ ERROR_BEACON: 'bam.nr-data.net',
19
+ };
20
+
21
+ export const DEFAULT_SPOTIFY_CONFIG = {
22
+ CLIENT_ID: '',
23
+ CLIENT_SECRET: '',
24
+ };
25
+
26
+ const isConfigMap = value =>
27
+ value && typeof value === 'object' && !Array.isArray(value);
28
+
29
+ const parseJsonValue = (value, fallback) => {
30
+ if (value === null || value === undefined || value === '') {
31
+ return fallback;
32
+ }
33
+
34
+ if (typeof value === 'string') {
35
+ try {
36
+ return JSON.parse(value);
37
+ } catch {
38
+ return fallback;
39
+ }
40
+ }
41
+
42
+ return value;
43
+ };
44
+
45
+ const normalizeTextValue = value => String(value || '').trim();
46
+
47
+ export const resolveIntegrationConfig = (configs, configKey, defaults) => {
48
+ if (!isConfigMap(defaults)) {
49
+ return {};
50
+ }
51
+
52
+ const rawConfig = isConfigMap(configs)
53
+ ? parseJsonValue(configs[configKey], {})
54
+ : {};
55
+ const source = isConfigMap(rawConfig) ? rawConfig : {};
56
+
57
+ return Object.keys(defaults).reduce((accumulator, fieldKey) => {
58
+ accumulator[fieldKey] = normalizeTextValue(
59
+ source[fieldKey] !== undefined ? source[fieldKey] : defaults[fieldKey],
60
+ );
61
+ return accumulator;
62
+ }, {});
63
+ };
64
+
65
+ export const resolveCieloConfig = configs =>
66
+ resolveIntegrationConfig(configs, CIELO_CONFIG_KEY, DEFAULT_CIELO_CONFIG);
67
+
68
+ export const resolveNewRelicConfig = configs =>
69
+ resolveIntegrationConfig(
70
+ configs,
71
+ NEW_RELIC_CONFIG_KEY,
72
+ DEFAULT_NEW_RELIC_CONFIG,
73
+ );
74
+
75
+ export const resolveSpotifyConfig = configs =>
76
+ resolveIntegrationConfig(
77
+ configs,
78
+ SPOTIFY_CONFIG_KEY,
79
+ DEFAULT_SPOTIFY_CONFIG,
80
+ );