@zohodesk/i18n 1.0.0-beta.34 → 1.0.0-beta.35-murphy

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 (51) hide show
  1. package/docs/murphy/01-MURPHY_OVERVIEW.md +148 -0
  2. package/docs/murphy/02-MURPHY_ARCHITECTURE.md +283 -0
  3. package/docs/murphy/03-MURPHY_BACKEND_CONFIG.md +337 -0
  4. package/docs/murphy/04-MURPHY_FRONTEND_INIT.md +437 -0
  5. package/docs/murphy/05-MURPHY_DESK_CLIENT_USAGE.md +467 -0
  6. package/docs/murphy/06-MURPHY_I18N_INTEGRATION.md +402 -0
  7. package/docs/murphy/07-MURPHY_WHY_I18N_APPROACH.md +391 -0
  8. package/es/components/DateTimeDiffFormat.js +5 -19
  9. package/es/components/FormatText.js +2 -2
  10. package/es/components/HOCI18N.js +32 -43
  11. package/es/components/I18N.js +2 -13
  12. package/es/components/I18NProvider.js +0 -9
  13. package/es/components/PluralFormat.js +3 -5
  14. package/es/components/UserTimeDiffFormat.js +5 -9
  15. package/es/components/__tests__/DateTimeDiffFormat.spec.js +157 -221
  16. package/es/components/__tests__/FormatText.spec.js +2 -2
  17. package/es/components/__tests__/HOCI18N.spec.js +2 -4
  18. package/es/components/__tests__/I18N.spec.js +6 -4
  19. package/es/components/__tests__/I18NProvider.spec.js +4 -4
  20. package/es/components/__tests__/PluralFormat.spec.js +2 -2
  21. package/es/components/__tests__/UserTimeDiffFormat.spec.js +249 -348
  22. package/es/index.js +1 -0
  23. package/es/utils/__tests__/jsxTranslations.spec.js +3 -7
  24. package/es/utils/errorReporter.js +31 -0
  25. package/es/utils/index.js +42 -92
  26. package/es/utils/jsxTranslations.js +34 -52
  27. package/lib/I18NContext.js +2 -7
  28. package/lib/components/DateTimeDiffFormat.js +46 -87
  29. package/lib/components/FormatText.js +18 -41
  30. package/lib/components/HOCI18N.js +24 -59
  31. package/lib/components/I18N.js +27 -64
  32. package/lib/components/I18NProvider.js +27 -63
  33. package/lib/components/PluralFormat.js +24 -50
  34. package/lib/components/UserTimeDiffFormat.js +43 -72
  35. package/lib/components/__tests__/DateTimeDiffFormat.spec.js +95 -165
  36. package/lib/components/__tests__/FormatText.spec.js +3 -10
  37. package/lib/components/__tests__/HOCI18N.spec.js +3 -14
  38. package/lib/components/__tests__/I18N.spec.js +4 -12
  39. package/lib/components/__tests__/I18NProvider.spec.js +8 -23
  40. package/lib/components/__tests__/PluralFormat.spec.js +3 -11
  41. package/lib/components/__tests__/UserTimeDiffFormat.spec.js +157 -225
  42. package/lib/index.js +25 -23
  43. package/lib/utils/__tests__/jsxTranslations.spec.js +1 -12
  44. package/lib/utils/errorReporter.js +39 -0
  45. package/lib/utils/index.js +49 -125
  46. package/lib/utils/jsxTranslations.js +61 -100
  47. package/package.json +1 -1
  48. package/src/index.js +5 -0
  49. package/src/utils/errorReporter.js +36 -0
  50. package/src/utils/index.js +8 -1
  51. package/src/utils/jsxTranslations.js +8 -1
