react-visual-feedback 1.4.9 → 2.2.1

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,2907 @@
1
+ function _arrayLikeToArray(r, a) {
2
+ (null == a || a > r.length) && (a = r.length);
3
+ for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
4
+ return n;
5
+ }
6
+ function _arrayWithHoles(r) {
7
+ if (Array.isArray(r)) return r;
8
+ }
9
+ function _arrayWithoutHoles(r) {
10
+ if (Array.isArray(r)) return _arrayLikeToArray(r);
11
+ }
12
+ function _assertThisInitialized(e) {
13
+ if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
14
+ return e;
15
+ }
16
+ function asyncGeneratorStep(n, t, e, r, o, a, c) {
17
+ try {
18
+ var i = n[a](c),
19
+ u = i.value;
20
+ } catch (n) {
21
+ return void e(n);
22
+ }
23
+ i.done ? t(u) : Promise.resolve(u).then(r, o);
24
+ }
25
+ function _asyncToGenerator(n) {
26
+ return function () {
27
+ var t = this,
28
+ e = arguments;
29
+ return new Promise(function (r, o) {
30
+ var a = n.apply(t, e);
31
+ function _next(n) {
32
+ asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
33
+ }
34
+ function _throw(n) {
35
+ asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
36
+ }
37
+ _next(void 0);
38
+ });
39
+ };
40
+ }
41
+ function _callSuper(t, o, e) {
42
+ return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
43
+ }
44
+ function _classCallCheck(a, n) {
45
+ if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
46
+ }
47
+ function _defineProperties(e, r) {
48
+ for (var t = 0; t < r.length; t++) {
49
+ var o = r[t];
50
+ o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o);
51
+ }
52
+ }
53
+ function _createClass(e, r, t) {
54
+ return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", {
55
+ writable: false
56
+ }), e;
57
+ }
58
+ function _defineProperty(e, r, t) {
59
+ return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
60
+ value: t,
61
+ enumerable: true,
62
+ configurable: true,
63
+ writable: true
64
+ }) : e[r] = t, e;
65
+ }
66
+ function _getPrototypeOf(t) {
67
+ return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
68
+ return t.__proto__ || Object.getPrototypeOf(t);
69
+ }, _getPrototypeOf(t);
70
+ }
71
+ function _inherits(t, e) {
72
+ if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
73
+ t.prototype = Object.create(e && e.prototype, {
74
+ constructor: {
75
+ value: t,
76
+ writable: true,
77
+ configurable: true
78
+ }
79
+ }), Object.defineProperty(t, "prototype", {
80
+ writable: false
81
+ }), e && _setPrototypeOf(t, e);
82
+ }
83
+ function _isNativeReflectConstruct() {
84
+ try {
85
+ var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
86
+ } catch (t) {}
87
+ return (_isNativeReflectConstruct = function () {
88
+ return !!t;
89
+ })();
90
+ }
91
+ function _iterableToArray(r) {
92
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
93
+ }
94
+ function _iterableToArrayLimit(r, l) {
95
+ var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
96
+ if (null != t) {
97
+ var e,
98
+ n,
99
+ i,
100
+ u,
101
+ a = [],
102
+ f = true,
103
+ o = false;
104
+ try {
105
+ if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
106
+ } catch (r) {
107
+ o = true, n = r;
108
+ } finally {
109
+ try {
110
+ if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
111
+ } finally {
112
+ if (o) throw n;
113
+ }
114
+ }
115
+ return a;
116
+ }
117
+ }
118
+ function _nonIterableRest() {
119
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
120
+ }
121
+ function _nonIterableSpread() {
122
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
123
+ }
124
+ function ownKeys(e, r) {
125
+ var t = Object.keys(e);
126
+ if (Object.getOwnPropertySymbols) {
127
+ var o = Object.getOwnPropertySymbols(e);
128
+ r && (o = o.filter(function (r) {
129
+ return Object.getOwnPropertyDescriptor(e, r).enumerable;
130
+ })), t.push.apply(t, o);
131
+ }
132
+ return t;
133
+ }
134
+ function _objectSpread2(e) {
135
+ for (var r = 1; r < arguments.length; r++) {
136
+ var t = null != arguments[r] ? arguments[r] : {};
137
+ r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
138
+ _defineProperty(e, r, t[r]);
139
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
140
+ Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
141
+ });
142
+ }
143
+ return e;
144
+ }
145
+ function _possibleConstructorReturn(t, e) {
146
+ if (e && ("object" == typeof e || "function" == typeof e)) return e;
147
+ if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
148
+ return _assertThisInitialized(t);
149
+ }
150
+ function _regenerator() {
151
+ /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
152
+ var e,
153
+ t,
154
+ r = "function" == typeof Symbol ? Symbol : {},
155
+ n = r.iterator || "@@iterator",
156
+ o = r.toStringTag || "@@toStringTag";
157
+ function i(r, n, o, i) {
158
+ var c = n && n.prototype instanceof Generator ? n : Generator,
159
+ u = Object.create(c.prototype);
160
+ return _regeneratorDefine(u, "_invoke", function (r, n, o) {
161
+ var i,
162
+ c,
163
+ u,
164
+ f = 0,
165
+ p = o || [],
166
+ y = false,
167
+ G = {
168
+ p: 0,
169
+ n: 0,
170
+ v: e,
171
+ a: d,
172
+ f: d.bind(e, 4),
173
+ d: function (t, r) {
174
+ return i = t, c = 0, u = e, G.n = r, a;
175
+ }
176
+ };
177
+ function d(r, n) {
178
+ for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) {
179
+ var o,
180
+ i = p[t],
181
+ d = G.p,
182
+ l = i[2];
183
+ r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0));
184
+ }
185
+ if (o || r > 1) return a;
186
+ throw y = true, n;
187
+ }
188
+ return function (o, p, l) {
189
+ if (f > 1) throw TypeError("Generator is already running");
190
+ for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) {
191
+ i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u);
192
+ try {
193
+ if (f = 2, i) {
194
+ if (c || (o = "next"), t = i[o]) {
195
+ if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object");
196
+ if (!t.done) return t;
197
+ u = t.value, c < 2 && (c = 0);
198
+ } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1);
199
+ i = e;
200
+ } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break;
201
+ } catch (t) {
202
+ i = e, c = 1, u = t;
203
+ } finally {
204
+ f = 1;
205
+ }
206
+ }
207
+ return {
208
+ value: t,
209
+ done: y
210
+ };
211
+ };
212
+ }(r, o, i), true), u;
213
+ }
214
+ var a = {};
215
+ function Generator() {}
216
+ function GeneratorFunction() {}
217
+ function GeneratorFunctionPrototype() {}
218
+ t = Object.getPrototypeOf;
219
+ var c = [][n] ? t(t([][n]())) : (_regeneratorDefine(t = {}, n, function () {
220
+ return this;
221
+ }), t),
222
+ u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c);
223
+ function f(e) {
224
+ return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e;
225
+ }
226
+ return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine(u), _regeneratorDefine(u, o, "Generator"), _regeneratorDefine(u, n, function () {
227
+ return this;
228
+ }), _regeneratorDefine(u, "toString", function () {
229
+ return "[object Generator]";
230
+ }), (_regenerator = function () {
231
+ return {
232
+ w: i,
233
+ m: f
234
+ };
235
+ })();
236
+ }
237
+ function _regeneratorDefine(e, r, n, t) {
238
+ var i = Object.defineProperty;
239
+ try {
240
+ i({}, "", {});
241
+ } catch (e) {
242
+ i = 0;
243
+ }
244
+ _regeneratorDefine = function (e, r, n, t) {
245
+ function o(r, n) {
246
+ _regeneratorDefine(e, r, function (e) {
247
+ return this._invoke(r, n, e);
248
+ });
249
+ }
250
+ r ? i ? i(e, r, {
251
+ value: n,
252
+ enumerable: !t,
253
+ configurable: !t,
254
+ writable: !t
255
+ }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2));
256
+ }, _regeneratorDefine(e, r, n, t);
257
+ }
258
+ function _setPrototypeOf(t, e) {
259
+ return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
260
+ return t.__proto__ = e, t;
261
+ }, _setPrototypeOf(t, e);
262
+ }
263
+ function _slicedToArray(r, e) {
264
+ return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
265
+ }
266
+ function _toConsumableArray(r) {
267
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
268
+ }
269
+ function _toPrimitive(t, r) {
270
+ if ("object" != typeof t || !t) return t;
271
+ var e = t[Symbol.toPrimitive];
272
+ if (void 0 !== e) {
273
+ var i = e.call(t, r);
274
+ if ("object" != typeof i) return i;
275
+ throw new TypeError("@@toPrimitive must return a primitive value.");
276
+ }
277
+ return ("string" === r ? String : Number)(t);
278
+ }
279
+ function _toPropertyKey(t) {
280
+ var i = _toPrimitive(t, "string");
281
+ return "symbol" == typeof i ? i : i + "";
282
+ }
283
+ function _typeof(o) {
284
+ "@babel/helpers - typeof";
285
+
286
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
287
+ return typeof o;
288
+ } : function (o) {
289
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
290
+ }, _typeof(o);
291
+ }
292
+ function _unsupportedIterableToArray(r, a) {
293
+ if (r) {
294
+ if ("string" == typeof r) return _arrayLikeToArray(r, a);
295
+ var t = {}.toString.call(r).slice(8, -1);
296
+ return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
297
+ }
298
+ }
299
+
300
+ /**
301
+ * Integration Configuration & Default Mappings
302
+ * Users can customize these by passing their own config
303
+ */
304
+
305
+ // ============================================
306
+ // ATLASSIAN DOCUMENT FORMAT (ADF) HELPER
307
+ // ============================================
308
+
309
+ /**
310
+ * Convert plain text to Atlassian Document Format
311
+ * Jira Cloud requires descriptions in ADF format
312
+ */
313
+ function textToADF(text) {
314
+ var lines = text.split('\n');
315
+ var content = [];
316
+ var currentParagraph = [];
317
+ var flushParagraph = function flushParagraph() {
318
+ if (currentParagraph.length > 0) {
319
+ content.push({
320
+ type: 'paragraph',
321
+ content: currentParagraph
322
+ });
323
+ currentParagraph = [];
324
+ }
325
+ };
326
+ lines.forEach(function (line, index) {
327
+ // Check if it's a section header (ALL CAPS)
328
+ if (line.match(/^[A-Z][A-Z\s]+$/) && line.trim().length > 0) {
329
+ flushParagraph();
330
+ content.push({
331
+ type: 'heading',
332
+ attrs: {
333
+ level: 3
334
+ },
335
+ content: [{
336
+ type: 'text',
337
+ text: line
338
+ }]
339
+ });
340
+ } else if (line === '---') {
341
+ // Horizontal rule
342
+ flushParagraph();
343
+ content.push({
344
+ type: 'rule'
345
+ });
346
+ } else if (line.trim() === '') {
347
+ // Empty line - flush paragraph
348
+ flushParagraph();
349
+ } else {
350
+ // Regular line
351
+ if (currentParagraph.length > 0) {
352
+ currentParagraph.push({
353
+ type: 'hardBreak'
354
+ });
355
+ }
356
+ currentParagraph.push({
357
+ type: 'text',
358
+ text: line
359
+ });
360
+ }
361
+ });
362
+ flushParagraph();
363
+ return {
364
+ type: 'doc',
365
+ version: 1,
366
+ content: content.length > 0 ? content : [{
367
+ type: 'paragraph',
368
+ content: [{
369
+ type: 'text',
370
+ text: ' '
371
+ }]
372
+ }]
373
+ };
374
+ }
375
+
376
+ // ============================================
377
+ // GOOGLE SHEETS COLUMN MAPPING
378
+ // ============================================
379
+
380
+ var DEFAULT_SHEET_COLUMNS = {
381
+ timestamp: {
382
+ key: 'timestamp',
383
+ header: 'Timestamp',
384
+ field: 'timestamp',
385
+ transform: function transform(value) {
386
+ return value || new Date().toISOString();
387
+ }
388
+ },
389
+ id: {
390
+ key: 'id',
391
+ header: 'Feedback ID',
392
+ field: 'id'
393
+ },
394
+ feedback: {
395
+ key: 'feedback',
396
+ header: 'Feedback',
397
+ field: 'feedback'
398
+ },
399
+ type: {
400
+ key: 'type',
401
+ header: 'Type',
402
+ field: 'type',
403
+ transform: function transform(value) {
404
+ return value || 'bug';
405
+ }
406
+ },
407
+ status: {
408
+ key: 'status',
409
+ header: 'Status',
410
+ field: 'status',
411
+ transform: function transform(value) {
412
+ return value || 'new';
413
+ }
414
+ },
415
+ userName: {
416
+ key: 'userName',
417
+ header: 'User Name',
418
+ field: 'userName',
419
+ transform: function transform(value) {
420
+ return value || 'Anonymous';
421
+ }
422
+ },
423
+ userEmail: {
424
+ key: 'userEmail',
425
+ header: 'User Email',
426
+ field: 'userEmail',
427
+ transform: function transform(value) {
428
+ return value || '';
429
+ }
430
+ },
431
+ url: {
432
+ key: 'url',
433
+ header: 'Page URL',
434
+ field: 'url'
435
+ },
436
+ viewport: {
437
+ key: 'viewport',
438
+ header: 'Viewport',
439
+ field: 'viewport',
440
+ transform: function transform(value) {
441
+ return value ? "".concat(value.width, "x").concat(value.height) : '';
442
+ }
443
+ },
444
+ userAgent: {
445
+ key: 'userAgent',
446
+ header: 'Browser',
447
+ field: 'userAgent',
448
+ transform: function transform(value) {
449
+ if (!value) return '';
450
+ // Simplify user agent
451
+ if (value.includes('Chrome')) return 'Chrome';
452
+ if (value.includes('Firefox')) return 'Firefox';
453
+ if (value.includes('Safari')) return 'Safari';
454
+ if (value.includes('Edge')) return 'Edge';
455
+ return value.substring(0, 50);
456
+ }
457
+ },
458
+ screenshot: {
459
+ key: 'screenshot',
460
+ header: 'Screenshot',
461
+ field: 'screenshot',
462
+ transform: function transform(value) {
463
+ return value ? 'Yes' : 'No';
464
+ } // Don't store base64 in sheets
465
+ },
466
+ video: {
467
+ key: 'video',
468
+ header: 'Video',
469
+ field: 'video',
470
+ transform: function transform(value) {
471
+ return value ? 'Yes' : 'No';
472
+ }
473
+ },
474
+ elementSelector: {
475
+ key: 'elementSelector',
476
+ header: 'Element',
477
+ field: 'elementInfo',
478
+ transform: function transform(value) {
479
+ return (value === null || value === void 0 ? void 0 : value.selector) || '';
480
+ }
481
+ },
482
+ componentName: {
483
+ key: 'componentName',
484
+ header: 'Component',
485
+ field: 'elementInfo',
486
+ transform: function transform(value) {
487
+ var _value$componentStack;
488
+ return (value === null || value === void 0 || (_value$componentStack = value.componentStack) === null || _value$componentStack === void 0 ? void 0 : _value$componentStack[0]) || '';
489
+ }
490
+ },
491
+ sourceFile: {
492
+ key: 'sourceFile',
493
+ header: 'Source File',
494
+ field: 'elementInfo',
495
+ transform: function transform(value) {
496
+ return (value === null || value === void 0 ? void 0 : value.sourceFile) || '';
497
+ }
498
+ },
499
+ jiraKey: {
500
+ key: 'jiraKey',
501
+ header: 'Jira Issue',
502
+ field: 'jiraKey',
503
+ transform: function transform(value) {
504
+ return value || '';
505
+ }
506
+ }
507
+ };
508
+
509
+ // Default columns to include (order matters)
510
+ var DEFAULT_SHEET_COLUMN_ORDER = ['timestamp', 'id', 'feedback', 'type', 'status', 'userName', 'userEmail', 'url', 'viewport', 'screenshot', 'video', 'jiraKey'];
511
+
512
+ // ============================================
513
+ // JIRA FIELD MAPPING
514
+ // ============================================
515
+
516
+ var DEFAULT_JIRA_FIELDS = {
517
+ summary: {
518
+ key: 'summary',
519
+ source: 'feedback',
520
+ maxLength: 255,
521
+ prefix: '[Feedback] ',
522
+ transform: function transform(data) {
523
+ var prefix = '[Feedback] ';
524
+ var text = data.feedback || 'User Feedback';
525
+ var maxLen = 255 - prefix.length;
526
+ return prefix + (text.length > maxLen ? text.substring(0, maxLen - 3) + '...' : text);
527
+ }
528
+ },
529
+ description: {
530
+ key: 'description',
531
+ // Build description directly - no wiki markup, clean plain text for ADF
532
+ transform: function transform(data) {
533
+ var lines = [];
534
+
535
+ // Feedback Details
536
+ lines.push('FEEDBACK DETAILS');
537
+ lines.push("Feedback: ".concat(data.feedback || 'No feedback provided'));
538
+ lines.push("Type: ".concat(data.type || 'bug'));
539
+ lines.push("Status: ".concat(data.status || 'new'));
540
+ lines.push('');
541
+
542
+ // User Information
543
+ lines.push('USER INFORMATION');
544
+ lines.push("Name: ".concat(data.userName || 'Anonymous'));
545
+ lines.push("Email: ".concat(data.userEmail || 'Not provided'));
546
+ lines.push('');
547
+
548
+ // Technical Details
549
+ lines.push('TECHNICAL DETAILS');
550
+ lines.push("Page URL: ".concat(data.url || 'N/A'));
551
+ if (data.viewport) {
552
+ lines.push("Viewport: ".concat(data.viewport.width, "x").concat(data.viewport.height));
553
+ }
554
+ if (data.userAgent) {
555
+ // Simplify user agent
556
+ var browser = data.userAgent;
557
+ if (browser.includes('Chrome')) browser = 'Chrome';else if (browser.includes('Firefox')) browser = 'Firefox';else if (browser.includes('Safari')) browser = 'Safari';else if (browser.includes('Edge')) browser = 'Edge';
558
+ lines.push("Browser: ".concat(browser));
559
+ }
560
+
561
+ // Element info
562
+ if (data.elementInfo) {
563
+ var _data$elementInfo$com;
564
+ if (data.elementInfo.selector) {
565
+ lines.push("Element: ".concat(data.elementInfo.selector));
566
+ }
567
+ if ((_data$elementInfo$com = data.elementInfo.componentStack) !== null && _data$elementInfo$com !== void 0 && _data$elementInfo$com.length) {
568
+ lines.push("Component: ".concat(data.elementInfo.componentStack.join(' > ')));
569
+ }
570
+ if (data.elementInfo.sourceFile) {
571
+ lines.push("Source: ".concat(data.elementInfo.sourceFile, ":").concat(data.elementInfo.lineNumber || ''));
572
+ }
573
+ }
574
+ lines.push('');
575
+
576
+ // Attachments
577
+ var attachments = [];
578
+ if (data.screenshot) attachments.push('Screenshot');
579
+ if (data.video) attachments.push('Screen Recording');
580
+ if (attachments.length > 0) {
581
+ lines.push('ATTACHMENTS');
582
+ lines.push(attachments.join(', ') + ' attached');
583
+ lines.push('');
584
+ }
585
+ lines.push('---');
586
+ lines.push('Submitted via React Visual Feedback');
587
+ return lines.join('\n');
588
+ }
589
+ },
590
+ issuetype: {
591
+ key: 'issuetype',
592
+ // Default to 'Task' which exists in most Jira projects
593
+ // Can be overridden via JIRA_ISSUE_TYPE env var or config
594
+ value: 'Task',
595
+ // Map feedback types to Jira issue types (all default to Task for compatibility)
596
+ typeMapping: {
597
+ bug: 'Task',
598
+ feature: 'Task',
599
+ improvement: 'Task',
600
+ question: 'Task',
601
+ other: 'Task'
602
+ },
603
+ transform: function transform(data, config) {
604
+ var _process$env;
605
+ // Priority: env var > config value > type mapping > default
606
+ var envIssueType = typeof process !== 'undefined' ? (_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.JIRA_ISSUE_TYPE : null;
607
+ if (envIssueType) return envIssueType;
608
+ if (config !== null && config !== void 0 && config.value && config.value !== 'Task') return config.value;
609
+ var mapping = (config === null || config === void 0 ? void 0 : config.typeMapping) || DEFAULT_JIRA_FIELDS.issuetype.typeMapping;
610
+ return mapping[data.type] || (config === null || config === void 0 ? void 0 : config.value) || 'Task';
611
+ }
612
+ },
613
+ labels: {
614
+ key: 'labels',
615
+ value: ['user-feedback'],
616
+ transform: function transform(data, config) {
617
+ var labels = _toConsumableArray((config === null || config === void 0 ? void 0 : config.value) || ['user-feedback']);
618
+ if (data.type) labels.push("type-".concat(data.type));
619
+ return labels;
620
+ }
621
+ },
622
+ priority: {
623
+ key: 'priority',
624
+ // Map to Jira priority IDs (user can customize)
625
+ priorityMapping: {
626
+ bug: 'High',
627
+ feature: 'Medium',
628
+ improvement: 'Medium',
629
+ question: 'Low',
630
+ other: 'Low'
631
+ },
632
+ transform: function transform(data, config) {
633
+ var mapping = (config === null || config === void 0 ? void 0 : config.priorityMapping) || DEFAULT_JIRA_FIELDS.priority.priorityMapping;
634
+ return mapping[data.type] || 'Medium';
635
+ }
636
+ }
637
+ };
638
+
639
+ // ============================================
640
+ // JIRA STATUS MAPPING (Bidirectional sync)
641
+ // ============================================
642
+
643
+ var DEFAULT_JIRA_STATUS_MAPPING = {
644
+ // Our status -> Jira status
645
+ toJira: {
646
+ "new": 'To Do',
647
+ open: 'To Do',
648
+ inProgress: 'In Progress',
649
+ underReview: 'In Review',
650
+ onHold: 'On Hold',
651
+ resolved: 'Done',
652
+ closed: 'Done',
653
+ wontFix: 'Won\'t Do'
654
+ },
655
+ // Jira status -> Our status
656
+ fromJira: {
657
+ 'To Do': 'open',
658
+ 'Open': 'open',
659
+ 'In Progress': 'inProgress',
660
+ 'In Review': 'underReview',
661
+ 'On Hold': 'onHold',
662
+ 'Done': 'resolved',
663
+ 'Closed': 'closed',
664
+ 'Won\'t Do': 'wontFix',
665
+ 'Resolved': 'resolved'
666
+ }
667
+ };
668
+
669
+ // ============================================
670
+ // INTEGRATION TYPES
671
+ // ============================================
672
+
673
+ var INTEGRATION_TYPES = {
674
+ JIRA: {
675
+ SERVER: 'server',
676
+ // Our server handler
677
+ AUTOMATION: 'jira-automation',
678
+ // Jira's built-in webhooks
679
+ ZAPIER: 'zapier' // Zapier webhook
680
+ },
681
+ SHEETS: {
682
+ SERVER: 'server',
683
+ // Our server handler (Service Account)
684
+ OAUTH: 'oauth',
685
+ // OAuth with refresh
686
+ APPS_SCRIPT: 'google-apps-script',
687
+ // Google Apps Script
688
+ ZAPIER: 'zapier' // Zapier webhook
689
+ }
690
+ };
691
+
692
+ // ============================================
693
+ // HELPER FUNCTIONS
694
+ // ============================================
695
+
696
+ /**
697
+ * Merge user config with defaults
698
+ */
699
+ function mergeSheetColumns() {
700
+ var userColumns = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
701
+ var columnOrder = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
702
+ var merged = _objectSpread2({}, DEFAULT_SHEET_COLUMNS);
703
+
704
+ // Apply user overrides
705
+ Object.entries(userColumns).forEach(function (_ref) {
706
+ var _ref2 = _slicedToArray(_ref, 2),
707
+ key = _ref2[0],
708
+ value = _ref2[1];
709
+ if (value === null || value === false) {
710
+ // Remove column
711
+ delete merged[key];
712
+ } else if (_typeof(value) === 'object') {
713
+ // Merge with default
714
+ merged[key] = _objectSpread2(_objectSpread2({}, merged[key]), value);
715
+ }
716
+ });
717
+
718
+ // Determine column order
719
+ var order = columnOrder || Object.keys(merged).filter(function (k) {
720
+ return DEFAULT_SHEET_COLUMN_ORDER.includes(k) || userColumns[k];
721
+ });
722
+ return {
723
+ columns: merged,
724
+ order: order
725
+ };
726
+ }
727
+
728
+ /**
729
+ * Merge user Jira config with defaults
730
+ */
731
+ function mergeJiraFields() {
732
+ var userFields = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
733
+ var merged = _objectSpread2({}, DEFAULT_JIRA_FIELDS);
734
+ Object.entries(userFields).forEach(function (_ref3) {
735
+ var _ref4 = _slicedToArray(_ref3, 2),
736
+ key = _ref4[0],
737
+ value = _ref4[1];
738
+ if (value === null || value === false) {
739
+ delete merged[key];
740
+ } else if (_typeof(value) === 'object') {
741
+ merged[key] = _objectSpread2(_objectSpread2({}, merged[key]), value);
742
+ }
743
+ });
744
+ return merged;
745
+ }
746
+
747
+ /**
748
+ * Transform feedback data to sheet row
749
+ */
750
+ function feedbackToSheetRow(feedbackData) {
751
+ var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
752
+ var _mergeSheetColumns = mergeSheetColumns(config.columns, config.columnOrder),
753
+ columns = _mergeSheetColumns.columns,
754
+ order = _mergeSheetColumns.order;
755
+ var row = order.map(function (key) {
756
+ var col = columns[key];
757
+ if (!col) return '';
758
+ var rawValue = feedbackData[col.field];
759
+ if (col.transform) {
760
+ return col.transform(rawValue) || '';
761
+ }
762
+ return rawValue || '';
763
+ });
764
+ return row;
765
+ }
766
+
767
+ /**
768
+ * Get sheet headers
769
+ */
770
+ function getSheetHeaders() {
771
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
772
+ var _mergeSheetColumns2 = mergeSheetColumns(config.columns, config.columnOrder),
773
+ columns = _mergeSheetColumns2.columns,
774
+ order = _mergeSheetColumns2.order;
775
+ return order.map(function (key) {
776
+ var _columns$key;
777
+ return ((_columns$key = columns[key]) === null || _columns$key === void 0 ? void 0 : _columns$key.header) || key;
778
+ });
779
+ }
780
+
781
+ /**
782
+ * Transform feedback data to Jira issue
783
+ */
784
+ function feedbackToJiraIssue(feedbackData) {
785
+ var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
786
+ var fields = mergeJiraFields(config.fields);
787
+
788
+ // Get plain text description and convert to ADF
789
+ var plainDescription = fields.description.transform(feedbackData, fields.description);
790
+ var adfDescription = textToADF(plainDescription);
791
+ var issue = {
792
+ fields: {
793
+ project: {
794
+ key: config.projectKey
795
+ },
796
+ summary: fields.summary.transform(feedbackData, fields.summary),
797
+ description: adfDescription,
798
+ issuetype: {
799
+ name: fields.issuetype.transform(feedbackData, fields.issuetype)
800
+ }
801
+ }
802
+ };
803
+
804
+ // Add labels if configured
805
+ if (fields.labels) {
806
+ issue.fields.labels = fields.labels.transform(feedbackData, fields.labels);
807
+ }
808
+
809
+ // Add priority if configured and user wants it
810
+ if (config.includePriority && fields.priority) {
811
+ issue.fields.priority = {
812
+ name: fields.priority.transform(feedbackData, fields.priority)
813
+ };
814
+ }
815
+
816
+ // Add custom fields
817
+ if (config.customFields) {
818
+ Object.entries(config.customFields).forEach(function (_ref5) {
819
+ var _ref6 = _slicedToArray(_ref5, 2),
820
+ fieldId = _ref6[0],
821
+ fieldConfig = _ref6[1];
822
+ if (typeof fieldConfig === 'string') {
823
+ issue.fields[fieldId] = feedbackData[fieldConfig];
824
+ } else if (fieldConfig.transform) {
825
+ issue.fields[fieldId] = fieldConfig.transform(feedbackData);
826
+ } else if (fieldConfig.value) {
827
+ issue.fields[fieldId] = fieldConfig.value;
828
+ }
829
+ });
830
+ }
831
+ return issue;
832
+ }
833
+
834
+ /**
835
+ * Map Jira status to our status
836
+ */
837
+ function mapJiraStatusToLocal(jiraStatus) {
838
+ var customMapping = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
839
+ var mapping = _objectSpread2(_objectSpread2({}, DEFAULT_JIRA_STATUS_MAPPING.fromJira), customMapping);
840
+ return mapping[jiraStatus] || 'open';
841
+ }
842
+
843
+ /**
844
+ * Map our status to Jira status
845
+ */
846
+ function mapLocalStatusToJira(localStatus) {
847
+ var customMapping = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
848
+ var mapping = _objectSpread2(_objectSpread2({}, DEFAULT_JIRA_STATUS_MAPPING.toJira), customMapping);
849
+ return mapping[localStatus] || 'To Do';
850
+ }
851
+
852
+ // ============================================
853
+ // HELPER FUNCTIONS
854
+ // ============================================
855
+
856
+ /**
857
+ * Format event logs as a readable text file
858
+ */
859
+ function formatEventLogs(eventLogs) {
860
+ if (!eventLogs || eventLogs.length === 0) {
861
+ return 'No event logs recorded.';
862
+ }
863
+ var lines = ['═══════════════════════════════════════════════════════════════', ' SESSION EVENT LOGS', '═══════════════════════════════════════════════════════════════', "Generated: ".concat(new Date().toISOString()), "Total Events: ".concat(eventLogs.length), '═══════════════════════════════════════════════════════════════', ''];
864
+ eventLogs.forEach(function (event, index) {
865
+ var _event$request, _event$response;
866
+ var timestamp = event.timestamp ? "[".concat((event.timestamp / 1000).toFixed(2), "s]") : '[--]';
867
+ switch (event.type) {
868
+ case 'console':
869
+ lines.push("".concat(timestamp, " [CONSOLE.").concat((event.level || 'log').toUpperCase(), "]"));
870
+ lines.push(" ".concat(event.message || 'No message'));
871
+ break;
872
+ case 'network':
873
+ var status = event.status || 'pending';
874
+ var duration = event.duration ? "(".concat(event.duration, "ms)") : '';
875
+ lines.push("".concat(timestamp, " [NETWORK] ").concat(event.method || 'GET', " ").concat(event.url));
876
+ lines.push(" Status: ".concat(status, " ").concat(duration));
877
+ if ((_event$request = event.request) !== null && _event$request !== void 0 && _event$request.body && event.request.body !== 'null' && event.request.body !== 'undefined') {
878
+ lines.push(" Request: ".concat(event.request.body.substring(0, 200)).concat(event.request.body.length > 200 ? '...' : ''));
879
+ }
880
+ if ((_event$response = event.response) !== null && _event$response !== void 0 && _event$response.body && event.response.body !== 'null' && event.response.body !== 'undefined') {
881
+ lines.push(" Response: ".concat(event.response.body.substring(0, 200)).concat(event.response.body.length > 200 ? '...' : ''));
882
+ }
883
+ break;
884
+ case 'storage':
885
+ lines.push("".concat(timestamp, " [").concat((event.storageType || 'storage').toUpperCase(), "] ").concat(event.action));
886
+ if (event.key) lines.push(" Key: ".concat(event.key));
887
+ if (event.value) lines.push(" Value: ".concat(event.value.substring(0, 100)).concat(event.value.length > 100 ? '...' : ''));
888
+ break;
889
+ case 'indexedDB':
890
+ lines.push("".concat(timestamp, " [INDEXEDDB] ").concat(event.action, " on ").concat(event.dbName || 'unknown').concat(event.storeName ? '.' + event.storeName : ''));
891
+ if (event.data) lines.push(" Data: ".concat(event.data.substring(0, 100)).concat(event.data.length > 100 ? '...' : ''));
892
+ break;
893
+ default:
894
+ lines.push("".concat(timestamp, " [").concat((event.type || 'EVENT').toUpperCase(), "]"));
895
+ lines.push(" ".concat(JSON.stringify(event).substring(0, 200)));
896
+ }
897
+ lines.push(''); // Empty line between events
898
+ });
899
+ lines.push('═══════════════════════════════════════════════════════════════');
900
+ lines.push(' END OF LOGS');
901
+ lines.push('═══════════════════════════════════════════════════════════════');
902
+ return lines.join('\n');
903
+ }
904
+
905
+ // ============================================
906
+ // JIRA API CLIENT
907
+ // ============================================
908
+ var JiraClient = /*#__PURE__*/function () {
909
+ function JiraClient(config) {
910
+ _classCallCheck(this, JiraClient);
911
+ var domain = config.domain || process.env.JIRA_DOMAIN;
912
+ this.email = config.email || process.env.JIRA_EMAIL;
913
+ this.apiToken = config.apiToken || process.env.JIRA_API_TOKEN;
914
+ this.projectKey = config.projectKey || process.env.JIRA_PROJECT_KEY;
915
+ if (!domain || !this.email || !this.apiToken) {
916
+ throw new Error('Jira configuration missing. Required: JIRA_DOMAIN, JIRA_EMAIL, JIRA_API_TOKEN');
917
+ }
918
+
919
+ // Strip protocol and trailing slashes from domain
920
+ this.domain = domain.replace(/^https?:\/\//, '').replace(/\/+$/, '');
921
+ this.baseUrl = "https://".concat(this.domain, "/rest/api/3");
922
+ this.authHeader = 'Basic ' + Buffer.from("".concat(this.email, ":").concat(this.apiToken)).toString('base64');
923
+ }
924
+ return _createClass(JiraClient, [{
925
+ key: "request",
926
+ value: function () {
927
+ var _request = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(endpoint) {
928
+ var options,
929
+ url,
930
+ response,
931
+ error,
932
+ text,
933
+ _args = arguments;
934
+ return _regenerator().w(function (_context) {
935
+ while (1) switch (_context.n) {
936
+ case 0:
937
+ options = _args.length > 1 && _args[1] !== undefined ? _args[1] : {};
938
+ url = "".concat(this.baseUrl).concat(endpoint);
939
+ _context.n = 1;
940
+ return fetch(url, _objectSpread2(_objectSpread2({}, options), {}, {
941
+ headers: _objectSpread2({
942
+ 'Authorization': this.authHeader,
943
+ 'Content-Type': 'application/json',
944
+ 'Accept': 'application/json'
945
+ }, options.headers)
946
+ }));
947
+ case 1:
948
+ response = _context.v;
949
+ if (response.ok) {
950
+ _context.n = 3;
951
+ break;
952
+ }
953
+ _context.n = 2;
954
+ return response.text();
955
+ case 2:
956
+ error = _context.v;
957
+ throw new Error("Jira API error (".concat(response.status, "): ").concat(error));
958
+ case 3:
959
+ _context.n = 4;
960
+ return response.text();
961
+ case 4:
962
+ text = _context.v;
963
+ return _context.a(2, text ? JSON.parse(text) : null);
964
+ }
965
+ }, _callee, this);
966
+ }));
967
+ function request(_x) {
968
+ return _request.apply(this, arguments);
969
+ }
970
+ return request;
971
+ }()
972
+ /**
973
+ * Create a new issue
974
+ */
975
+ }, {
976
+ key: "createIssue",
977
+ value: (function () {
978
+ var _createIssue = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(issueData) {
979
+ return _regenerator().w(function (_context2) {
980
+ while (1) switch (_context2.n) {
981
+ case 0:
982
+ return _context2.a(2, this.request('/issue', {
983
+ method: 'POST',
984
+ body: JSON.stringify(issueData)
985
+ }));
986
+ }
987
+ }, _callee2, this);
988
+ }));
989
+ function createIssue(_x2) {
990
+ return _createIssue.apply(this, arguments);
991
+ }
992
+ return createIssue;
993
+ }()
994
+ /**
995
+ * Get issue details
996
+ */
997
+ )
998
+ }, {
999
+ key: "getIssue",
1000
+ value: (function () {
1001
+ var _getIssue = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(issueKey) {
1002
+ return _regenerator().w(function (_context3) {
1003
+ while (1) switch (_context3.n) {
1004
+ case 0:
1005
+ return _context3.a(2, this.request("/issue/".concat(issueKey)));
1006
+ }
1007
+ }, _callee3, this);
1008
+ }));
1009
+ function getIssue(_x3) {
1010
+ return _getIssue.apply(this, arguments);
1011
+ }
1012
+ return getIssue;
1013
+ }()
1014
+ /**
1015
+ * Update issue status via transition
1016
+ */
1017
+ )
1018
+ }, {
1019
+ key: "transitionIssue",
1020
+ value: (function () {
1021
+ var _transitionIssue = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(issueKey, transitionName) {
1022
+ var transitions, transition;
1023
+ return _regenerator().w(function (_context4) {
1024
+ while (1) switch (_context4.n) {
1025
+ case 0:
1026
+ _context4.n = 1;
1027
+ return this.request("/issue/".concat(issueKey, "/transitions"));
1028
+ case 1:
1029
+ transitions = _context4.v;
1030
+ transition = transitions.transitions.find(function (t) {
1031
+ return t.name.toLowerCase() === transitionName.toLowerCase() || t.to.name.toLowerCase() === transitionName.toLowerCase();
1032
+ });
1033
+ if (transition) {
1034
+ _context4.n = 2;
1035
+ break;
1036
+ }
1037
+ throw new Error("Transition \"".concat(transitionName, "\" not found for issue ").concat(issueKey));
1038
+ case 2:
1039
+ _context4.n = 3;
1040
+ return this.request("/issue/".concat(issueKey, "/transitions"), {
1041
+ method: 'POST',
1042
+ body: JSON.stringify({
1043
+ transition: {
1044
+ id: transition.id
1045
+ }
1046
+ })
1047
+ });
1048
+ case 3:
1049
+ return _context4.a(2, {
1050
+ success: true,
1051
+ transitionId: transition.id
1052
+ });
1053
+ }
1054
+ }, _callee4, this);
1055
+ }));
1056
+ function transitionIssue(_x4, _x5) {
1057
+ return _transitionIssue.apply(this, arguments);
1058
+ }
1059
+ return transitionIssue;
1060
+ }()
1061
+ /**
1062
+ * Add attachment to issue
1063
+ */
1064
+ )
1065
+ }, {
1066
+ key: "addAttachment",
1067
+ value: (function () {
1068
+ var _addAttachment = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(issueKey, filename, content, contentType) {
1069
+ var url, buffer, commaIndex, base64Data, boundary, formData, response, error;
1070
+ return _regenerator().w(function (_context5) {
1071
+ while (1) switch (_context5.n) {
1072
+ case 0:
1073
+ url = "".concat(this.baseUrl, "/issue/").concat(issueKey, "/attachments"); // Convert content to buffer
1074
+ if (!Buffer.isBuffer(content)) {
1075
+ _context5.n = 1;
1076
+ break;
1077
+ }
1078
+ // Already a buffer
1079
+ buffer = content;
1080
+ _context5.n = 8;
1081
+ break;
1082
+ case 1:
1083
+ if (!(typeof content === 'string')) {
1084
+ _context5.n = 6;
1085
+ break;
1086
+ }
1087
+ if (!content.startsWith('data:')) {
1088
+ _context5.n = 4;
1089
+ break;
1090
+ }
1091
+ // Data URL format: data:video/webm;base64,AAAA...
1092
+ commaIndex = content.indexOf(',');
1093
+ if (!(commaIndex !== -1)) {
1094
+ _context5.n = 2;
1095
+ break;
1096
+ }
1097
+ base64Data = content.substring(commaIndex + 1);
1098
+ buffer = Buffer.from(base64Data, 'base64');
1099
+ _context5.n = 3;
1100
+ break;
1101
+ case 2:
1102
+ throw new Error('Invalid data URL format - missing comma separator');
1103
+ case 3:
1104
+ _context5.n = 5;
1105
+ break;
1106
+ case 4:
1107
+ // Assume raw base64 string
1108
+ buffer = Buffer.from(content, 'base64');
1109
+ case 5:
1110
+ _context5.n = 8;
1111
+ break;
1112
+ case 6:
1113
+ if (!(content instanceof Uint8Array)) {
1114
+ _context5.n = 7;
1115
+ break;
1116
+ }
1117
+ buffer = Buffer.from(content);
1118
+ _context5.n = 8;
1119
+ break;
1120
+ case 7:
1121
+ throw new Error("Unsupported content type: ".concat(_typeof(content)));
1122
+ case 8:
1123
+ if (!(!buffer || buffer.length === 0)) {
1124
+ _context5.n = 9;
1125
+ break;
1126
+ }
1127
+ throw new Error('Attachment content is empty');
1128
+ case 9:
1129
+ // Create form data manually for Node.js
1130
+ boundary = '----FormBoundary' + Math.random().toString(36).substring(2);
1131
+ formData = Buffer.concat([Buffer.from("--".concat(boundary, "\r\n") + "Content-Disposition: form-data; name=\"file\"; filename=\"".concat(filename, "\"\r\n") + "Content-Type: ".concat(contentType, "\r\n\r\n")), buffer, Buffer.from("\r\n--".concat(boundary, "--\r\n"))]);
1132
+ _context5.n = 10;
1133
+ return fetch(url, {
1134
+ method: 'POST',
1135
+ headers: {
1136
+ 'Authorization': this.authHeader,
1137
+ 'X-Atlassian-Token': 'no-check',
1138
+ 'Content-Type': "multipart/form-data; boundary=".concat(boundary)
1139
+ },
1140
+ body: formData
1141
+ });
1142
+ case 10:
1143
+ response = _context5.v;
1144
+ if (response.ok) {
1145
+ _context5.n = 12;
1146
+ break;
1147
+ }
1148
+ _context5.n = 11;
1149
+ return response.text();
1150
+ case 11:
1151
+ error = _context5.v;
1152
+ throw new Error("Failed to upload attachment (".concat(response.status, "): ").concat(error));
1153
+ case 12:
1154
+ return _context5.a(2, response.json());
1155
+ }
1156
+ }, _callee5, this);
1157
+ }));
1158
+ function addAttachment(_x6, _x7, _x8, _x9) {
1159
+ return _addAttachment.apply(this, arguments);
1160
+ }
1161
+ return addAttachment;
1162
+ }()
1163
+ /**
1164
+ * Add comment to issue
1165
+ */
1166
+ )
1167
+ }, {
1168
+ key: "addComment",
1169
+ value: (function () {
1170
+ var _addComment = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(issueKey, comment) {
1171
+ return _regenerator().w(function (_context6) {
1172
+ while (1) switch (_context6.n) {
1173
+ case 0:
1174
+ return _context6.a(2, this.request("/issue/".concat(issueKey, "/comment"), {
1175
+ method: 'POST',
1176
+ body: JSON.stringify({
1177
+ body: {
1178
+ type: 'doc',
1179
+ version: 1,
1180
+ content: [{
1181
+ type: 'paragraph',
1182
+ content: [{
1183
+ type: 'text',
1184
+ text: comment
1185
+ }]
1186
+ }]
1187
+ }
1188
+ })
1189
+ }));
1190
+ }
1191
+ }, _callee6, this);
1192
+ }));
1193
+ function addComment(_x0, _x1) {
1194
+ return _addComment.apply(this, arguments);
1195
+ }
1196
+ return addComment;
1197
+ }()
1198
+ /**
1199
+ * Get issue status
1200
+ */
1201
+ )
1202
+ }, {
1203
+ key: "getIssueStatus",
1204
+ value: (function () {
1205
+ var _getIssueStatus = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(issueKey) {
1206
+ var issue;
1207
+ return _regenerator().w(function (_context7) {
1208
+ while (1) switch (_context7.n) {
1209
+ case 0:
1210
+ _context7.n = 1;
1211
+ return this.getIssue(issueKey);
1212
+ case 1:
1213
+ issue = _context7.v;
1214
+ return _context7.a(2, issue.fields.status.name);
1215
+ }
1216
+ }, _callee7, this);
1217
+ }));
1218
+ function getIssueStatus(_x10) {
1219
+ return _getIssueStatus.apply(this, arguments);
1220
+ }
1221
+ return getIssueStatus;
1222
+ }())
1223
+ }]);
1224
+ }(); // ============================================
1225
+ // REQUEST HANDLERS
1226
+ // ============================================
1227
+ /**
1228
+ * Parse multipart form data from request
1229
+ * Works with Next.js App Router, Pages Router, and Express
1230
+ */
1231
+ function parseFormData(_x11) {
1232
+ return _parseFormData.apply(this, arguments);
1233
+ }
1234
+ /**
1235
+ * Create Jira handler with configuration
1236
+ */
1237
+ function _parseFormData() {
1238
+ _parseFormData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1(req) {
1239
+ var _req$headers, _req$headers$get, _req$headers2, contentType, body, formData, action, metadataStr, metadata, screenshot, video, eventLogs, feedbackData, arrayBuffer, _arrayBuffer, text, _body;
1240
+ return _regenerator().w(function (_context1) {
1241
+ while (1) switch (_context1.n) {
1242
+ case 0:
1243
+ if (!(typeof req.json === 'function' || typeof req.formData === 'function')) {
1244
+ _context1.n = 10;
1245
+ break;
1246
+ }
1247
+ // Check Content-Type to determine how to parse
1248
+ contentType = ((_req$headers = req.headers) === null || _req$headers === void 0 || (_req$headers$get = _req$headers.get) === null || _req$headers$get === void 0 ? void 0 : _req$headers$get.call(_req$headers, 'content-type')) || ((_req$headers2 = req.headers) === null || _req$headers2 === void 0 ? void 0 : _req$headers2['content-type']) || ''; // Handle JSON requests (e.g., getStatus, updateStatus)
1249
+ if (!contentType.includes('application/json')) {
1250
+ _context1.n = 2;
1251
+ break;
1252
+ }
1253
+ _context1.n = 1;
1254
+ return req.json();
1255
+ case 1:
1256
+ body = _context1.v;
1257
+ return _context1.a(2, {
1258
+ action: body.action || 'create',
1259
+ feedbackData: body.feedbackData || body,
1260
+ issueKey: body.issueKey,
1261
+ status: body.status,
1262
+ comment: body.comment
1263
+ });
1264
+ case 2:
1265
+ if (!(typeof req.formData === 'function')) {
1266
+ _context1.n = 10;
1267
+ break;
1268
+ }
1269
+ _context1.n = 3;
1270
+ return req.formData();
1271
+ case 3:
1272
+ formData = _context1.v;
1273
+ action = formData.get('action') || 'create';
1274
+ metadataStr = formData.get('metadata');
1275
+ metadata = metadataStr ? JSON.parse(metadataStr) : {}; // Get files
1276
+ screenshot = formData.get('screenshot');
1277
+ video = formData.get('video');
1278
+ eventLogs = formData.get('eventLogs'); // Convert files to buffers
1279
+ feedbackData = _objectSpread2({}, metadata);
1280
+ if (!(screenshot && screenshot instanceof Blob)) {
1281
+ _context1.n = 5;
1282
+ break;
1283
+ }
1284
+ _context1.n = 4;
1285
+ return screenshot.arrayBuffer();
1286
+ case 4:
1287
+ arrayBuffer = _context1.v;
1288
+ feedbackData.screenshotBuffer = Buffer.from(arrayBuffer);
1289
+ feedbackData.screenshotType = screenshot.type || 'image/png';
1290
+ case 5:
1291
+ if (!(video && video instanceof Blob)) {
1292
+ _context1.n = 7;
1293
+ break;
1294
+ }
1295
+ _context1.n = 6;
1296
+ return video.arrayBuffer();
1297
+ case 6:
1298
+ _arrayBuffer = _context1.v;
1299
+ feedbackData.videoBuffer = Buffer.from(_arrayBuffer);
1300
+ feedbackData.videoType = video.type || 'video/webm';
1301
+ feedbackData.videoSize = video.size;
1302
+ case 7:
1303
+ if (!(eventLogs && eventLogs instanceof Blob)) {
1304
+ _context1.n = 9;
1305
+ break;
1306
+ }
1307
+ _context1.n = 8;
1308
+ return eventLogs.text();
1309
+ case 8:
1310
+ text = _context1.v;
1311
+ try {
1312
+ feedbackData.eventLogs = JSON.parse(text);
1313
+ } catch (e) {
1314
+ feedbackData.eventLogs = [];
1315
+ }
1316
+ case 9:
1317
+ return _context1.a(2, {
1318
+ action: action,
1319
+ feedbackData: feedbackData
1320
+ });
1321
+ case 10:
1322
+ if (!req.body) {
1323
+ _context1.n = 11;
1324
+ break;
1325
+ }
1326
+ _body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
1327
+ return _context1.a(2, {
1328
+ action: _body.action || 'create',
1329
+ feedbackData: _body.feedbackData || _body,
1330
+ issueKey: _body.issueKey,
1331
+ status: _body.status,
1332
+ comment: _body.comment
1333
+ });
1334
+ case 11:
1335
+ throw new Error('Unable to parse request body');
1336
+ case 12:
1337
+ return _context1.a(2);
1338
+ }
1339
+ }, _callee1);
1340
+ }));
1341
+ return _parseFormData.apply(this, arguments);
1342
+ }
1343
+ function createJiraHandler() {
1344
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1345
+ var handler = /*#__PURE__*/function () {
1346
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8(req, res) {
1347
+ var _yield$parseFormData, _yield$parseFormData$, action, feedbackData, issueKey, status, comment, client, result, errorResponse, _t, _t2;
1348
+ return _regenerator().w(function (_context8) {
1349
+ while (1) switch (_context8.p = _context8.n) {
1350
+ case 0:
1351
+ _context8.p = 0;
1352
+ _context8.n = 1;
1353
+ return parseFormData(req);
1354
+ case 1:
1355
+ _yield$parseFormData = _context8.v;
1356
+ _yield$parseFormData$ = _yield$parseFormData.action;
1357
+ action = _yield$parseFormData$ === void 0 ? 'create' : _yield$parseFormData$;
1358
+ feedbackData = _yield$parseFormData.feedbackData;
1359
+ issueKey = _yield$parseFormData.issueKey;
1360
+ status = _yield$parseFormData.status;
1361
+ comment = _yield$parseFormData.comment;
1362
+ client = new JiraClient(config);
1363
+ _t = action;
1364
+ _context8.n = _t === 'create' ? 2 : _t === 'updateStatus' ? 4 : _t === 'getStatus' ? 6 : _t === 'addComment' ? 8 : 10;
1365
+ break;
1366
+ case 2:
1367
+ _context8.n = 3;
1368
+ return handleCreate(client, feedbackData, config);
1369
+ case 3:
1370
+ result = _context8.v;
1371
+ return _context8.a(3, 11);
1372
+ case 4:
1373
+ _context8.n = 5;
1374
+ return handleStatusUpdate(client, issueKey, status, config);
1375
+ case 5:
1376
+ result = _context8.v;
1377
+ return _context8.a(3, 11);
1378
+ case 6:
1379
+ _context8.n = 7;
1380
+ return handleGetStatus(client, issueKey, config);
1381
+ case 7:
1382
+ result = _context8.v;
1383
+ return _context8.a(3, 11);
1384
+ case 8:
1385
+ _context8.n = 9;
1386
+ return handleAddComment(client, issueKey, comment);
1387
+ case 9:
1388
+ result = _context8.v;
1389
+ return _context8.a(3, 11);
1390
+ case 10:
1391
+ throw new Error("Unknown action: ".concat(action));
1392
+ case 11:
1393
+ if (!(res !== null && res !== void 0 && res.json)) {
1394
+ _context8.n = 12;
1395
+ break;
1396
+ }
1397
+ res.status(200).json(result);
1398
+ _context8.n = 13;
1399
+ break;
1400
+ case 12:
1401
+ return _context8.a(2, new Response(JSON.stringify(result), {
1402
+ status: 200,
1403
+ headers: {
1404
+ 'Content-Type': 'application/json'
1405
+ }
1406
+ }));
1407
+ case 13:
1408
+ _context8.n = 16;
1409
+ break;
1410
+ case 14:
1411
+ _context8.p = 14;
1412
+ _t2 = _context8.v;
1413
+ errorResponse = {
1414
+ success: false,
1415
+ error: _t2.message
1416
+ };
1417
+ if (!(res !== null && res !== void 0 && res.json)) {
1418
+ _context8.n = 15;
1419
+ break;
1420
+ }
1421
+ res.status(500).json(errorResponse);
1422
+ _context8.n = 16;
1423
+ break;
1424
+ case 15:
1425
+ return _context8.a(2, new Response(JSON.stringify(errorResponse), {
1426
+ status: 500,
1427
+ headers: {
1428
+ 'Content-Type': 'application/json'
1429
+ }
1430
+ }));
1431
+ case 16:
1432
+ return _context8.a(2);
1433
+ }
1434
+ }, _callee8, null, [[0, 14]]);
1435
+ }));
1436
+ return function handler(_x12, _x13) {
1437
+ return _ref.apply(this, arguments);
1438
+ };
1439
+ }();
1440
+ return handler;
1441
+ }
1442
+
1443
+ /**
1444
+ * Handle issue creation
1445
+ */
1446
+ function handleCreate(_x14, _x15, _x16) {
1447
+ return _handleCreate.apply(this, arguments);
1448
+ }
1449
+ /**
1450
+ * Handle status update (local -> Jira)
1451
+ */
1452
+ function _handleCreate() {
1453
+ _handleCreate = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10(client, feedbackData, config) {
1454
+ var issueData, issue, issueKey, attachments, result, _result, videoType, extension, _result2, videoData, _videoType, _extension, _result3, logsText, logsBuffer, _result4, debugInfo, _t4, _t5, _t6, _t7, _t8;
1455
+ return _regenerator().w(function (_context10) {
1456
+ while (1) switch (_context10.p = _context10.n) {
1457
+ case 0:
1458
+ // Transform feedback to Jira issue format
1459
+ issueData = feedbackToJiraIssue(feedbackData, {
1460
+ projectKey: config.projectKey || client.projectKey,
1461
+ fields: config.fields,
1462
+ customFields: config.customFields,
1463
+ includePriority: config.includePriority
1464
+ }); // Create the issue
1465
+ _context10.n = 1;
1466
+ return client.createIssue(issueData);
1467
+ case 1:
1468
+ issue = _context10.v;
1469
+ issueKey = issue.key; // Upload attachments
1470
+ attachments = []; // Handle screenshot - support both Buffer (from FormData) and base64 string
1471
+ if (!(config.uploadAttachments !== false)) {
1472
+ _context10.n = 10;
1473
+ break;
1474
+ }
1475
+ if (!feedbackData.screenshotBuffer) {
1476
+ _context10.n = 6;
1477
+ break;
1478
+ }
1479
+ _context10.p = 2;
1480
+ _context10.n = 3;
1481
+ return client.addAttachment(issueKey, "screenshot-".concat(feedbackData.id || Date.now(), ".png"), feedbackData.screenshotBuffer, feedbackData.screenshotType || 'image/png');
1482
+ case 3:
1483
+ result = _context10.v;
1484
+ attachments.push(_objectSpread2({
1485
+ type: 'screenshot'
1486
+ }, result[0]));
1487
+ _context10.n = 5;
1488
+ break;
1489
+ case 4:
1490
+ _context10.p = 4;
1491
+ _t4 = _context10.v;
1492
+ attachments.push({
1493
+ type: 'screenshot',
1494
+ error: _t4.message
1495
+ });
1496
+ case 5:
1497
+ _context10.n = 10;
1498
+ break;
1499
+ case 6:
1500
+ if (!(feedbackData.screenshot && typeof feedbackData.screenshot === 'string')) {
1501
+ _context10.n = 10;
1502
+ break;
1503
+ }
1504
+ _context10.p = 7;
1505
+ _context10.n = 8;
1506
+ return client.addAttachment(issueKey, "screenshot-".concat(feedbackData.id || Date.now(), ".png"), feedbackData.screenshot, 'image/png');
1507
+ case 8:
1508
+ _result = _context10.v;
1509
+ attachments.push(_objectSpread2({
1510
+ type: 'screenshot'
1511
+ }, _result[0]));
1512
+ _context10.n = 10;
1513
+ break;
1514
+ case 9:
1515
+ _context10.p = 9;
1516
+ _t5 = _context10.v;
1517
+ attachments.push({
1518
+ type: 'screenshot',
1519
+ error: _t5.message
1520
+ });
1521
+ case 10:
1522
+ if (!(config.uploadAttachments !== false)) {
1523
+ _context10.n = 21;
1524
+ break;
1525
+ }
1526
+ if (!feedbackData.videoBuffer) {
1527
+ _context10.n = 15;
1528
+ break;
1529
+ }
1530
+ _context10.p = 11;
1531
+ videoType = feedbackData.videoType || 'video/webm';
1532
+ extension = videoType.includes('mp4') ? 'mp4' : 'webm';
1533
+ _context10.n = 12;
1534
+ return client.addAttachment(issueKey, "recording-".concat(feedbackData.id || Date.now(), ".").concat(extension), feedbackData.videoBuffer, videoType);
1535
+ case 12:
1536
+ _result2 = _context10.v;
1537
+ attachments.push(_objectSpread2({
1538
+ type: 'video',
1539
+ size: feedbackData.videoSize || feedbackData.videoBuffer.length
1540
+ }, _result2[0]));
1541
+ _context10.n = 14;
1542
+ break;
1543
+ case 13:
1544
+ _context10.p = 13;
1545
+ _t6 = _context10.v;
1546
+ attachments.push({
1547
+ type: 'video',
1548
+ error: _t6.message
1549
+ });
1550
+ case 14:
1551
+ _context10.n = 21;
1552
+ break;
1553
+ case 15:
1554
+ if (!(feedbackData.video && typeof feedbackData.video === 'string')) {
1555
+ _context10.n = 21;
1556
+ break;
1557
+ }
1558
+ _context10.p = 16;
1559
+ videoData = feedbackData.video;
1560
+ if (videoData.startsWith('data:')) {
1561
+ _context10.n = 17;
1562
+ break;
1563
+ }
1564
+ throw new Error('Video data is not a valid data URL');
1565
+ case 17:
1566
+ if (!(videoData.length < 1000)) {
1567
+ _context10.n = 18;
1568
+ break;
1569
+ }
1570
+ throw new Error("Video data appears truncated (only ".concat(videoData.length, " chars)"));
1571
+ case 18:
1572
+ _videoType = 'video/webm';
1573
+ _extension = 'webm';
1574
+ if (videoData.includes('video/mp4')) {
1575
+ _videoType = 'video/mp4';
1576
+ _extension = 'mp4';
1577
+ }
1578
+ _context10.n = 19;
1579
+ return client.addAttachment(issueKey, "recording-".concat(feedbackData.id || Date.now(), ".").concat(_extension), videoData, _videoType);
1580
+ case 19:
1581
+ _result3 = _context10.v;
1582
+ attachments.push(_objectSpread2({
1583
+ type: 'video'
1584
+ }, _result3[0]));
1585
+ _context10.n = 21;
1586
+ break;
1587
+ case 20:
1588
+ _context10.p = 20;
1589
+ _t7 = _context10.v;
1590
+ attachments.push({
1591
+ type: 'video',
1592
+ error: _t7.message
1593
+ });
1594
+ case 21:
1595
+ if (!(feedbackData.eventLogs && feedbackData.eventLogs.length > 0 && config.uploadAttachments !== false)) {
1596
+ _context10.n = 25;
1597
+ break;
1598
+ }
1599
+ _context10.p = 22;
1600
+ logsText = formatEventLogs(feedbackData.eventLogs);
1601
+ logsBuffer = Buffer.from(logsText, 'utf-8');
1602
+ _context10.n = 23;
1603
+ return client.addAttachment(issueKey, "session-logs-".concat(feedbackData.id || Date.now(), ".txt"), logsBuffer, 'text/plain');
1604
+ case 23:
1605
+ _result4 = _context10.v;
1606
+ attachments.push(_objectSpread2({
1607
+ type: 'logs'
1608
+ }, _result4[0]));
1609
+ _context10.n = 25;
1610
+ break;
1611
+ case 24:
1612
+ _context10.p = 24;
1613
+ _t8 = _context10.v;
1614
+ attachments.push({
1615
+ type: 'logs',
1616
+ error: _t8.message
1617
+ });
1618
+ case 25:
1619
+ // Include debug info
1620
+ debugInfo = {
1621
+ videoBufferReceived: !!feedbackData.videoBuffer,
1622
+ videoBufferSize: feedbackData.videoBuffer ? feedbackData.videoBuffer.length : 0,
1623
+ videoBase64Received: !!feedbackData.video,
1624
+ videoBase64Length: feedbackData.video ? feedbackData.video.length : 0,
1625
+ screenshotBufferReceived: !!feedbackData.screenshotBuffer,
1626
+ eventLogsCount: feedbackData.eventLogs ? feedbackData.eventLogs.length : 0
1627
+ };
1628
+ return _context10.a(2, {
1629
+ success: true,
1630
+ issueKey: issueKey,
1631
+ issueId: issue.id,
1632
+ issueUrl: "https://".concat(client.domain, "/browse/").concat(issueKey),
1633
+ attachments: attachments,
1634
+ debug: debugInfo
1635
+ });
1636
+ }
1637
+ }, _callee10, null, [[22, 24], [16, 20], [11, 13], [7, 9], [2, 4]]);
1638
+ }));
1639
+ return _handleCreate.apply(this, arguments);
1640
+ }
1641
+ function handleStatusUpdate(_x17, _x18, _x19, _x20) {
1642
+ return _handleStatusUpdate.apply(this, arguments);
1643
+ }
1644
+ /**
1645
+ * Handle get status (Jira -> local)
1646
+ */
1647
+ function _handleStatusUpdate() {
1648
+ _handleStatusUpdate = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee11(client, issueKey, localStatus, config) {
1649
+ var _config$statusMapping;
1650
+ var jiraStatus;
1651
+ return _regenerator().w(function (_context11) {
1652
+ while (1) switch (_context11.n) {
1653
+ case 0:
1654
+ jiraStatus = mapLocalStatusToJira(localStatus, (_config$statusMapping = config.statusMapping) === null || _config$statusMapping === void 0 ? void 0 : _config$statusMapping.toJira);
1655
+ _context11.n = 1;
1656
+ return client.transitionIssue(issueKey, jiraStatus);
1657
+ case 1:
1658
+ return _context11.a(2, {
1659
+ success: true,
1660
+ issueKey: issueKey,
1661
+ newStatus: jiraStatus
1662
+ });
1663
+ }
1664
+ }, _callee11);
1665
+ }));
1666
+ return _handleStatusUpdate.apply(this, arguments);
1667
+ }
1668
+ function handleGetStatus(_x21, _x22, _x23) {
1669
+ return _handleGetStatus.apply(this, arguments);
1670
+ }
1671
+ /**
1672
+ * Handle add comment
1673
+ */
1674
+ function _handleGetStatus() {
1675
+ _handleGetStatus = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee12(client, issueKey, config) {
1676
+ var _config$statusMapping2;
1677
+ var jiraStatus, localStatus;
1678
+ return _regenerator().w(function (_context12) {
1679
+ while (1) switch (_context12.n) {
1680
+ case 0:
1681
+ _context12.n = 1;
1682
+ return client.getIssueStatus(issueKey);
1683
+ case 1:
1684
+ jiraStatus = _context12.v;
1685
+ localStatus = mapJiraStatusToLocal(jiraStatus, (_config$statusMapping2 = config.statusMapping) === null || _config$statusMapping2 === void 0 ? void 0 : _config$statusMapping2.fromJira);
1686
+ return _context12.a(2, {
1687
+ success: true,
1688
+ issueKey: issueKey,
1689
+ jiraStatus: jiraStatus,
1690
+ localStatus: localStatus
1691
+ });
1692
+ }
1693
+ }, _callee12);
1694
+ }));
1695
+ return _handleGetStatus.apply(this, arguments);
1696
+ }
1697
+ function handleAddComment(_x24, _x25, _x26) {
1698
+ return _handleAddComment.apply(this, arguments);
1699
+ } // ============================================
1700
+ // FRAMEWORK-SPECIFIC EXPORTS
1701
+ // ============================================
1702
+ /**
1703
+ * Next.js App Router handler
1704
+ * Returns a function that can be directly exported as POST
1705
+ */
1706
+ function _handleAddComment() {
1707
+ _handleAddComment = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee13(client, issueKey, comment) {
1708
+ return _regenerator().w(function (_context13) {
1709
+ while (1) switch (_context13.n) {
1710
+ case 0:
1711
+ _context13.n = 1;
1712
+ return client.addComment(issueKey, comment);
1713
+ case 1:
1714
+ return _context13.a(2, {
1715
+ success: true,
1716
+ issueKey: issueKey
1717
+ });
1718
+ }
1719
+ }, _callee13);
1720
+ }));
1721
+ return _handleAddComment.apply(this, arguments);
1722
+ }
1723
+ function createNextAppHandler$1() {
1724
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1725
+ var handler = createJiraHandler(config);
1726
+ return /*#__PURE__*/function () {
1727
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9(request) {
1728
+ return _regenerator().w(function (_context9) {
1729
+ while (1) switch (_context9.n) {
1730
+ case 0:
1731
+ return _context9.a(2, handler(request, null));
1732
+ }
1733
+ }, _callee9);
1734
+ }));
1735
+ return function (_x27) {
1736
+ return _ref2.apply(this, arguments);
1737
+ };
1738
+ }();
1739
+ }
1740
+
1741
+ /**
1742
+ * Next.js Pages Router handler
1743
+ */
1744
+ function createNextPagesHandler$1() {
1745
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1746
+ return createJiraHandler(config);
1747
+ }
1748
+
1749
+ /**
1750
+ * Express middleware
1751
+ */
1752
+ function createExpressMiddleware$1() {
1753
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1754
+ var handler = createJiraHandler(config);
1755
+ return /*#__PURE__*/function () {
1756
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0(req, res, next) {
1757
+ var _t3;
1758
+ return _regenerator().w(function (_context0) {
1759
+ while (1) switch (_context0.p = _context0.n) {
1760
+ case 0:
1761
+ _context0.p = 0;
1762
+ _context0.n = 1;
1763
+ return handler(req, res);
1764
+ case 1:
1765
+ _context0.n = 3;
1766
+ break;
1767
+ case 2:
1768
+ _context0.p = 2;
1769
+ _t3 = _context0.v;
1770
+ next(_t3);
1771
+ case 3:
1772
+ return _context0.a(2);
1773
+ }
1774
+ }, _callee0, null, [[0, 2]]);
1775
+ }));
1776
+ return function (_x28, _x29, _x30) {
1777
+ return _ref3.apply(this, arguments);
1778
+ };
1779
+ }();
1780
+ }
1781
+
1782
+ /**
1783
+ * Generic handler for any framework
1784
+ */
1785
+ function createGenericHandler() {
1786
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1787
+ return createJiraHandler(config);
1788
+ }
1789
+
1790
+ // ============================================
1791
+ // WEBHOOK HANDLERS (For Jira Automation / Zapier)
1792
+ // ============================================
1793
+
1794
+ /**
1795
+ * Format feedback for Jira Automation webhook
1796
+ */
1797
+ function formatForJiraAutomation(feedbackData) {
1798
+ var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1799
+ return {
1800
+ summary: "[Feedback] ".concat((feedbackData.feedback || '').substring(0, 200)),
1801
+ description: feedbackToJiraIssue(feedbackData, config).fields.description,
1802
+ type: feedbackData.type || 'bug',
1803
+ userName: feedbackData.userName || 'Anonymous',
1804
+ userEmail: feedbackData.userEmail || '',
1805
+ url: feedbackData.url || '',
1806
+ hasScreenshot: !!feedbackData.screenshot,
1807
+ hasVideo: !!feedbackData.video,
1808
+ timestamp: feedbackData.timestamp || new Date().toISOString()
1809
+ };
1810
+ }
1811
+
1812
+ /**
1813
+ * Format feedback for Zapier webhook
1814
+ */
1815
+ function formatForZapier$1(feedbackData) {
1816
+ var _feedbackData$element, _feedbackData$element2, _feedbackData$element3;
1817
+ return {
1818
+ id: feedbackData.id,
1819
+ feedback: feedbackData.feedback,
1820
+ type: feedbackData.type,
1821
+ status: feedbackData.status,
1822
+ user_name: feedbackData.userName,
1823
+ user_email: feedbackData.userEmail,
1824
+ page_url: feedbackData.url,
1825
+ viewport: feedbackData.viewport ? "".concat(feedbackData.viewport.width, "x").concat(feedbackData.viewport.height) : '',
1826
+ has_screenshot: !!feedbackData.screenshot,
1827
+ has_video: !!feedbackData.video,
1828
+ element_selector: ((_feedbackData$element = feedbackData.elementInfo) === null || _feedbackData$element === void 0 ? void 0 : _feedbackData$element.selector) || '',
1829
+ component_name: (((_feedbackData$element2 = feedbackData.elementInfo) === null || _feedbackData$element2 === void 0 ? void 0 : _feedbackData$element2.componentStack) || [])[0] || '',
1830
+ source_file: ((_feedbackData$element3 = feedbackData.elementInfo) === null || _feedbackData$element3 === void 0 ? void 0 : _feedbackData$element3.sourceFile) || '',
1831
+ timestamp: feedbackData.timestamp || new Date().toISOString()
1832
+ };
1833
+ }
1834
+
1835
+ var jira = /*#__PURE__*/Object.freeze({
1836
+ __proto__: null,
1837
+ createExpressMiddleware: createExpressMiddleware$1,
1838
+ createGenericHandler: createGenericHandler,
1839
+ createJiraHandler: createJiraHandler,
1840
+ createNextAppHandler: createNextAppHandler$1,
1841
+ createNextPagesHandler: createNextPagesHandler$1,
1842
+ default: createJiraHandler,
1843
+ formatForJiraAutomation: formatForJiraAutomation,
1844
+ formatForZapier: formatForZapier$1
1845
+ });
1846
+
1847
+ // ============================================
1848
+ // GOOGLE SHEETS CLIENT (Service Account)
1849
+ // ============================================
1850
+ var SheetsClient = /*#__PURE__*/function () {
1851
+ function SheetsClient(config) {
1852
+ _classCallCheck(this, SheetsClient);
1853
+ this.spreadsheetId = config.spreadsheetId || process.env.GOOGLE_SPREADSHEET_ID;
1854
+ this.sheetName = config.sheetName || 'Feedback';
1855
+
1856
+ // Service Account credentials
1857
+ var credentials = config.credentials || process.env.GOOGLE_SERVICE_ACCOUNT;
1858
+ if (!credentials) {
1859
+ throw new Error('Google credentials missing. Set GOOGLE_SERVICE_ACCOUNT environment variable.');
1860
+ }
1861
+ this.credentials = typeof credentials === 'string' ? JSON.parse(credentials) : credentials;
1862
+ if (!this.spreadsheetId) {
1863
+ throw new Error('Spreadsheet ID missing. Set GOOGLE_SPREADSHEET_ID environment variable.');
1864
+ }
1865
+ this.accessToken = null;
1866
+ this.tokenExpiry = null;
1867
+ }
1868
+
1869
+ /**
1870
+ * Get access token using Service Account JWT
1871
+ */
1872
+ return _createClass(SheetsClient, [{
1873
+ key: "getAccessToken",
1874
+ value: (function () {
1875
+ var _getAccessToken = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
1876
+ var _this$credentials, client_email, private_key, header, now, payload, jwt, response, error, data;
1877
+ return _regenerator().w(function (_context) {
1878
+ while (1) switch (_context.n) {
1879
+ case 0:
1880
+ if (!(this.accessToken && this.tokenExpiry && Date.now() < this.tokenExpiry)) {
1881
+ _context.n = 1;
1882
+ break;
1883
+ }
1884
+ return _context.a(2, this.accessToken);
1885
+ case 1:
1886
+ _this$credentials = this.credentials, client_email = _this$credentials.client_email, private_key = _this$credentials.private_key; // Create JWT
1887
+ header = {
1888
+ alg: 'RS256',
1889
+ typ: 'JWT'
1890
+ };
1891
+ now = Math.floor(Date.now() / 1000);
1892
+ payload = {
1893
+ iss: client_email,
1894
+ scope: 'https://www.googleapis.com/auth/spreadsheets',
1895
+ aud: 'https://oauth2.googleapis.com/token',
1896
+ exp: now + 3600,
1897
+ iat: now
1898
+ };
1899
+ _context.n = 2;
1900
+ return this.createJWT(header, payload, private_key);
1901
+ case 2:
1902
+ jwt = _context.v;
1903
+ _context.n = 3;
1904
+ return fetch('https://oauth2.googleapis.com/token', {
1905
+ method: 'POST',
1906
+ headers: {
1907
+ 'Content-Type': 'application/x-www-form-urlencoded'
1908
+ },
1909
+ body: new URLSearchParams({
1910
+ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
1911
+ assertion: jwt
1912
+ })
1913
+ });
1914
+ case 3:
1915
+ response = _context.v;
1916
+ if (response.ok) {
1917
+ _context.n = 5;
1918
+ break;
1919
+ }
1920
+ _context.n = 4;
1921
+ return response.text();
1922
+ case 4:
1923
+ error = _context.v;
1924
+ throw new Error("Failed to get access token: ".concat(error));
1925
+ case 5:
1926
+ _context.n = 6;
1927
+ return response.json();
1928
+ case 6:
1929
+ data = _context.v;
1930
+ this.accessToken = data.access_token;
1931
+ this.tokenExpiry = Date.now() + (data.expires_in - 60) * 1000; // Refresh 1 min early
1932
+ return _context.a(2, this.accessToken);
1933
+ }
1934
+ }, _callee, this);
1935
+ }));
1936
+ function getAccessToken() {
1937
+ return _getAccessToken.apply(this, arguments);
1938
+ }
1939
+ return getAccessToken;
1940
+ }()
1941
+ /**
1942
+ * Create JWT for Service Account auth
1943
+ */
1944
+ )
1945
+ }, {
1946
+ key: "createJWT",
1947
+ value: (function () {
1948
+ var _createJWT = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(header, payload, privateKey) {
1949
+ var headerB64, payloadB64, signatureInput, pemHeader, pemFooter, pemContents, crypto, sign, signature, signatureB64;
1950
+ return _regenerator().w(function (_context2) {
1951
+ while (1) switch (_context2.n) {
1952
+ case 0:
1953
+ new TextEncoder();
1954
+ headerB64 = this.base64UrlEncode(JSON.stringify(header));
1955
+ payloadB64 = this.base64UrlEncode(JSON.stringify(payload));
1956
+ signatureInput = "".concat(headerB64, ".").concat(payloadB64); // Import private key
1957
+ pemHeader = '-----BEGIN PRIVATE KEY-----';
1958
+ pemFooter = '-----END PRIVATE KEY-----';
1959
+ pemContents = privateKey.replace(pemHeader, '').replace(pemFooter, '').replace(/\s/g, '');
1960
+ Buffer.from(pemContents, 'base64'); // Use Node.js crypto for signing
1961
+ _context2.n = 1;
1962
+ return import('crypto');
1963
+ case 1:
1964
+ crypto = _context2.v;
1965
+ sign = crypto.createSign('RSA-SHA256');
1966
+ sign.update(signatureInput);
1967
+ sign.end();
1968
+ signature = sign.sign({
1969
+ key: privateKey,
1970
+ padding: crypto.constants.RSA_PKCS1_PADDING
1971
+ });
1972
+ signatureB64 = this.base64UrlEncode(signature);
1973
+ return _context2.a(2, "".concat(signatureInput, ".").concat(signatureB64));
1974
+ }
1975
+ }, _callee2, this);
1976
+ }));
1977
+ function createJWT(_x, _x2, _x3) {
1978
+ return _createJWT.apply(this, arguments);
1979
+ }
1980
+ return createJWT;
1981
+ }())
1982
+ }, {
1983
+ key: "base64UrlEncode",
1984
+ value: function base64UrlEncode(data) {
1985
+ typeof data === 'string' ? data : Buffer.from(data).toString('base64');
1986
+ return Buffer.from(data).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
1987
+ }
1988
+
1989
+ /**
1990
+ * Make authenticated request to Sheets API
1991
+ */
1992
+ }, {
1993
+ key: "request",
1994
+ value: (function () {
1995
+ var _request = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(endpoint) {
1996
+ var options,
1997
+ token,
1998
+ baseUrl,
1999
+ response,
2000
+ error,
2001
+ text,
2002
+ _args3 = arguments;
2003
+ return _regenerator().w(function (_context3) {
2004
+ while (1) switch (_context3.n) {
2005
+ case 0:
2006
+ options = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : {};
2007
+ _context3.n = 1;
2008
+ return this.getAccessToken();
2009
+ case 1:
2010
+ token = _context3.v;
2011
+ baseUrl = 'https://sheets.googleapis.com/v4/spreadsheets';
2012
+ _context3.n = 2;
2013
+ return fetch("".concat(baseUrl, "/").concat(this.spreadsheetId).concat(endpoint), _objectSpread2(_objectSpread2({}, options), {}, {
2014
+ headers: _objectSpread2({
2015
+ 'Authorization': "Bearer ".concat(token),
2016
+ 'Content-Type': 'application/json'
2017
+ }, options.headers)
2018
+ }));
2019
+ case 2:
2020
+ response = _context3.v;
2021
+ if (response.ok) {
2022
+ _context3.n = 4;
2023
+ break;
2024
+ }
2025
+ _context3.n = 3;
2026
+ return response.text();
2027
+ case 3:
2028
+ error = _context3.v;
2029
+ throw new Error("Sheets API error (".concat(response.status, "): ").concat(error));
2030
+ case 4:
2031
+ _context3.n = 5;
2032
+ return response.text();
2033
+ case 5:
2034
+ text = _context3.v;
2035
+ return _context3.a(2, text ? JSON.parse(text) : null);
2036
+ }
2037
+ }, _callee3, this);
2038
+ }));
2039
+ function request(_x4) {
2040
+ return _request.apply(this, arguments);
2041
+ }
2042
+ return request;
2043
+ }()
2044
+ /**
2045
+ * Append row to sheet
2046
+ */
2047
+ )
2048
+ }, {
2049
+ key: "appendRow",
2050
+ value: (function () {
2051
+ var _appendRow = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(values) {
2052
+ var sheetName,
2053
+ range,
2054
+ _args4 = arguments;
2055
+ return _regenerator().w(function (_context4) {
2056
+ while (1) switch (_context4.n) {
2057
+ case 0:
2058
+ sheetName = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : null;
2059
+ range = "".concat(sheetName || this.sheetName, "!A:Z");
2060
+ return _context4.a(2, this.request("/values/".concat(encodeURIComponent(range), ":append"), {
2061
+ method: 'POST',
2062
+ body: JSON.stringify({
2063
+ values: [values],
2064
+ majorDimension: 'ROWS'
2065
+ }) + '?valueInputOption=RAW&insertDataOption=INSERT_ROWS'
2066
+ }));
2067
+ }
2068
+ }, _callee4, this);
2069
+ }));
2070
+ function appendRow(_x5) {
2071
+ return _appendRow.apply(this, arguments);
2072
+ }
2073
+ return appendRow;
2074
+ }()
2075
+ /**
2076
+ * Get sheet values
2077
+ */
2078
+ )
2079
+ }, {
2080
+ key: "getValues",
2081
+ value: (function () {
2082
+ var _getValues = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(range) {
2083
+ return _regenerator().w(function (_context5) {
2084
+ while (1) switch (_context5.n) {
2085
+ case 0:
2086
+ return _context5.a(2, this.request("/values/".concat(encodeURIComponent(range))));
2087
+ }
2088
+ }, _callee5, this);
2089
+ }));
2090
+ function getValues(_x6) {
2091
+ return _getValues.apply(this, arguments);
2092
+ }
2093
+ return getValues;
2094
+ }()
2095
+ /**
2096
+ * Update specific cell/range
2097
+ */
2098
+ )
2099
+ }, {
2100
+ key: "updateValues",
2101
+ value: (function () {
2102
+ var _updateValues = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(range, values) {
2103
+ return _regenerator().w(function (_context6) {
2104
+ while (1) switch (_context6.n) {
2105
+ case 0:
2106
+ return _context6.a(2, this.request("/values/".concat(encodeURIComponent(range), "?valueInputOption=RAW"), {
2107
+ method: 'PUT',
2108
+ body: JSON.stringify({
2109
+ values: values,
2110
+ majorDimension: 'ROWS'
2111
+ })
2112
+ }));
2113
+ }
2114
+ }, _callee6, this);
2115
+ }));
2116
+ function updateValues(_x7, _x8) {
2117
+ return _updateValues.apply(this, arguments);
2118
+ }
2119
+ return updateValues;
2120
+ }()
2121
+ /**
2122
+ * Check if headers exist, create if not
2123
+ */
2124
+ )
2125
+ }, {
2126
+ key: "ensureHeaders",
2127
+ value: (function () {
2128
+ var _ensureHeaders = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(headers) {
2129
+ var existing, _t2;
2130
+ return _regenerator().w(function (_context7) {
2131
+ while (1) switch (_context7.p = _context7.n) {
2132
+ case 0:
2133
+ _context7.p = 0;
2134
+ _context7.n = 1;
2135
+ return this.getValues("".concat(this.sheetName, "!1:1"));
2136
+ case 1:
2137
+ existing = _context7.v;
2138
+ if (!(!existing.values || existing.values.length === 0)) {
2139
+ _context7.n = 3;
2140
+ break;
2141
+ }
2142
+ _context7.n = 2;
2143
+ return this.updateValues("".concat(this.sheetName, "!A1"), [headers]);
2144
+ case 2:
2145
+ return _context7.a(2, {
2146
+ created: true
2147
+ });
2148
+ case 3:
2149
+ return _context7.a(2, {
2150
+ created: false,
2151
+ existing: existing.values[0]
2152
+ });
2153
+ case 4:
2154
+ _context7.p = 4;
2155
+ _context7.v;
2156
+ _context7.p = 5;
2157
+ _context7.n = 6;
2158
+ return this.updateValues("".concat(this.sheetName, "!A1"), [headers]);
2159
+ case 6:
2160
+ return _context7.a(2, {
2161
+ created: true
2162
+ });
2163
+ case 7:
2164
+ _context7.p = 7;
2165
+ _t2 = _context7.v;
2166
+ throw new Error("Failed to set up headers: ".concat(_t2.message));
2167
+ case 8:
2168
+ return _context7.a(2);
2169
+ }
2170
+ }, _callee7, this, [[5, 7], [0, 4]]);
2171
+ }));
2172
+ function ensureHeaders(_x9) {
2173
+ return _ensureHeaders.apply(this, arguments);
2174
+ }
2175
+ return ensureHeaders;
2176
+ }()
2177
+ /**
2178
+ * Find row by feedback ID
2179
+ */
2180
+ )
2181
+ }, {
2182
+ key: "findRowByFeedbackId",
2183
+ value: (function () {
2184
+ var _findRowByFeedbackId = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8(feedbackId) {
2185
+ var idColumn,
2186
+ values,
2187
+ rowIndex,
2188
+ _args8 = arguments;
2189
+ return _regenerator().w(function (_context8) {
2190
+ while (1) switch (_context8.n) {
2191
+ case 0:
2192
+ idColumn = _args8.length > 1 && _args8[1] !== undefined ? _args8[1] : 'B';
2193
+ _context8.n = 1;
2194
+ return this.getValues("".concat(this.sheetName, "!").concat(idColumn, ":").concat(idColumn));
2195
+ case 1:
2196
+ values = _context8.v;
2197
+ if (values.values) {
2198
+ _context8.n = 2;
2199
+ break;
2200
+ }
2201
+ return _context8.a(2, null);
2202
+ case 2:
2203
+ rowIndex = values.values.findIndex(function (row) {
2204
+ return row[0] === feedbackId;
2205
+ });
2206
+ return _context8.a(2, rowIndex >= 0 ? rowIndex + 1 : null);
2207
+ }
2208
+ }, _callee8, this);
2209
+ }));
2210
+ function findRowByFeedbackId(_x0) {
2211
+ return _findRowByFeedbackId.apply(this, arguments);
2212
+ }
2213
+ return findRowByFeedbackId;
2214
+ }()
2215
+ /**
2216
+ * Update feedback status in sheet
2217
+ */
2218
+ )
2219
+ }, {
2220
+ key: "updateStatus",
2221
+ value: (function () {
2222
+ var _updateStatus = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9(feedbackId, newStatus) {
2223
+ var statusColumn,
2224
+ rowNumber,
2225
+ _args9 = arguments;
2226
+ return _regenerator().w(function (_context9) {
2227
+ while (1) switch (_context9.n) {
2228
+ case 0:
2229
+ statusColumn = _args9.length > 2 && _args9[2] !== undefined ? _args9[2] : 'E';
2230
+ _context9.n = 1;
2231
+ return this.findRowByFeedbackId(feedbackId);
2232
+ case 1:
2233
+ rowNumber = _context9.v;
2234
+ if (rowNumber) {
2235
+ _context9.n = 2;
2236
+ break;
2237
+ }
2238
+ throw new Error("Feedback ".concat(feedbackId, " not found in sheet"));
2239
+ case 2:
2240
+ _context9.n = 3;
2241
+ return this.updateValues("".concat(this.sheetName, "!").concat(statusColumn).concat(rowNumber), [[newStatus]]);
2242
+ case 3:
2243
+ return _context9.a(2, {
2244
+ success: true,
2245
+ row: rowNumber
2246
+ });
2247
+ }
2248
+ }, _callee9, this);
2249
+ }));
2250
+ function updateStatus(_x1, _x10) {
2251
+ return _updateStatus.apply(this, arguments);
2252
+ }
2253
+ return updateStatus;
2254
+ }())
2255
+ }]);
2256
+ }(); // ============================================
2257
+ // OAUTH CLIENT (User Authentication)
2258
+ // ============================================
2259
+ var SheetsOAuthClient = /*#__PURE__*/function (_SheetsClient) {
2260
+ function SheetsOAuthClient(config) {
2261
+ var _this;
2262
+ _classCallCheck(this, SheetsOAuthClient);
2263
+ _this = _callSuper(this, SheetsOAuthClient, [{
2264
+ spreadsheetId: config.spreadsheetId,
2265
+ sheetName: config.sheetName,
2266
+ credentials: {
2267
+ client_email: '',
2268
+ private_key: ''
2269
+ }
2270
+ }]);
2271
+ _this.clientId = config.clientId || process.env.GOOGLE_CLIENT_ID;
2272
+ _this.clientSecret = config.clientSecret || process.env.GOOGLE_CLIENT_SECRET;
2273
+ _this.redirectUri = config.redirectUri || process.env.GOOGLE_REDIRECT_URI;
2274
+
2275
+ // Token storage (user must provide storage mechanism)
2276
+ _this.getStoredTokens = config.getStoredTokens;
2277
+ _this.saveTokens = config.saveTokens;
2278
+ if (!_this.clientId || !_this.clientSecret) {
2279
+ throw new Error('OAuth configuration missing. Required: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET');
2280
+ }
2281
+ return _this;
2282
+ }
2283
+
2284
+ /**
2285
+ * Get OAuth authorization URL
2286
+ */
2287
+ _inherits(SheetsOAuthClient, _SheetsClient);
2288
+ return _createClass(SheetsOAuthClient, [{
2289
+ key: "getAuthUrl",
2290
+ value: function getAuthUrl() {
2291
+ var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
2292
+ var params = new URLSearchParams({
2293
+ client_id: this.clientId,
2294
+ redirect_uri: this.redirectUri,
2295
+ response_type: 'code',
2296
+ scope: 'https://www.googleapis.com/auth/spreadsheets',
2297
+ access_type: 'offline',
2298
+ prompt: 'consent',
2299
+ state: state
2300
+ });
2301
+ return "https://accounts.google.com/o/oauth2/v2/auth?".concat(params);
2302
+ }
2303
+
2304
+ /**
2305
+ * Exchange authorization code for tokens
2306
+ */
2307
+ }, {
2308
+ key: "exchangeCode",
2309
+ value: (function () {
2310
+ var _exchangeCode = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0(code) {
2311
+ var response, error, tokens;
2312
+ return _regenerator().w(function (_context0) {
2313
+ while (1) switch (_context0.n) {
2314
+ case 0:
2315
+ _context0.n = 1;
2316
+ return fetch('https://oauth2.googleapis.com/token', {
2317
+ method: 'POST',
2318
+ headers: {
2319
+ 'Content-Type': 'application/x-www-form-urlencoded'
2320
+ },
2321
+ body: new URLSearchParams({
2322
+ client_id: this.clientId,
2323
+ client_secret: this.clientSecret,
2324
+ code: code,
2325
+ grant_type: 'authorization_code',
2326
+ redirect_uri: this.redirectUri
2327
+ })
2328
+ });
2329
+ case 1:
2330
+ response = _context0.v;
2331
+ if (response.ok) {
2332
+ _context0.n = 3;
2333
+ break;
2334
+ }
2335
+ _context0.n = 2;
2336
+ return response.text();
2337
+ case 2:
2338
+ error = _context0.v;
2339
+ throw new Error("Failed to exchange code: ".concat(error));
2340
+ case 3:
2341
+ _context0.n = 4;
2342
+ return response.json();
2343
+ case 4:
2344
+ tokens = _context0.v;
2345
+ if (!this.saveTokens) {
2346
+ _context0.n = 5;
2347
+ break;
2348
+ }
2349
+ _context0.n = 5;
2350
+ return this.saveTokens({
2351
+ access_token: tokens.access_token,
2352
+ refresh_token: tokens.refresh_token,
2353
+ expiry: Date.now() + tokens.expires_in * 1000
2354
+ });
2355
+ case 5:
2356
+ return _context0.a(2, tokens);
2357
+ }
2358
+ }, _callee0, this);
2359
+ }));
2360
+ function exchangeCode(_x11) {
2361
+ return _exchangeCode.apply(this, arguments);
2362
+ }
2363
+ return exchangeCode;
2364
+ }()
2365
+ /**
2366
+ * Refresh access token using refresh token
2367
+ */
2368
+ )
2369
+ }, {
2370
+ key: "refreshAccessToken",
2371
+ value: (function () {
2372
+ var _refreshAccessToken = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1(refreshToken) {
2373
+ var response, error, data, stored;
2374
+ return _regenerator().w(function (_context1) {
2375
+ while (1) switch (_context1.n) {
2376
+ case 0:
2377
+ _context1.n = 1;
2378
+ return fetch('https://oauth2.googleapis.com/token', {
2379
+ method: 'POST',
2380
+ headers: {
2381
+ 'Content-Type': 'application/x-www-form-urlencoded'
2382
+ },
2383
+ body: new URLSearchParams({
2384
+ client_id: this.clientId,
2385
+ client_secret: this.clientSecret,
2386
+ refresh_token: refreshToken,
2387
+ grant_type: 'refresh_token'
2388
+ })
2389
+ });
2390
+ case 1:
2391
+ response = _context1.v;
2392
+ if (response.ok) {
2393
+ _context1.n = 3;
2394
+ break;
2395
+ }
2396
+ _context1.n = 2;
2397
+ return response.text();
2398
+ case 2:
2399
+ error = _context1.v;
2400
+ throw new Error("Failed to refresh token: ".concat(error));
2401
+ case 3:
2402
+ _context1.n = 4;
2403
+ return response.json();
2404
+ case 4:
2405
+ data = _context1.v;
2406
+ if (!this.saveTokens) {
2407
+ _context1.n = 6;
2408
+ break;
2409
+ }
2410
+ _context1.n = 5;
2411
+ return this.getStoredTokens();
2412
+ case 5:
2413
+ stored = _context1.v;
2414
+ _context1.n = 6;
2415
+ return this.saveTokens({
2416
+ access_token: data.access_token,
2417
+ refresh_token: stored.refresh_token,
2418
+ // Keep existing refresh token
2419
+ expiry: Date.now() + data.expires_in * 1000
2420
+ });
2421
+ case 6:
2422
+ return _context1.a(2, data.access_token);
2423
+ }
2424
+ }, _callee1, this);
2425
+ }));
2426
+ function refreshAccessToken(_x12) {
2427
+ return _refreshAccessToken.apply(this, arguments);
2428
+ }
2429
+ return refreshAccessToken;
2430
+ }()
2431
+ /**
2432
+ * Override getAccessToken to use OAuth
2433
+ */
2434
+ )
2435
+ }, {
2436
+ key: "getAccessToken",
2437
+ value: (function () {
2438
+ var _getAccessToken2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10() {
2439
+ var stored;
2440
+ return _regenerator().w(function (_context10) {
2441
+ while (1) switch (_context10.n) {
2442
+ case 0:
2443
+ if (this.getStoredTokens) {
2444
+ _context10.n = 1;
2445
+ break;
2446
+ }
2447
+ throw new Error('Token storage not configured. Provide getStoredTokens and saveTokens functions.');
2448
+ case 1:
2449
+ _context10.n = 2;
2450
+ return this.getStoredTokens();
2451
+ case 2:
2452
+ stored = _context10.v;
2453
+ if (!(!stored || !stored.refresh_token)) {
2454
+ _context10.n = 3;
2455
+ break;
2456
+ }
2457
+ throw new Error('Not authenticated. User needs to complete OAuth flow.');
2458
+ case 3:
2459
+ if (!(stored.access_token && stored.expiry && Date.now() < stored.expiry - 60000)) {
2460
+ _context10.n = 4;
2461
+ break;
2462
+ }
2463
+ return _context10.a(2, stored.access_token);
2464
+ case 4:
2465
+ return _context10.a(2, this.refreshAccessToken(stored.refresh_token));
2466
+ }
2467
+ }, _callee10, this);
2468
+ }));
2469
+ function getAccessToken() {
2470
+ return _getAccessToken2.apply(this, arguments);
2471
+ }
2472
+ return getAccessToken;
2473
+ }())
2474
+ }]);
2475
+ }(SheetsClient); // ============================================
2476
+ // REQUEST HANDLERS
2477
+ // ============================================
2478
+ /**
2479
+ * Create Sheets handler with configuration
2480
+ */
2481
+ function createSheetsHandler() {
2482
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2483
+ var handler = /*#__PURE__*/function () {
2484
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee11(req, res) {
2485
+ var body, _body$action, action, feedbackData, feedbackId, status, row, ClientClass, client, result, headers, errorResponse, _t3, _t4;
2486
+ return _regenerator().w(function (_context11) {
2487
+ while (1) switch (_context11.p = _context11.n) {
2488
+ case 0:
2489
+ _context11.p = 0;
2490
+ body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
2491
+ _body$action = body.action, action = _body$action === void 0 ? 'append' : _body$action, feedbackData = body.feedbackData, feedbackId = body.feedbackId, status = body.status, row = body.row; // Choose client type based on config
2492
+ ClientClass = config.oauth ? SheetsOAuthClient : SheetsClient;
2493
+ client = new ClientClass(config);
2494
+ _t3 = action;
2495
+ _context11.n = _t3 === 'append' ? 1 : _t3 === 'updateStatus' ? 3 : _t3 === 'updateRow' ? 5 : _t3 === 'getHeaders' ? 7 : _t3 === 'ensureHeaders' ? 8 : _t3 === 'getAuthUrl' ? 10 : _t3 === 'exchangeCode' ? 12 : 15;
2496
+ break;
2497
+ case 1:
2498
+ _context11.n = 2;
2499
+ return handleAppend(client, feedbackData, config);
2500
+ case 2:
2501
+ result = _context11.v;
2502
+ return _context11.a(3, 16);
2503
+ case 3:
2504
+ _context11.n = 4;
2505
+ return handleUpdateStatus(client, feedbackId, status, config);
2506
+ case 4:
2507
+ result = _context11.v;
2508
+ return _context11.a(3, 16);
2509
+ case 5:
2510
+ _context11.n = 6;
2511
+ return handleUpdateRow(client, row, feedbackData, config);
2512
+ case 6:
2513
+ result = _context11.v;
2514
+ return _context11.a(3, 16);
2515
+ case 7:
2516
+ result = {
2517
+ headers: getSheetHeaders(config)
2518
+ };
2519
+ return _context11.a(3, 16);
2520
+ case 8:
2521
+ headers = getSheetHeaders(config);
2522
+ _context11.n = 9;
2523
+ return client.ensureHeaders(headers);
2524
+ case 9:
2525
+ result = _context11.v;
2526
+ return _context11.a(3, 16);
2527
+ case 10:
2528
+ if (client instanceof SheetsOAuthClient) {
2529
+ _context11.n = 11;
2530
+ break;
2531
+ }
2532
+ throw new Error('OAuth not configured');
2533
+ case 11:
2534
+ result = {
2535
+ url: client.getAuthUrl(body.state)
2536
+ };
2537
+ return _context11.a(3, 16);
2538
+ case 12:
2539
+ if (client instanceof SheetsOAuthClient) {
2540
+ _context11.n = 13;
2541
+ break;
2542
+ }
2543
+ throw new Error('OAuth not configured');
2544
+ case 13:
2545
+ _context11.n = 14;
2546
+ return client.exchangeCode(body.code);
2547
+ case 14:
2548
+ result = _context11.v;
2549
+ return _context11.a(3, 16);
2550
+ case 15:
2551
+ throw new Error("Unknown action: ".concat(action));
2552
+ case 16:
2553
+ if (!(res !== null && res !== void 0 && res.json)) {
2554
+ _context11.n = 17;
2555
+ break;
2556
+ }
2557
+ res.status(200).json(result);
2558
+ _context11.n = 18;
2559
+ break;
2560
+ case 17:
2561
+ return _context11.a(2, new Response(JSON.stringify(result), {
2562
+ status: 200,
2563
+ headers: {
2564
+ 'Content-Type': 'application/json'
2565
+ }
2566
+ }));
2567
+ case 18:
2568
+ _context11.n = 21;
2569
+ break;
2570
+ case 19:
2571
+ _context11.p = 19;
2572
+ _t4 = _context11.v;
2573
+ errorResponse = {
2574
+ success: false,
2575
+ error: _t4.message
2576
+ };
2577
+ if (!(res !== null && res !== void 0 && res.json)) {
2578
+ _context11.n = 20;
2579
+ break;
2580
+ }
2581
+ res.status(500).json(errorResponse);
2582
+ _context11.n = 21;
2583
+ break;
2584
+ case 20:
2585
+ return _context11.a(2, new Response(JSON.stringify(errorResponse), {
2586
+ status: 500,
2587
+ headers: {
2588
+ 'Content-Type': 'application/json'
2589
+ }
2590
+ }));
2591
+ case 21:
2592
+ return _context11.a(2);
2593
+ }
2594
+ }, _callee11, null, [[0, 19]]);
2595
+ }));
2596
+ return function handler(_x13, _x14) {
2597
+ return _ref.apply(this, arguments);
2598
+ };
2599
+ }();
2600
+ return handler;
2601
+ }
2602
+
2603
+ /**
2604
+ * Handle append row
2605
+ */
2606
+ function handleAppend(_x15, _x16, _x17) {
2607
+ return _handleAppend.apply(this, arguments);
2608
+ }
2609
+ /**
2610
+ * Handle status update
2611
+ */
2612
+ function _handleAppend() {
2613
+ _handleAppend = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee14(client, feedbackData, config) {
2614
+ var _result$updates, _result$updates2;
2615
+ var headers, row, result;
2616
+ return _regenerator().w(function (_context14) {
2617
+ while (1) switch (_context14.n) {
2618
+ case 0:
2619
+ // Ensure headers exist
2620
+ headers = getSheetHeaders(config);
2621
+ _context14.n = 1;
2622
+ return client.ensureHeaders(headers);
2623
+ case 1:
2624
+ // Transform feedback to row
2625
+ row = feedbackToSheetRow(feedbackData, config); // Append row
2626
+ _context14.n = 2;
2627
+ return client.appendRow(row);
2628
+ case 2:
2629
+ result = _context14.v;
2630
+ return _context14.a(2, {
2631
+ success: true,
2632
+ updatedRange: result === null || result === void 0 || (_result$updates = result.updates) === null || _result$updates === void 0 ? void 0 : _result$updates.updatedRange,
2633
+ rowNumber: result === null || result === void 0 || (_result$updates2 = result.updates) === null || _result$updates2 === void 0 || (_result$updates2 = _result$updates2.updatedRange) === null || _result$updates2 === void 0 || (_result$updates2 = _result$updates2.match(/:(\d+)$/)) === null || _result$updates2 === void 0 ? void 0 : _result$updates2[1]
2634
+ });
2635
+ }
2636
+ }, _callee14);
2637
+ }));
2638
+ return _handleAppend.apply(this, arguments);
2639
+ }
2640
+ function handleUpdateStatus(_x18, _x19, _x20, _x21) {
2641
+ return _handleUpdateStatus.apply(this, arguments);
2642
+ }
2643
+ /**
2644
+ * Handle row update
2645
+ */
2646
+ function _handleUpdateStatus() {
2647
+ _handleUpdateStatus = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee15(client, feedbackId, status, config) {
2648
+ var _mergeSheetColumns, order, statusIndex, statusColumn, result;
2649
+ return _regenerator().w(function (_context15) {
2650
+ while (1) switch (_context15.n) {
2651
+ case 0:
2652
+ // Find status column
2653
+ _mergeSheetColumns = mergeSheetColumns(config.columns, config.columnOrder), _mergeSheetColumns.columns, order = _mergeSheetColumns.order;
2654
+ statusIndex = order.indexOf('status');
2655
+ statusColumn = String.fromCharCode(65 + statusIndex); // A, B, C...
2656
+ _context15.n = 1;
2657
+ return client.updateStatus(feedbackId, status, statusColumn);
2658
+ case 1:
2659
+ result = _context15.v;
2660
+ return _context15.a(2, result);
2661
+ }
2662
+ }, _callee15);
2663
+ }));
2664
+ return _handleUpdateStatus.apply(this, arguments);
2665
+ }
2666
+ function handleUpdateRow(_x22, _x23, _x24, _x25) {
2667
+ return _handleUpdateRow.apply(this, arguments);
2668
+ } // ============================================
2669
+ // FRAMEWORK-SPECIFIC EXPORTS
2670
+ // ============================================
2671
+ /**
2672
+ * Next.js App Router handler
2673
+ * Returns a function that can be directly exported as POST
2674
+ */
2675
+ function _handleUpdateRow() {
2676
+ _handleUpdateRow = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee16(client, rowNumber, feedbackData, config) {
2677
+ var row, range;
2678
+ return _regenerator().w(function (_context16) {
2679
+ while (1) switch (_context16.n) {
2680
+ case 0:
2681
+ row = feedbackToSheetRow(feedbackData, config);
2682
+ range = "".concat(config.sheetName || 'Feedback', "!A").concat(rowNumber);
2683
+ _context16.n = 1;
2684
+ return client.updateValues(range, [row]);
2685
+ case 1:
2686
+ return _context16.a(2, {
2687
+ success: true,
2688
+ row: rowNumber
2689
+ });
2690
+ }
2691
+ }, _callee16);
2692
+ }));
2693
+ return _handleUpdateRow.apply(this, arguments);
2694
+ }
2695
+ function createNextAppHandler() {
2696
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2697
+ var handler = createSheetsHandler(config);
2698
+ return /*#__PURE__*/function () {
2699
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee12(request) {
2700
+ var body;
2701
+ return _regenerator().w(function (_context12) {
2702
+ while (1) switch (_context12.n) {
2703
+ case 0:
2704
+ _context12.n = 1;
2705
+ return request.json();
2706
+ case 1:
2707
+ body = _context12.v;
2708
+ return _context12.a(2, handler({
2709
+ body: body
2710
+ }, null));
2711
+ }
2712
+ }, _callee12);
2713
+ }));
2714
+ return function (_x26) {
2715
+ return _ref2.apply(this, arguments);
2716
+ };
2717
+ }();
2718
+ }
2719
+
2720
+ /**
2721
+ * Next.js Pages Router handler
2722
+ */
2723
+ function createNextPagesHandler() {
2724
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2725
+ return createSheetsHandler(config);
2726
+ }
2727
+
2728
+ /**
2729
+ * Express middleware
2730
+ */
2731
+ function createExpressMiddleware() {
2732
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2733
+ var handler = createSheetsHandler(config);
2734
+ return /*#__PURE__*/function () {
2735
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee13(req, res, next) {
2736
+ var _t5;
2737
+ return _regenerator().w(function (_context13) {
2738
+ while (1) switch (_context13.p = _context13.n) {
2739
+ case 0:
2740
+ _context13.p = 0;
2741
+ _context13.n = 1;
2742
+ return handler(req, res);
2743
+ case 1:
2744
+ _context13.n = 3;
2745
+ break;
2746
+ case 2:
2747
+ _context13.p = 2;
2748
+ _t5 = _context13.v;
2749
+ next(_t5);
2750
+ case 3:
2751
+ return _context13.a(2);
2752
+ }
2753
+ }, _callee13, null, [[0, 2]]);
2754
+ }));
2755
+ return function (_x27, _x28, _x29) {
2756
+ return _ref3.apply(this, arguments);
2757
+ };
2758
+ }();
2759
+ }
2760
+
2761
+ // ============================================
2762
+ // GOOGLE APPS SCRIPT TEMPLATE
2763
+ // ============================================
2764
+
2765
+ /**
2766
+ * Returns the Google Apps Script code that users paste into their sheet
2767
+ */
2768
+ function getAppsScriptTemplate() {
2769
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2770
+ var headers = getSheetHeaders(config);
2771
+ return "\n/**\n * React Visual Feedback - Google Apps Script Handler\n *\n * Setup:\n * 1. Open your Google Sheet\n * 2. Extensions > Apps Script\n * 3. Paste this code\n * 4. Deploy > New deployment > Web app\n * 5. Execute as: Me, Who has access: Anyone\n * 6. Copy the URL and use in your React app\n */\n\n// Sheet configuration\nconst SHEET_NAME = '".concat(config.sheetName || 'Feedback', "';\nconst HEADERS = ").concat(JSON.stringify(headers), ";\n\n/**\n * Handle POST requests\n */\nfunction doPost(e) {\n try {\n const data = JSON.parse(e.postData.contents);\n const action = data.action || 'append';\n\n let result;\n\n switch (action) {\n case 'append':\n result = appendFeedback(data.feedbackData);\n break;\n case 'updateStatus':\n result = updateStatus(data.feedbackId, data.status);\n break;\n case 'getRows':\n result = getRows(data.limit || 100);\n break;\n default:\n throw new Error('Unknown action: ' + action);\n }\n\n return ContentService\n .createTextOutput(JSON.stringify(result))\n .setMimeType(ContentService.MimeType.JSON);\n\n } catch (error) {\n return ContentService\n .createTextOutput(JSON.stringify({ success: false, error: error.message }))\n .setMimeType(ContentService.MimeType.JSON);\n }\n}\n\n/**\n * Handle GET requests (for testing)\n */\nfunction doGet(e) {\n return ContentService\n .createTextOutput(JSON.stringify({ status: 'ok', message: 'Feedback API ready' }))\n .setMimeType(ContentService.MimeType.JSON);\n}\n\n/**\n * Append feedback to sheet\n */\nfunction appendFeedback(feedbackData) {\n const sheet = getOrCreateSheet();\n\n const row = [\n new Date().toISOString(), // Timestamp\n feedbackData.id || '', // ID\n feedbackData.feedback || '', // Feedback\n feedbackData.type || 'bug', // Type\n feedbackData.status || 'new', // Status\n feedbackData.userName || 'Anonymous', // User Name\n feedbackData.userEmail || '', // User Email\n feedbackData.url || '', // Page URL\n feedbackData.viewport ? feedbackData.viewport.width + 'x' + feedbackData.viewport.height : '', // Viewport\n feedbackData.screenshot ? 'Yes' : 'No', // Screenshot\n feedbackData.video ? 'Yes' : 'No', // Video\n feedbackData.jiraKey || '' // Jira Key\n ];\n\n sheet.appendRow(row);\n\n return {\n success: true,\n row: sheet.getLastRow()\n };\n}\n\n/**\n * Update feedback status\n */\nfunction updateStatus(feedbackId, newStatus) {\n const sheet = getOrCreateSheet();\n const data = sheet.getDataRange().getValues();\n\n // Find row with matching ID (column B, index 1)\n for (let i = 1; i < data.length; i++) {\n if (data[i][1] === feedbackId) {\n // Update status (column E, index 4)\n sheet.getRange(i + 1, 5).setValue(newStatus);\n return { success: true, row: i + 1 };\n }\n }\n\n return { success: false, error: 'Feedback not found' };\n}\n\n/**\n * Get rows from sheet\n */\nfunction getRows(limit) {\n const sheet = getOrCreateSheet();\n const data = sheet.getDataRange().getValues();\n\n const rows = data.slice(1, limit + 1).map((row, index) => ({\n rowNumber: index + 2,\n timestamp: row[0],\n id: row[1],\n feedback: row[2],\n type: row[3],\n status: row[4],\n userName: row[5],\n userEmail: row[6],\n url: row[7],\n viewport: row[8],\n hasScreenshot: row[9] === 'Yes',\n hasVideo: row[10] === 'Yes',\n jiraKey: row[11]\n }));\n\n return { success: true, rows };\n}\n\n/**\n * Get or create the feedback sheet\n */\nfunction getOrCreateSheet() {\n const ss = SpreadsheetApp.getActiveSpreadsheet();\n let sheet = ss.getSheetByName(SHEET_NAME);\n\n if (!sheet) {\n sheet = ss.insertSheet(SHEET_NAME);\n sheet.appendRow(HEADERS);\n\n // Format headers\n const headerRange = sheet.getRange(1, 1, 1, HEADERS.length);\n headerRange.setFontWeight('bold');\n headerRange.setBackground('#4285f4');\n headerRange.setFontColor('#ffffff');\n }\n\n return sheet;\n}\n\n/**\n * Update Jira key for a feedback item\n */\nfunction updateJiraKey(feedbackId, jiraKey) {\n const sheet = getOrCreateSheet();\n const data = sheet.getDataRange().getValues();\n\n for (let i = 1; i < data.length; i++) {\n if (data[i][1] === feedbackId) {\n // Update Jira key (column L, index 11)\n sheet.getRange(i + 1, 12).setValue(jiraKey);\n return { success: true, row: i + 1 };\n }\n }\n\n return { success: false, error: 'Feedback not found' };\n}\n").trim();
2772
+ }
2773
+
2774
+ // ============================================
2775
+ // ZAPIER / WEBHOOK FORMATTERS
2776
+ // ============================================
2777
+
2778
+ /**
2779
+ * Format feedback for Zapier webhook
2780
+ */
2781
+ function formatForZapier(feedbackData) {
2782
+ var _feedbackData$element, _feedbackData$element2;
2783
+ return {
2784
+ timestamp: new Date().toISOString(),
2785
+ id: feedbackData.id,
2786
+ feedback: feedbackData.feedback,
2787
+ type: feedbackData.type || 'bug',
2788
+ status: feedbackData.status || 'new',
2789
+ user_name: feedbackData.userName || 'Anonymous',
2790
+ user_email: feedbackData.userEmail || '',
2791
+ page_url: feedbackData.url || '',
2792
+ viewport: feedbackData.viewport ? "".concat(feedbackData.viewport.width, "x").concat(feedbackData.viewport.height) : '',
2793
+ has_screenshot: !!feedbackData.screenshot,
2794
+ has_video: !!feedbackData.video,
2795
+ element_selector: ((_feedbackData$element = feedbackData.elementInfo) === null || _feedbackData$element === void 0 ? void 0 : _feedbackData$element.selector) || '',
2796
+ component_name: (((_feedbackData$element2 = feedbackData.elementInfo) === null || _feedbackData$element2 === void 0 ? void 0 : _feedbackData$element2.componentStack) || [])[0] || ''
2797
+ };
2798
+ }
2799
+
2800
+ var sheets = /*#__PURE__*/Object.freeze({
2801
+ __proto__: null,
2802
+ createExpressMiddleware: createExpressMiddleware,
2803
+ createNextAppHandler: createNextAppHandler,
2804
+ createNextPagesHandler: createNextPagesHandler,
2805
+ createSheetsHandler: createSheetsHandler,
2806
+ default: createSheetsHandler,
2807
+ formatForZapier: formatForZapier,
2808
+ getAppsScriptTemplate: getAppsScriptTemplate
2809
+ });
2810
+
2811
+ // ============================================
2812
+ // CONVENIENCE HANDLERS
2813
+ // ============================================
2814
+
2815
+ /**
2816
+ * Create both Jira and Sheets handlers with shared config
2817
+ */
2818
+ function createIntegrationHandlers() {
2819
+ return _createIntegrationHandlers.apply(this, arguments);
2820
+ }
2821
+
2822
+ /**
2823
+ * Create a combined handler that routes to Jira or Sheets based on request
2824
+ */
2825
+ function _createIntegrationHandlers() {
2826
+ _createIntegrationHandlers = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
2827
+ var config,
2828
+ handlers,
2829
+ _yield$import,
2830
+ createJiraHandler,
2831
+ _yield$import2,
2832
+ createSheetsHandler,
2833
+ _args2 = arguments;
2834
+ return _regenerator().w(function (_context2) {
2835
+ while (1) switch (_context2.n) {
2836
+ case 0:
2837
+ config = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : {};
2838
+ handlers = {};
2839
+ if (!config.jira) {
2840
+ _context2.n = 2;
2841
+ break;
2842
+ }
2843
+ _context2.n = 1;
2844
+ return Promise.resolve().then(function () { return jira; });
2845
+ case 1:
2846
+ _yield$import = _context2.v;
2847
+ createJiraHandler = _yield$import["default"];
2848
+ handlers.jira = createJiraHandler(config.jira);
2849
+ case 2:
2850
+ if (!config.sheets) {
2851
+ _context2.n = 4;
2852
+ break;
2853
+ }
2854
+ _context2.n = 3;
2855
+ return Promise.resolve().then(function () { return sheets; });
2856
+ case 3:
2857
+ _yield$import2 = _context2.v;
2858
+ createSheetsHandler = _yield$import2["default"];
2859
+ handlers.sheets = createSheetsHandler(config.sheets);
2860
+ case 4:
2861
+ return _context2.a(2, handlers);
2862
+ }
2863
+ }, _callee2);
2864
+ }));
2865
+ return _createIntegrationHandlers.apply(this, arguments);
2866
+ }
2867
+ function createCombinedHandler() {
2868
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2869
+ var handlers = createIntegrationHandlers(config);
2870
+ return /*#__PURE__*/function () {
2871
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(req, res) {
2872
+ var body, integration, error;
2873
+ return _regenerator().w(function (_context) {
2874
+ while (1) switch (_context.n) {
2875
+ case 0:
2876
+ body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
2877
+ integration = body.integration;
2878
+ if (!(!integration || !handlers[integration])) {
2879
+ _context.n = 2;
2880
+ break;
2881
+ }
2882
+ error = {
2883
+ success: false,
2884
+ error: "Unknown integration: ".concat(integration)
2885
+ };
2886
+ if (!(res !== null && res !== void 0 && res.json)) {
2887
+ _context.n = 1;
2888
+ break;
2889
+ }
2890
+ return _context.a(2, res.status(400).json(error));
2891
+ case 1:
2892
+ return _context.a(2, new Response(JSON.stringify(error), {
2893
+ status: 400
2894
+ }));
2895
+ case 2:
2896
+ return _context.a(2, handlers[integration](req, res));
2897
+ }
2898
+ }, _callee);
2899
+ }));
2900
+ return function (_x, _x2) {
2901
+ return _ref.apply(this, arguments);
2902
+ };
2903
+ }();
2904
+ }
2905
+
2906
+ export { DEFAULT_JIRA_FIELDS, DEFAULT_JIRA_STATUS_MAPPING, DEFAULT_SHEET_COLUMNS, DEFAULT_SHEET_COLUMN_ORDER, INTEGRATION_TYPES, createCombinedHandler, createIntegrationHandlers, createGenericHandler as createJiraGenericHandler, createJiraHandler, createExpressMiddleware$1 as createJiraMiddleware, createNextAppHandler$1 as createJiraNextAppHandler, createNextPagesHandler$1 as createJiraNextPagesHandler, createSheetsHandler, createExpressMiddleware as createSheetsMiddleware, createNextAppHandler as createSheetsNextAppHandler, createNextPagesHandler as createSheetsNextPagesHandler, feedbackToJiraIssue, feedbackToSheetRow, formatForJiraAutomation, formatForZapier$1 as formatJiraForZapier, formatForZapier as formatSheetsForZapier, getAppsScriptTemplate, getSheetHeaders, mapJiraStatusToLocal, mapLocalStatusToJira, mergeJiraFields, mergeSheetColumns };
2907
+ //# sourceMappingURL=index.js.map