@@ -0,0 +1,467 @@
1
+ # Murphy Usage in Desk Client App
2
+
3
+ ## Overview
4
+
5
+ The desk client application provides utility wrappers around Murphy to standardize error tracking and logging across the codebase.
6
+
7
+ ---
8
+
9
+ ## Utility Wrappers
10
+
11
+ ```
12
+ +-------------------------------------------------------------------+
13
+ | MURPHY UTILITY WRAPPERS |
14
+ | Path: src/library/murphy/Utils.js |
15
+ +-------------------------------------------------------------------+
16
+ | |
17
+ | Error Tracking |
18
+ | +---------------------------------------------------------------+ |
19
+ | | deskCustomError(ErrorDetails, Message, envData) | |
20
+ | | +-- Wraps murphy.error() | |
21
+ | | +-- Adds custom tracking with murphy.addCustomTracking() | |
22
+ | | +-- Supports Error objects or plain objects | |
23
+ | | +-- Handles error details formatting | |
24
+ | +---------------------------------------------------------------+ |
25
+ | |
26
+ | Application Logging |
27
+ | +---------------------------------------------------------------+ |
28
+ | | deskLogger(info, details) | |
29
+ | | +-- Wraps murphy.appLog() | |
30
+ | | +-- Supports INFO, WARN, SEVERE levels | |
31
+ | | +-- Adds custom tags with _c_ prefix | |
32
+ | +---------------------------------------------------------------+ |
33
+ | |
34
+ | Performance Tracking |
35
+ | +---------------------------------------------------------------+ |
36
+ | | endInitialLoadForMurphyPerformanceLogs() | |
37
+ | | startSoftNavigationMurphyPerformanceLogs({ fromUrl, toUrl }) | |
38
+ | | endSoftNavigationMurphyPerformanceLogs() | |
39
+ | | setClientMetricTags(value) | |
40
+ | +---------------------------------------------------------------+ |
41
+ | |
42
+ | Presence Checks |
43
+ | +---------------------------------------------------------------+ |
44
+ | | isMurphyPresent() -> Check if murphy exists | |
45
+ | | isMurphyClientMetricsPresent() -> Check client metrics | |
46
+ | | isMurphyClientMetricsInstalled() -> Check if installed | |
47
+ | +---------------------------------------------------------------+ |
48
+ | |
49
+ +-------------------------------------------------------------------+
50
+ ```
51
+
52
+ ---
53
+
54
+ ## 1. Presence Checks
55
+
56
+ Before using Murphy, always check if it's available:
57
+
58
+ ```javascript
59
+ // Path: src/library/murphy/Utils.js
60
+
61
+ /**
62
+ * Check if Murphy SDK is loaded
63
+ */
64
+ export function isMurphyPresent() {
65
+ return typeof murphy !== 'undefined';
66
+ }
67
+
68
+ /**
69
+ * Check if Murphy client metrics and telemetry are available
70
+ */
71
+ export function isMurphyClientMetricsPresent() {
72
+ return (
73
+ isMurphyPresent() &&
74
+ typeof murphy.clientmetrics !== 'undefined' &&
75
+ typeof murphy.telemetry !== 'undefined'
76
+ );
77
+ }
78
+
79
+ /**
80
+ * Check if client metrics are installed
81
+ */
82
+ export function isMurphyClientMetricsInstalled() {
83
+ return murphy.clientmetrics.isClientMetricsInstalled();
84
+ }
85
+ ```
86
+
87
+ ---
88
+
89
+ ## 2. Error Tracking (deskCustomError)
90
+
91
+ The primary function for reporting errors:
92
+
93
+ ```javascript
94
+ /**
95
+ * Report custom error to Murphy
96
+ *
97
+ * @param {Object|Error} ErrorDetails - Error details or Error object
98
+ * @param {string} ErrorDisplayMessage - Human-readable error message
99
+ * @param {Object} envData - Additional environment/context data
100
+ */
101
+ export function deskCustomError(ErrorDetails, ErrorDisplayMessage, envData) {
102
+ try {
103
+ if (isMurphyPresent()) {
104
+ let error;
105
+
106
+ // Handle Error objects
107
+ if (ErrorDetails instanceof Error) {
108
+ error = ErrorDetails;
109
+ error.message = ErrorDisplayMessage
110
+ ? `${ErrorDisplayMessage} - ${error.message}`
111
+ : error.message || 'An error occurred';
112
+ } else {
113
+ // Create new Error from message
114
+ error = new Error(ErrorDisplayMessage || 'An error occurred');
115
+ }
116
+
117
+ // Add tracking data
118
+ murphy && murphy.addCustomTracking(ErrorDetails);
119
+
120
+ // Build custom tags
121
+ let customErrorDataObj;
122
+ if (envData && typeof envData === 'object') {
123
+ const { errorType, ...errorData } = envData;
124
+ customErrorDataObj = {
125
+ customTags: {
126
+ errordetail: errorData,
127
+ errortype: errorType
128
+ },
129
+ preventClientGrouping: true
130
+ };
131
+ }
132
+
133
+ // Report to Murphy
134
+ murphy && murphy.error(error, undefined, customErrorDataObj);
135
+ }
136
+ } catch (error) {
137
+ console.error('error in desk custom error', error);
138
+ }
139
+ }
140
+
141
+ // Also exposed globally for error handling
142
+ window._windowDeskCustomError = deskCustomError;
143
+ ```
144
+
145
+ ### Usage Examples
146
+
147
+ ```javascript
148
+ // Basic error reporting
149
+ deskCustomError(
150
+ { type: 'api_error', endpoint: '/tickets' },
151
+ 'Failed to load tickets'
152
+ );
153
+
154
+ // With Error object
155
+ try {
156
+ await saveTicket(data);
157
+ } catch (err) {
158
+ deskCustomError(err, 'Ticket save failed', {
159
+ errorType: 'save_error',
160
+ ticketId: data.id
161
+ });
162
+ }
163
+
164
+ // HTTP error tracking (resource load failure)
165
+ deskCustomError(
166
+ {
167
+ type: 'http',
168
+ category: 'xhr',
169
+ data: {
170
+ method: 'script',
171
+ url: loadFile,
172
+ status_code: 404
173
+ }
174
+ },
175
+ `Resource entry failed - ${JSON.stringify(loadFile)}`
176
+ );
177
+ ```
178
+
179
+ ---
180
+
181
+ ## 3. Application Logging (deskLogger)
182
+
183
+ Structured logging to Murphy:
184
+
185
+ ```javascript
186
+ import { LOG_LEVEL } from './Constants';
187
+
188
+ /**
189
+ * Send application logs to Murphy
190
+ *
191
+ * @param {string|Object} info - Log level/message or {type, message}
192
+ * @param {Object} details - Additional log details
193
+ */
194
+ export function deskLogger(info, details) {
195
+ if (isMurphyPresent()) {
196
+ let type;
197
+ let message;
198
+
199
+ // Handle object input
200
+ if (info && typeof info === 'object') {
201
+ ({ type = LOG_LEVEL.INFO, message } = info);
202
+ } else {
203
+ type = LOG_LEVEL.INFO;
204
+ message = info;
205
+ }
206
+
207
+ // Build custom tags with _c_ prefix
208
+ let customTagObj = {};
209
+ if (details && typeof details === 'object') {
210
+ Object.keys(details).forEach((key) => {
211
+ customTagObj[`_c_${key}`] = details[key];
212
+ });
213
+ }
214
+
215
+ // Send to Murphy
216
+ message && murphy.appLog(type, message, customTagObj);
217
+ }
218
+ }
219
+ ```
220
+
221
+ ### Log Levels
222
+
223
+ ```
224
+ +-----------------------------------+
225
+ | LOG_LEVEL Constants |
226
+ +-----------------------------------+
227
+ | INFO -> Informational logs |
228
+ | WARN -> Warning conditions |
229
+ | SEVERE -> Critical errors |
230
+ +-----------------------------------+
231
+ ```
232
+
233
+ ### Usage Examples
234
+
235
+ ```javascript
236
+ // Simple info log
237
+ deskLogger('User opened ticket detail view');
238
+
239
+ // With details
240
+ deskLogger('Ticket updated', {
241
+ ticketId: '12345',
242
+ field: 'status',
243
+ oldValue: 'Open',
244
+ newValue: 'Closed'
245
+ });
246
+
247
+ // With log level
248
+ deskLogger(
249
+ { type: LOG_LEVEL.WARN, message: 'Slow API response detected' },
250
+ { endpoint: '/tickets', duration: 5000 }
251
+ );
252
+ ```
253
+
254
+ ---
255
+
256
+ ## 4. Performance Tracking
257
+
258
+ ### Time to Interactive
259
+
260
+ ```javascript
261
+ /**
262
+ * Mark end of initial load
263
+ */
264
+ export function endInitialLoadForMurphyPerformanceLogs({
265
+ isCancelled = false,
266
+ ...value
267
+ } = {}) {
268
+ if (!isMurphyClientMetricsPresent()) {
269
+ return;
270
+ }
271
+
272
+ const modeOfOperation = isCancelled
273
+ ? 'Cancelled_route_navigation'
274
+ : 'Success_route_navigation';
275
+
276
+ setClientMetricTags({
277
+ routerState: modeOfOperation,
278
+ ...value
279
+ });
280
+
281
+ murphy.clientmetrics.setTimeToInteractive();
282
+ }
283
+ ```
284
+
285
+ ### Soft Navigation Tracking
286
+
287
+ ```javascript
288
+ /**
289
+ * Start tracking route change
290
+ */
291
+ export function startSoftNavigationMurphyPerformanceLogs({ fromUrl, toUrl }) {
292
+ if (!isMurphyClientMetricsPresent()) {
293
+ return;
294
+ }
295
+
296
+ murphy.clientmetrics.startSoftNavigation({
297
+ from_url: fromUrl,
298
+ to_url: toUrl,
299
+ from_normalised_url: fromUrl,
300
+ to_normalised_url: toUrl
301
+ });
302
+ }
303
+
304
+ /**
305
+ * End tracking route change
306
+ */
307
+ export function endSoftNavigationMurphyPerformanceLogs(isCancelled = false) {
308
+ if (!isMurphyClientMetricsPresent()) {
309
+ return;
310
+ }
311
+
312
+ const modeOfOperation = isCancelled
313
+ ? 'Cancelled_route_navigation'
314
+ : 'Success_route_navigation';
315
+
316
+ setClientMetricTags({
317
+ routerState: modeOfOperation
318
+ });
319
+
320
+ murphy.clientmetrics.endSoftNavigation();
321
+ }
322
+ ```
323
+
324
+ ### Usage in Router
325
+
326
+ ```javascript
327
+ // In route change handler
328
+ const handleRouteChange = (fromUrl, toUrl) => {
329
+ // Start tracking
330
+ startSoftNavigationMurphyPerformanceLogs({ fromUrl, toUrl });
331
+
332
+ // ... perform navigation ...
333
+
334
+ // End tracking when component mounts
335
+ endSoftNavigationMurphyPerformanceLogs();
336
+ };
337
+ ```
338
+
339
+ ---
340
+
341
+ ## 5. Failed Resource Tracking
342
+
343
+ Automatically tracks failed resource loads:
344
+
345
+ ```javascript
346
+ /**
347
+ * Monkey-patches document.createElement to track failed resources
348
+ */
349
+ export function failedResourcesEntry() {
350
+ if (isMurphyPresent()) {
351
+ document.createElement = (function (create) {
352
+ return function () {
353
+ var ret = create.apply(this, arguments);
354
+
355
+ if (
356
+ ret.tagName.toLowerCase() === 'script' ||
357
+ ret.tagName.toLowerCase() === 'link'
358
+ ) {
359
+ // Track load start time
360
+ ret.setAttribute('X-MURPHY-LOAD-START', Date.now());
361
+
362
+ // Handle successful load
363
+ ret.addEventListener('load', function () {
364
+ var loadFile = getLoadFile(this);
365
+ setCors(loadFile, ret);
366
+ });
367
+
368
+ // Handle failed load
369
+ ret.addEventListener('error', function () {
370
+ var loadFile = getLoadFile(this);
371
+
372
+ deskCustomError(
373
+ {
374
+ type: 'http',
375
+ category: 'xhr',
376
+ data: {
377
+ method: this.tagName.toLowerCase(),
378
+ url: loadFile,
379
+ startimestamp: this.getAttribute('X-MURPHY-LOAD-START'),
380
+ timeTaken: Date.now() - this.getAttribute('X-MURPHY-LOAD-START'),
381
+ status_code: 404
382
+ }
383
+ },
384
+ `Resource entry failed - ${JSON.stringify(loadFile)}`
385
+ );
386
+ });
387
+ }
388
+
389
+ return ret;
390
+ };
391
+ })(document.createElement);
392
+ }
393
+ }
394
+ ```
395
+
396
+ ---
397
+
398
+ ## Integration Pattern
399
+
400
+ ```
401
+ +-------------------------------------------------------------------+
402
+ | TYPICAL MURPHY INTEGRATION IN DESK CLIENT |
403
+ +-------------------------------------------------------------------+
404
+ | |
405
+ | Component/Module Code |
406
+ | +---------------------------------------------------------------+ |
407
+ | | import { | |
408
+ | | deskCustomError, | |
409
+ | | deskLogger | |
410
+ | | } from 'library/murphy/Utils'; | |
411
+ | | | |
412
+ | | async function saveTicket(data) { | |
413
+ | | try { | |
414
+ | | deskLogger('Saving ticket', { ticketId: data.id }); | |
415
+ | | await api.save(data); | |
416
+ | | deskLogger('Ticket saved successfully'); | |
417
+ | | } catch (error) { | |
418
+ | | deskCustomError(error, 'Failed to save ticket', { | |
419
+ | | errorType: 'api_error', | |
420
+ | | ticketId: data.id | |
421
+ | | }); | |
422
+ | | throw error; | |
423
+ | | } | |
424
+ | | } | |
425
+ | +---------------------------------------------------------------+ |
426
+ | |
427
+ +-------------------------------------------------------------------+
428
+ ```
429
+
430
+ ---
431
+
432
+ ## Summary
433
+
434
+ ```
435
+ +-------------------------------------------------------------------+
436
+ | DESK CLIENT MURPHY USAGE SUMMARY |
437
+ +-------------------------------------------------------------------+
438
+ | |
439
+ | Error Tracking: |
440
+ | +-- deskCustomError() -> Standardized error reporting |
441
+ | +-- Supports Error objects and plain objects |
442
+ | +-- Adds custom tags and tracking data |
443
+ | |
444
+ | Logging: |
445
+ | +-- deskLogger() -> Structured application logs |
446
+ | +-- Supports INFO, WARN, SEVERE levels |
447
+ | +-- Auto-prefixes custom tags with _c_ |
448
+ | |
449
+ | Performance: |
450
+ | +-- Initial load tracking |
451
+ | +-- Soft navigation tracking |
452
+ | +-- Resource load failure detection |
453
+ | |
454
+ | Safety: |
455
+ | +-- All functions check isMurphyPresent() first |
456
+ | +-- Graceful degradation if Murphy unavailable |
457
+ | |
458
+ +-------------------------------------------------------------------+
459
+ ```
460
+
461
+ ---
462
+
463
+ ## Related Documents
464
+
465
+ - [04-MURPHY_FRONTEND_INIT.md](./04-MURPHY_FRONTEND_INIT.md) - Frontend initialization
466
+ - [06-MURPHY_I18N_INTEGRATION.md](./06-MURPHY_I18N_INTEGRATION.md) - i18n library integration
467
+ - [07-MURPHY_WHY_I18N_APPROACH.md](./07-MURPHY_WHY_I18N_APPROACH.md) - Why i18n approach